TDialog

Core Class Inherits TWindow source/classes/dialog.prg

TDialog is the class used to create modal and modeless dialog boxes in FiveWin. It inherits from TWindow and adds dialog-specific behavior: modal/modeless activation, resource-based creation, coordinate system selection (text, pixel, true-pixel), transparent control backgrounds, dark mode support, and a structured lifecycle with ON INIT / VALID phases.

Inheritance

classDiagram class TWindow { +hWnd +cCaption +aControls +Activate() +End() } class TDialog { +lModal +lTruePixel +lCentered +nResult +cResName +Activate() +End() +Define() +cToChar() } TWindow <|-- TDialog TDialog : +lTransparent TDialog : +lResizable TDialog : +hResources TDialog : +aDarkColors TDialog : +oMonitor

Key DATA Members

DATATypeDefaultDescription
lModalLogicalnilWhether the dialog runs as modal (.T.) or modeless (.F.). Set during Activate().
nResultNumeric0Dialog result code. Typically IDOK (1) or IDCANCEL (2).
lCenteredLogicalnilCenter the dialog on screen when activated.
lCenterInWndLogicalnilCenter the dialog within its parent window instead of the screen.
lTruePixelLogical.F.Use true pixel coordinates (1:1 mapping). See Coordinate Systems.
lTransparentLogical.F.Enable transparent control backgrounds (required for gradient/bitmap brushes).
lResize16Logical.F.Resize 32-bit resource dialogs to match 16-bit proportions.
cResNameCharacternilResource name for resource-based dialogs.
hResourcesNumericGetResources()Handle to the resource DLL/EXE containing dialog templates.
bStartBlocknilEvaluated once on first Display(). Auto-clears after execution.
lMdiChildLogical.F.Show the dialog as an MDI child window.
oMonitorObjectnilTarget monitor for multi-display positioning (read-only after Activate).
aDarkColorsArraynilArray { nClrText, nClrBack } for dark mode styling.

Key Methods

New() — Constructor

METHOD New( nTop, nLeft, nBottom, nRight, cCaption, cResName,
      hResources, lVbx, nStyle, nClrText, nClrBack, oBrush, oWnd,
      lPixels, oIco, oFont, nHelpId, nWidth, nHeight, lTransparent,
      aGradColors, cVarName, lUnicode, lTruePixel, lResizable )

Creates a TDialog object. If cResName is provided, the dialog layout comes from a compiled resource. Otherwise coordinates define the dialog size. When nWidth and nHeight are non-zero, they override nBottom/nRight and force pixel mode.

Define() — Alternative Constructor

METHOD Define( nTop, nLeft, nBottom, nRight, cCaption, nStyle,
      lVbx, nClrText, nClrBack, oBrush )

Minimal constructor used primarily by the visual designer. Creates the object with fewer parameters.

Activate()

METHOD Activate( bLClicked, bMoved, bPainted, lCentered,
      bValid, lModal, bInit, bRClicked, bWhen, lResize16,
      lCenterInWnd, lMdiChild, oMdiChild, bMdiSetup, oMonitor )

Creates the Win32 dialog and enters the message loop. For modal dialogs (default), this call blocks until End() is called. For modeless dialogs (lModal := .F. or NOMODAL clause), it returns immediately.

End()

METHOD End( nResult )

Closes the dialog. If bValid is set, it is evaluated first; if it returns .F., the dialog stays open. The optional nResult parameter sets ::nResult before closing.

cToChar()

METHOD cToChar( hActiveWnd )

Generates a character string representation of the dialog and all its controls — used by the visual designer to serialize a dialog to source code.

SetDarkMode()

METHOD SetDarkMode( nClrText, nClrBack )

Enables dark mode styling for the dialog and its child controls.

DefControl()

METHOD DefControl( oCtrl )

Register a control as the default focus target for the dialog. When the dialog is activated, this control receives the initial focus.

Initiate()

METHOD Initiate( hDlg )

Called internally during dialog creation to subclass the Win32 dialog procedure, distribute child controls via REDEFINE, evaluate bInit, and apply dark mode colors. Called automatically during Activate().

Command()

METHOD Command( nCtrlId, nNotifyCode )

Handles WM_COMMAND messages from child controls. Routes button clicks, menu selections, and control notifications to the appropriate event handlers.

CtlColor()

METHOD CtlColor( hDC, oCtrl, nCtlType )

Handles WM_CTLCOLOR messages to set text and background colors for child controls. Called automatically during dialog painting.

Commands: DEFINE DIALOG / ACTIVATE DIALOG

DEFINE DIALOG

DEFINE DIALOG oDlg ;
   [ FROM nTop, nLeft TO nBottom, nRight ] ;
   [ SIZE nWidth, nHeight ] ;
   [ TITLE cTitle ] ;
   [ RESOURCE cResName ] ;
   [ OF oParent ] ;
   [ STYLE nStyle ] ;
   [ COLOR nClrText, nClrBack ] ;
   [ BRUSH oBrush ] ;
   [ FONT oFont ] ;
   [ ICON oIcon ] ;
   [ PIXEL ] ;
   [ TRUEPIXEL ] ;
   [ TRANSPARENT ] ;
   [ RESIZABLE ] ;
   [ HELPID nHelpId ] ;
   [ UNICODE ] ;
   [ GRADIENT aGradColors ]

ACTIVATE DIALOG

ACTIVATE DIALOG oDlg ;
   [ CENTER | CENTERED ] ;
   [ CENTERED IN WINDOW oWnd ] ;
   [ ON INIT bInit ] ;
   [ VALID bValid ] ;
   [ ON PAINT bPainted ] ;
   [ ON CLICK bLClicked ] ;
   [ ON RIGHT CLICK bRClicked ] ;
   [ ON MOVE bMoved ] ;
   [ NOMODAL | NOWAIT ] ;
   [ WHEN bWhen ] ;
   [ RESIZE16 ]

Dialog Lifecycle

Understanding the dialog lifecycle is critical for correct initialization and cleanup:

flowchart TD A["DEFINE DIALOG
(TDialog:New)"] --> B["Add Controls
@ ... GET, SAY, BUTTON, etc."] B --> C["ACTIVATE DIALOG
(TDialog:Activate)"] C --> D["Win32 CreateDialog /
DialogBoxParam"] D --> E["Initiate()
Distribute child controls"] E --> F["ON INIT block
bInit evaluated"] F --> G["Message Loop
User interaction"] G --> H{"End() called
or close button"} H -->|"VALID returns .F."| G H -->|"VALID returns .T."| I["Destroy controls
DestroyWindow"] I --> J["Activate() returns
nResult available"]

Important: controls must be created between DEFINE DIALOG and ACTIVATE DIALOG. The ON INIT block fires after the dialog window exists (has a valid hWnd), making it the right place for initialization that needs the window handle.

Coordinate Systems

FiveWin dialogs support three coordinate systems. Choosing the right one is essential for correct layout across different DPI settings:

SystemClauseUnitWhen to Use
Text coordinates(default)Character cells: 1 row ~ 16px, 1 col ~ 8px (at 96 DPI)Legacy code, simple dialogs. Coordinates like @ 1, 2 place controls in text grid positions.
PIXELPIXELDialog units (DLUs), not true pixels. Scaled by the system font.Resource-editor compatibility. Still not 1:1 with screen pixels.
TRUEPIXELTRUEPIXELActual screen pixels (1:1 mapping)Modern applications. Full control over exact positioning. Recommended for new code.

Coordinate Comparison

// Text coordinates (default) - relative to character grid
DEFINE DIALOG oDlg TITLE "Text Coords" ;
   FROM 2, 5 TO 20, 60

   @ 1, 1 SAY "Name:" OF oDlg
   @ 1, 6 GET oGet VAR cName OF oDlg SIZE 100, 11

ACTIVATE DIALOG oDlg CENTER

// TRUEPIXEL - exact screen pixels, recommended for new code
DEFINE DIALOG oDlg TITLE "True Pixels" ;
   SIZE 500, 400 TRUEPIXEL

   @ 20, 20 SAY "Name:" OF oDlg SIZE 60, 22 TRUEPIXEL
   @ 20, 90 GET oGet VAR cName OF oDlg SIZE 200, 24 TRUEPIXEL

ACTIVATE DIALOG oDlg CENTER

Tip: On Windows 10/11 with high-DPI displays, text coordinates and PIXEL mode may produce unexpected results. Use TRUEPIXEL for pixel-perfect layouts. You can also set it globally with FW_SetTruePixel( .T. ) or at the class level with TDialog():lClsTruePixel := .T..

Example: Modal Dialog with GETs and Buttons

#include "FiveWin.ch"

function EditCustomer( oWnd )

   local oDlg, oFont, oBtnOk, oBtnCancel
   local cName   := Space( 40 )
   local cEmail  := Space( 60 )
   local cPhone  := Space( 20 )
   local cCity   := Space( 30 )
   local nResult

   DEFINE FONT oFont NAME "Segoe UI" SIZE 0, -14

   DEFINE DIALOG oDlg TITLE "Edit Customer" ;
      SIZE 480, 340 TRUEPIXEL ;
      FONT oFont OF oWnd TRANSPARENT

   @ 20,  20 SAY "Name:"  OF oDlg SIZE 80, 22 TRUEPIXEL
   @ 20, 110 GET cName    OF oDlg SIZE 340, 24 TRUEPIXEL

   @ 55,  20 SAY "Email:" OF oDlg SIZE 80, 22 TRUEPIXEL
   @ 55, 110 GET cEmail   OF oDlg SIZE 340, 24 TRUEPIXEL

   @ 90,  20 SAY "Phone:" OF oDlg SIZE 80, 22 TRUEPIXEL
   @ 90, 110 GET cPhone   OF oDlg SIZE 200, 24 TRUEPIXEL

   @ 125, 20 SAY "City:"  OF oDlg SIZE 80, 22 TRUEPIXEL
   @ 125, 110 GET cCity   OF oDlg SIZE 200, 24 TRUEPIXEL

   @ 260, 250 BUTTON oBtnOk PROMPT "&OK" OF oDlg ;
      SIZE 100, 30 TRUEPIXEL ;
      ACTION ( oDlg:End( IDOK ) )

   @ 260, 360 BUTTON oBtnCancel PROMPT "&Cancel" OF oDlg ;
      SIZE 100, 30 TRUEPIXEL ;
      ACTION ( oDlg:End( IDCANCEL ) ) CANCEL

   ACTIVATE DIALOG oDlg CENTER ;
      VALID ( oDlg:nResult != IDOK .or. ;
              !Empty( cName ) .or. ;
              MsgAlert( "Name is required" ) == nil )

   nResult := oDlg:nResult

   oFont:End()

   if nResult == IDOK
      // Save the data...
      MsgInfo( "Saved: " + AllTrim( cName ) )
   endif

return nResult

Example: Modeless Dialog

A modeless dialog does not block the calling code. The user can interact with both the dialog and other windows. Use NOMODAL or NOWAIT:

#include "FiveWin.ch"

static oDlgFind   // keep reference alive!

function ShowFindDialog( oWnd )

   local cSearch := Space( 40 )

   if oDlgFind != nil .and. IsWindow( oDlgFind:hWnd )
      oDlgFind:SetFocus()
      return nil
   endif

   DEFINE DIALOG oDlgFind TITLE "Find" ;
      SIZE 400, 140 TRUEPIXEL ;
      OF oWnd STYLE nOR( DS_MODALFRAME, WS_POPUP, WS_CAPTION, WS_SYSMENU )

   @ 20, 20  SAY "Search:" OF oDlgFind SIZE 60, 22 TRUEPIXEL
   @ 20, 90  GET cSearch   OF oDlgFind SIZE 200, 24 TRUEPIXEL

   @ 20, 300 BUTTON "Find" OF oDlgFind SIZE 80, 26 TRUEPIXEL ;
      ACTION DoSearch( cSearch )

   @ 56, 300 BUTTON "Close" OF oDlgFind SIZE 80, 26 TRUEPIXEL ;
      ACTION oDlgFind:End()

   ACTIVATE DIALOG oDlgFind CENTER NOMODAL ;
      ON INIT ( oDlgFind:SetFocus() )

   // Code here runs IMMEDIATELY (dialog is modeless)

return nil

static function DoSearch( cSearch )
   MsgInfo( "Searching for: " + AllTrim( cSearch ) )
return nil

Resource-Based Dialogs

Dialogs can be loaded from compiled .RC resources (embedded in the EXE or a resource DLL). This is useful for visual editors or when migrating from C/C++ applications:

#include "FiveWin.ch"

function ShowAbout()

   local oDlg

   DEFINE DIALOG oDlg RESOURCE "ABOUTDLG"

   REDEFINE BUTTON ID 101 OF oDlg ACTION oDlg:End()

   ACTIVATE DIALOG oDlg CENTER

return nil

Use REDEFINE commands (instead of @) to bind FiveWin objects to controls already defined in the resource template by their numeric IDs.

Gradient and Transparent Backgrounds

Gradient backgrounds require TRANSPARENT so child controls paint correctly over the gradient:

DEFINE DIALOG oDlg TITLE "Gradient Dialog" ;
   SIZE 500, 350 TRUEPIXEL TRANSPARENT ;
   GRADIENT { { 0.5, nRGB(30,60,120), nRGB(15,30,60) }, ;
              { 0.5, nRGB(15,30,60),  nRGB(5,10,20) } }

Modal vs Modeless Flow

flowchart LR subgraph Modal M1["ACTIVATE DIALOG
oDlg CENTER"] --> M2["Dialog runs...
(code blocked)"] M2 --> M3["oDlg:End()"] M3 --> M4["Next line
executes"] end subgraph Modeless N1["ACTIVATE DIALOG
oDlg NOMODAL"] --> N2["Next line
executes immediately"] N1 --> N3["Dialog runs
independently"] N3 --> N4["oDlg:End()"] end

Usage Tips

FW_SetDarkMode — Global Dark Theme

FiveWin provides a global dark mode function that automatically themes all new and existing dialogs. Call FW_SetDarkMode() once to enable dark styling across the entire application:

// Enable with default colors
FW_SetDarkMode( .T. )

// Enable with custom colors
FW_SetDarkMode( .T., nClrText, nClrBack )

// Disable
FW_SetDarkMode( .F. )

// Query current state
lIsDark := FW_SetDarkMode()

When enabled:

Ver También