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
Key DATA Members
| DATA | Type | Default | Description |
|---|---|---|---|
lModal | Logical | nil | Whether the dialog runs as modal (.T.) or modeless (.F.). Set during Activate(). |
nResult | Numeric | 0 | Dialog result code. Typically IDOK (1) or IDCANCEL (2). |
lCentered | Logical | nil | Center the dialog on screen when activated. |
lCenterInWnd | Logical | nil | Center the dialog within its parent window instead of the screen. |
lTruePixel | Logical | .F. | Use true pixel coordinates (1:1 mapping). See Coordinate Systems. |
lTransparent | Logical | .F. | Enable transparent control backgrounds (required for gradient/bitmap brushes). |
lResize16 | Logical | .F. | Resize 32-bit resource dialogs to match 16-bit proportions. |
cResName | Character | nil | Resource name for resource-based dialogs. |
hResources | Numeric | GetResources() | Handle to the resource DLL/EXE containing dialog templates. |
bStart | Block | nil | Evaluated once on first Display(). Auto-clears after execution. |
lMdiChild | Logical | .F. | Show the dialog as an MDI child window. |
oMonitor | Object | nil | Target monitor for multi-display positioning (read-only after Activate). |
aDarkColors | Array | nil | Array { 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:
(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:
| System | Clause | Unit | When 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. |
| PIXEL | PIXEL | Dialog units (DLUs), not true pixels. Scaled by the system font. | Resource-editor compatibility. Still not 1:1 with screen pixels. |
| TRUEPIXEL | TRUEPIXEL | Actual 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
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
- Always use
CENTERunless you have a specific reason to position the dialog manually. Hardcoded pixel positions break on different screen resolutions. - Keep modeless dialog references in
staticvariables to prevent the garbage collector from destroying them. - Use
ON INITfor code that needs the dialog window to exist (setting focus, populating XBrowse, calling Win32 API). Do not rely on code betweenDEFINEandACTIVATEfor this. VALIDfires on every close attempt, including the title-bar X button and pressing Escape. Return.T.to allow closing,.F.to prevent it.- Dark mode — Call
oDlg:SetDarkMode( nClrText, nClrBack )in theON INITblock for a dark-themed dialog. - Resizable dialogs — Use the
RESIZABLEclause. Combine with control anchoring (AdjClient(),AdjTop()) to auto-resize child controls.
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:
- All new dialogs are automatically themed in
Initiate()using the configured dark colors. - Existing open windows are themed immediately.
- Child controls inherit the dark colors automatically via
WM_CTLCOLORhandling. - The
aDarkColorsDATA member stores the{ nClrText, nClrBack }pair for each dialog. - Individual dialogs can override the global theme using
oDlg:SetDarkMode( nClrT, nClrP )inON INIT.