DF_Text( aT[ i ][ 1 ], x + 8, 4, x + 130, 24, CL_INK, 1, 0 )
DF_Text( aT[ i ][ 2 ], x + 8, 23, x + 130, 42, CL_MUTE, 2, 0 )
NEXT
RETURN NIL
STATIC FUNCTION PaintCenter()
LOCAL c1, c2, p1, f := oM:aFields[ nFSel ], cK := f[ 3 ], aB, nB, nStep, by, rcy, i, br, lc, aU, cU, x, aA, k, aCh, nTot, lEl, w, cLbl, nCut
IF cK == "tree" .OR. cK == "btn"
Win( 388, 88, 868, 650, iif( cK == "btn", "Árbol de acción para ", "Árbol de decisión para " ) + f[ 2 ], "Se decide según " + LabelOf( RTest() ) + " · gana la primera rama que se cumple" )
aB := RB(); nB := Len( aB ); nStep := iif( nB <= 3, 100, 64 ); br := Branch()
rcy := 150 + ( nB - 1 ) * nStep / 2 + 22
DF_Box( 411, rcy - 18, 541, rcy + 24, RGB( 190, 197, 209 ), RGB( 190, 197, 209 ), 12 )
DF_Box( 408, rcy - 21, 538, rcy + 21, RGB( 15, 23, 42 ), RGB( 15, 23, 42 ), 12 )
DF_Text( LabelOf( RTest() ), 408, rcy - 21, 538, rcy + 21, CL_WHITE, 1, 1 )
FOR k := 0 TO 1
FOR i := 1 TO nB
IF ( k == 1 ) != ( i == br ); LOOP; ENDIF
by := 150 + ( i - 1 ) * nStep; lc := iif( i == br, CL_ACC, CL_EDGE )
x := iif( i == br, 3, 1 )
DF_Line( 538, rcy, 580, rcy, lc, x ); DF_Line( 580, rcy, 580, by + 22, lc, x ); DF_Line( 580, by + 22, 600, by + 22, lc, x ); DF_Line( 720, by + 22, 740, by + 22, lc, x )
DF_Box( 603, by + 3, 723, by + 47, RGB( 203, 210, 222 ), RGB( 203, 210, 222 ), 10 )
DF_Box( 600, by, 720, by + 44, iif( i == br, CL_ACCL, CL_PALE ), lc, 10 )
DF_Text( iif( aB[ i ][ 1 ] == "otherwise", "en otro caso", LTrim( Str( i ) ) + ". " + Sym( aB[ i ][ 1 ] ) + " " + TrimNum( aB[ i ][ 2 ] ) ), 600, by, 720, by + 44, CL_INK, 0, 1 )
DF_Box( 740, by, 840, by + 44, iif( i == br, CL_ACC, CL_PALE ), lc, 10 )
DF_Text( iif( cK == "btn", ActShort( aB[ i ][ 3 ][ 2 ] ), TrimNum( aB[ i ][ 3 ][ 2 ] ) + " " + f[ 5 ] ), 740, by, 840, by + 44, iif( i == br, CL_WHITE, CL_MUTE ), 1, 1 )
NEXT
NEXT
by := 150 + ( nSel - 1 ) * nStep
DF_DotBox( 596, by - 4, 844, by + 48, CL_INK )
DF_Text( "Con " + LabelOf( RTest() ) + " " + TrimNum( oM:hF[ RTest() ] ) + " rama " + LTrim( Str( br ) ) + iif( cK == "btn", ": 1º árbol: " + ActShort( Int( oM:hF[ f[ 1 ] ] ) ) + iif( LinkOf( f[ 1 ] ) > 0, " · 2º enlace: " + LabelOf( aLinks[ LinkOf( f[ 1 ] ) ][ 2 ] ) + " " + LinkAct( aLinks[ LinkOf( f[ 1 ] ) ][ 3 ] ), "" ), ": " + f[ 2 ] + " = " + ValStr( nFSel ) ), 408, 468, 860, 492, CL_ACC, 2, 0 )
DF_Text( "Rama " + LTrim( Str( nSel ) ) + " seleccionada (línea de puntos): edítala en el panel de la derecha.", 408, 494, 860, 518, CL_MUTE, 2, 0 )
ELSEIF cK == "fx"
Win( 388, 88, 868, 650, "Fórmula para " + f[ 2 ], "Campo calculado: se recalcula al cambiar cualquier campo del que depende" )
DF_Text( "EXPRESIÓN (Enter aplica y guarda)", 408, 142, 848, 164, CL_MUTE, 2, 0 )
DF_Box( 408, 168, 848, 206, CL_WHITE, CL_ACC, 8 )
c1 := "Campos: " + FieldNames(); c2 := ""
IF Len( c1 ) > 56
p1 := RAt( ", ", Left( c1, 56 ) ); c2 := SubStr( c1, p1 + 2 ); c1 := Left( c1, p1 )
ENDIF
DF_Text( c1, 408, 213, 856, 229, CL_MUTE, 2, 0 )
IF ! Empty( c2 ); DF_Text( c2, 408, 229, 856, 245, CL_MUTE, 2, 0 ); ENDIF
DF_Text( "Operadores: + - * / ( )", 408, 245, 856, 263, CL_MUTE, 2, 0 )
DF_Box( 408, 272, 848, 376, CL_PALE, CL_EDGE, 12 )
DF_Text( "VALOR ACTUAL", 428, 282, 700, 302, CL_MUTE, 2, 0 )
DF_Text( ValStr( nFSel ), 428, 306, 828, 362, CL_INK, 4, 0 )
aU := oM:UsedBy( f[ 1 ] ); cU := ""
AEval( aU, { | z | cU += iif( Empty( cU ), "", ", " ) + z } )
DF_Text( "Lo usan: " + iif( Empty( cU ), "(ningún campo)", cU ), 408, 390, 856, 412, CL_MUTE, 2, 0 )
ELSE
Win( 388, 88, 868, 650, "Campo de entrada " + f[ 2 ], "Lo escribe quien rellena el formulario (celda blanca a la izquierda)" )
DF_Box( 408, 150, 848, 260, CL_PALE, CL_EDGE, 12 )
DF_Text( "VALOR ACTUAL", 428, 162, 700, 184, CL_MUTE, 2, 0 )
DF_Text( ValStr( nFSel ), 428, 190, 828, 246, CL_INK, 4, 0 )
aU := oM:UsedBy( f[ 1 ] ); cU := ""
AEval( aU, { | z | cU += iif( Empty( cU ), "", ", " ) + z } )
DF_Text( "Lo usan: " + iif( Empty( cU ), "(ningún campo todavía)", cU ), 408, 280, 856, 304, CL_MUTE, 2, 0 )
DF_Text( "Crea una fórmula o un árbol de decisión con + Campo para usarlo.", 408, 308, 856, 332, CL_MUTE, 2, 0 )
ENDIF
// dependency chain
DF_Line( 408, 546, 848, 546, CL_EDGE, 1 )
DF_Text( "DEPENDENCIAS", 408, 554, 700, 574, CL_MUTE, 2, 0 )
aA := Direct( f[ 1 ] )
IF Empty( aA )
DF_Text( "Este campo no depende de otros.", 408, 586, 848, 614, CL_MUTE, 0, 0 )
ELSE
DF_Text( "Calculado con:", 408, 586, 520, 618, CL_MUTE, 2, 0 )
aCh := {}; nCut := 0
FOR EACH k IN aA
cLbl := oM:aFields[ k ][ 2 ]; AAdd( aCh, { cLbl, 22 + 7 * Len( cLbl ), "dep" } )
NEXT
AAdd( aCh, { f[ 2 ], 22 + 7 * Len( f[ 2 ] ), "sel" } )
DO WHILE Len( aCh ) > 2
nTot := 0; AEval( aCh, { | z | nTot += z[ 2 ] + 22 } )
IF nTot <= 320; EXIT; ENDIF
ADel( aCh, 1 ); ASize( aCh, Len( aCh ) - 1 ); nCut++
ENDDO
x := 528
IF nCut > 0; DF_Text( "+" + LTrim( Str( nCut ) ) + " más", 408, 620, 520, 640, CL_MUTE, 2, 0 ); ENDIF
FOR i := 1 TO Len( aCh )
w := aCh[ i ][ 2 ]
IF aCh[ i ][ 3 ] == "sel"
DF_Box( x, 584, x + w, 620, CL_ACC, CL_ACC, 12 ); DF_Text( aCh[ i ][ 1 ], x, 584, x + w, 620, CL_WHITE, 1, 1 )
ELSE
DF_Box( x, 584, x + w, 620, CL_SOFT, RGB( 203, 213, 225 ), 12 ); DF_Text( aCh[ i ][ 1 ], x, 584, x + w, 620, CL_INK, 0, 1 )
ENDIF
IF i < Len( aCh )
IF i == Len( aCh ) - 1
DF_Line( x + w + 3, 602, x + w + 18, 602, CL_MUTE, 2 ); DF_Line( x + w + 13, 597, x + w + 18, 602, CL_MUTE, 2 ); DF_Line( x + w + 13, 607, x + w + 18, 602, CL_MUTE, 2 )
ELSE
DF_Text( "", x + w, 584, x + w + 22, 620, CL_MUTE, 1, 1 )
ENDIF
ENDIF
x += w + 22
NEXT
ENDIF
RETURN NIL
STATIC FUNCTION Direct( cName )
LOCAL k := oM:FormIdx( cName ), r := oM:RuleIdx( cName ), a := {}, x, j, aO := {}
IF k > 0; a := DT_Names( oM:aForms[ k ][ 2 ] ); ELSEIF r > 0; a := { oM:aRules[ r ][ 2 ] }; ENDIF
FOR EACH x IN a
j := oM:FieldIdx( x )
IF j > 0 .AND. AScan( aO, j ) == 0; AAdd( aO, j ); ENDIF
NEXT
ASort( aO )
RETURN aO
STATIC FUNCTION FieldNames()
LOCAL c := "", f, n := 0
FOR EACH f IN oM:aFields
IF f[ 1 ] != oM:aFields[ nFSel ][ 1 ]; c += iif( Empty( c ), "", ", " ) + f[ 1 ]; ENDIF
NEXT
RETURN c
STATIC FUNCTION PaintRight()
LOCAL f := oM:aFields[ nFSel ], aB, cK := f[ 3 ], cU, aU
Card( 884, 72, 1164, 650, "Propiedades", "" )
IF ! lView
Pill( 904, 556, 1020, 588, "Subir campo", nFSel > 1 ); Pill( 1028, 556, 1144, 588, "Bajar campo", nFSel < Len( oM:aFields ) )
ENDIF
IF lView
DF_Text( "Las propiedades del campo se editan en el editor.", 904, 124, 1140, 180, CL_MUTE, 2, 8 )
DF_Text( "Pulsa F11 o haz clic en un campo de la lista para volver.", 904, 190, 1140, 250, CL_MUTE, 2, 8 )
RETURN NIL
ENDIF
DF_Text( "NOMBRE", 904, 124, 1140, 142, CL_MUTE, 2, 0 )
DF_Text( f[ 1 ], 904, 142, 1140, 164, CL_INK, 0, 0 )
DF_Text( "TIPO", 904, 172, 1140, 190, CL_MUTE, 2, 0 )
DF_Text( iif( cK == "in", "Entrada", iif( cK == "fx", "Fórmula", iif( cK == "btn", "Botón (árbol de acciones)", "Árbol de decisión" ) ) ), 904, 190, 1140, 212, CL_INK, 0, 0 )
DF_Line( 904, 226, 1144, 226, CL_EDGE, 1 )
IF cK == "tree" .OR. cK == "btn"
aB := RB()
DF_Text( "RAMA " + LTrim( Str( nSel ) ) + " DE " + LTrim( Str( Len( aB ) ) ), 904, 226, 1060, 246, CL_MUTE, 2, 0 )
DF_Text( "Si " + LabelOf( RTest() ), 904, 250, 1070, 274, CL_INK, 0, 0 )
IF aB[ nSel ][ 1 ] == "otherwise"
Pill( 1076, 246, 1144, 274, "otro caso", .F. )
ELSE
Pill( 1076, 246, 1144, 274, Sym( aB[ nSel ][ 1 ] ), .T. )
ENDIF
DF_Text( "Umbral", 904, 284, 1140, 304, CL_MUTE, 2, 0 )
DF_Box( 904, 310, 1140, 342, CL_PALE, RGB( 203, 213, 225 ), 8 )
DF_Text( iif( cK == "btn", "Acción (0 nada · 1 guardar · 2 limpiar)", "Resultado" + iif( Empty( f[ 5 ] ), "", " (" + f[ 5 ] + ")" ) ), 904, 364, 1140, 384, CL_MUTE, 2, 0 )
DF_Box( 904, 390, 1140, 422, CL_PALE, RGB( 203, 213, 225 ), 8 )
DF_Text( iif( cK == "btn", "Acciones: 0 no hace nada, 1 guarda el pedido, 2 pone las entradas a cero.", iif( f[ 5 ] == "%", "Admite 0 a 100.", "Admite cualquier número." ) + " Umbrales: cualquier número, en orden." ), 904, 432, 1144, 470, CL_MUTE, 2, 8 )
IF cK == "btn"; Pill( 904, 476, 1144, 508, "Pulsar botón (F9)", .T. ); ENDIF
IF cK == "btn" .AND. ! lView
IF LinkOf( f[ 1 ] ) > 0
DF_Text( "Al pulsar -> " + LabelOf( aLinks[ LinkOf( f[ 1 ] ) ][ 2 ] ), 904, 510, 1144, 530, CL_INK, 1, 0 )
Pill( 904, 532, 1020, 554, ShortLab( LinkAct( aLinks[ LinkOf( f[ 1 ] ) ][ 3 ] ), 14 ), .T. )
Pill( 1032, 532, 1144, 554, "Quitar enlace", .F. )
ELSE
DF_Text( "Enlace: arrastra este botón sobre un campo de Entrada", 904, 512, 1144, 552, CL_MUTE, 2, 8 )
ENDIF
ENDIF
Pill( 904, 598, 1012, 630, "+ Rama (F3)", .F. )
Pill( 1032, 598, 1144, 630, "Quitar (F4)", .F. )
ELSE
DF_Text( "ETIQUETA", 904, 226, 1140, 244, CL_MUTE, 2, 0 )
IF ( cK == "in" .OR. cK == "fx" ) .AND. ! lView
DF_Box( 904, 246, 1140, 280, CL_PALE, RGB( 203, 213, 225 ), 8 )
DF_Text( "Enter o salir del cuadro: guarda", 904, 282, 1140, 300, CL_MUTE, 2, 0 )
ENDIF
IF cK == "in" .AND. ! lView
Pill( 904, 598, 1144, 630, "Duplicar campo", .F. )
ENDIF
IF cK == "in"
DF_Text( "DECIMALES (clic para cambiar 0 / 2)", 904, 312, 1140, 332, CL_MUTE, 2, 0 )
DF_Box( 904, 336, 1140, 368, CL_PALE, RGB( 203, 213, 225 ), 8 )
DF_Text( LTrim( Str( f[ 4 ] ) ), 916, 336, 1130, 368, CL_INK, 0, 0 )
ELSE
DF_Text( "DEPENDE DE", 904, 312, 1140, 330, CL_MUTE, 2, 0 )
aU := Direct( f[ 1 ] ); cU := ""
AEval( aU, { | z | cU += iif( Empty( cU ), "", ", " ) + oM:aFields[ z ][ 1 ] } )
DF_Text( cU, 904, 334, 1144, 394, CL_INK, 2, 8 )
ENDIF
ENDIF
RETURN NIL
#pragma BEGINDUMP
#include <windows.h>
#include "hbapi.h"
#include <stdio.h>
static HDC g_dc, g_dc0; static HBITMAP g_bmp; static HGDIOBJ g_obm, g_of; static HFONT g_f[ 5 ]; static int g_W, g_H;
HB_FUNC( DF_MOUSEPOS ){ POINT p; GetCursorPos( &p ); ScreenToClient( ( HWND ) ( ULONG_PTR ) hb_parnint( 1 ), &p ); hb_retnl( p.x * 10000L + p.y ); }
HB_FUNC( DF_BEGIN )
{
HWND hw = ( HWND ) ( UINT_PTR ) hb_parnint( 2 ); RECT cr, r;
HBRUSH hb;
g_dc0 = ( HDC ) ( UINT_PTR ) hb_parnint( 1 );
GetClientRect( hw, &cr ); g_W = cr.right; g_H = cr.bottom;
g_dc = CreateCompatibleDC( g_dc0 ); g_bmp = CreateCompatibleBitmap( g_dc0, g_W, g_H ); g_obm = SelectObject( g_dc, g_bmp );
g_f[ 0 ] = CreateFontW( -16, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY, 0, L"Segoe UI" );
g_f[ 1 ] = CreateFontW( -16, 0, 0, 0, FW_BOLD, 0, 0, 0, DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY, 0, L"Segoe UI" );
g_f[ 2 ] = CreateFontW( -13, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY, 0, L"Segoe UI" );
g_f[ 3 ] = CreateFontW( -22, 0, 0, 0, FW_BOLD, 0, 0, 0, DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY, 0, L"Segoe UI" );
g_f[ 4 ] = CreateFontW( -34, 0, 0, 0, FW_BOLD, 0, 0, 0, DEFAULT_CHARSET, 0, 0, CLEARTYPE_QUALITY, 0, L"Segoe UI" );
g_of = SelectObject( g_dc, g_f[ 0 ] );
r.left = 0; r.top = 0; r.right = g_W; r.bottom = g_H; hb = CreateSolidBrush( ( COLORREF ) hb_parnl( 3 ) ); FillRect( g_dc, &r, hb ); DeleteObject( hb );
SetBkMode( g_dc, TRANSPARENT );
}
HB_FUNC( DF_W ){ hb_retni( g_W ); }
HB_FUNC( DF_END )
{
int i;
SetViewportOrgEx( g_dc, 0, 0, NULL ); BitBlt( g_dc0, 0, 0, g_W, g_H, g_dc, 0, 0, SRCCOPY );
SelectObject( g_dc, g_of ); for( i = 0; i < 5; i++ ) DeleteObject( g_f[ i ] );
SelectObject( g_dc, g_obm ); DeleteObject( g_bmp ); DeleteDC( g_dc );
}
HB_FUNC( DF_CHILDRECT )
{
HWND h = ( HWND ) ( UINT_PTR ) hb_parnint( 1 ); RECT r; POINT p; char b[ 64 ];
if( ! h || ! IsWindow( h ) ) { hb_retc( "" ); return; }
GetWindowRect( h, &r ); p.x = r.left; p.y = r.top; ScreenToClient( GetParent( h ), &p );
sprintf( b, "%ld,%ld,%ld,%ld", ( long ) p.x, ( long ) p.y, ( long ) ( r.right - r.left ), ( long ) ( r.bottom - r.top ) ); hb_retc( b );
}
HB_FUNC( DF_RELPOS )
{
POINT p; char b[ 32 ]; GetCursorPos( &p ); ScreenToClient( ( HWND ) ( UINT_PTR ) hb_parnint( 1 ), &p );
sprintf( b, "%ld,%ld", ( long ) p.x, ( long ) p.y ); hb_retc( b );
}
HB_FUNC( DF_CAPTURE ){ if( hb_parl( 2 ) ) SetCapture( ( HWND ) ( UINT_PTR ) hb_parnint( 1 ) ); else ReleaseCapture(); }
HB_FUNC( DF_RESTORE ){ HWND h = ( HWND ) ( UINT_PTR ) hb_parnint( 1 ); if( IsIconic( h ) || IsZoomed( h ) ) ShowWindow( h, SW_RESTORE ); }
HB_FUNC( DF_ORG ){ SetViewportOrgEx( g_dc, hb_parni( 1 ), hb_parni( 2 ), NULL ); }
/* DF_BOX( l, t, r, b, fill, edge, radius ) */
HB_FUNC( DF_BOX )
{
HBRUSH hb = CreateSolidBrush( ( COLORREF ) hb_parnl( 5 ) ); HPEN hp = CreatePen( PS_SOLID, 1, ( COLORREF ) hb_parnl( 6 ) );
HGDIOBJ ob = SelectObject( g_dc, hb ), op = SelectObject( g_dc, hp );
if( hb_parni( 7 ) > 0 ) RoundRect( g_dc, hb_parni( 1 ), hb_parni( 2 ), hb_parni( 3 ), hb_parni( 4 ), hb_parni( 7 ), hb_parni( 7 ) );
else Rectangle( g_dc, hb_parni( 1 ), hb_parni( 2 ), hb_parni( 3 ), hb_parni( 4 ) );
SelectObject( g_dc, ob ); SelectObject( g_dc, op ); DeleteObject( hb ); DeleteObject( hp );
}
HB_FUNC( DF_DOTBOX )
{
HGDIOBJ nb = GetStockObject( NULL_BRUSH ); HPEN hp = CreatePen( PS_DOT, 1, ( COLORREF ) hb_parnl( 5 ) );
HGDIOBJ ob = SelectObject( g_dc, nb ), op = SelectObject( g_dc, hp );
RoundRect( g_dc, hb_parni( 1 ), hb_parni( 2 ), hb_parni( 3 ), hb_parni( 4 ), 12, 12 );
SelectObject( g_dc, ob ); SelectObject( g_dc, op ); DeleteObject( hp );
}
HB_FUNC( DF_LINE )
{
HPEN hp = CreatePen( PS_SOLID, hb_parni( 6 ), ( COLORREF ) hb_parnl( 5 ) ); HGDIOBJ op = SelectObject( g_dc, hp );
MoveToEx( g_dc, hb_parni( 1 ), hb_parni( 2 ), NULL ); LineTo( g_dc, hb_parni( 3 ), hb_parni( 4 ) ); SelectObject( g_dc, op ); DeleteObject( hp );
}
/* DF_TEXT( cUtf8, l, t, r, b, color, font 0-4, align 0 left 1 center 2 right + 8 wordbreak ) */
HB_FUNC( DF_TEXT )
{
WCHAR w[ 400 ]; RECT rc; int al = hb_parni( 8 ); UINT fl = DT_NOPREFIX | DT_END_ELLIPSIS;
const char * s = hb_parc( 1 );
if( ! s ) return;
rc.left = hb_parni( 2 ); rc.top = hb_parni( 3 ); rc.right = hb_parni( 4 ); rc.bottom = hb_parni( 5 );
MultiByteToWideChar( CP_UTF8, 0, s, -1, w, 400 );
SelectObject( g_dc, g_f[ hb_parni( 7 ) ] ); SetTextColor( g_dc, ( COLORREF ) hb_parnl( 6 ) );
fl |= ( ( al & 3 ) == 1 ) ? DT_CENTER : ( ( al & 3 ) == 2 ) ? DT_RIGHT : DT_LEFT;
if( al & 8 ) { fl &= ~DT_END_ELLIPSIS; fl |= DT_WORDBREAK; } else fl |= DT_SINGLELINE | DT_VCENTER;
DrawTextW( g_dc, w, -1, &rc, fl );
}
HB_FUNC( DF_U8ANSI )
{
WCHAR w[ 600 ]; char b[ 600 ]; const char * s = hb_parc( 1 );
if( ! s ) { hb_retc( "" ); return; }
MultiByteToWideChar( CP_UTF8, 0, s, -1, w, 600 ); WideCharToMultiByte( CP_ACP, 0, w, -1, b, 600, NULL, NULL ); hb_retc( b );
}
HB_FUNC( DF_ANSI2U8 )
{
WCHAR w[ 600 ]; char b[ 1200 ]; const char * s = hb_parc( 1 );
if( ! s ) { hb_retc( "" ); return; }
MultiByteToWideChar( CP_ACP, 0, s, -1, w, 600 ); WideCharToMultiByte( CP_UTF8, 0, w, -1, b, 1200, NULL, NULL ); hb_retc( b );
}
#pragma ENDDUMP