FWH 1808: Dialog as Mdichild
Posted: Mon Oct 22, 2018 5:42 pm
Introducing enhanced command:
While developing applications in MDI environment, we may like to design some mdichild windows with a resource editor, but it is not directly possible. So, we adopt a workaround by first creating a dialog from resources and then transferring the controls to mdichild.
Present method:
A typical implementation looks like this:
Individual programmers may adopt different code but essentially the underlying theme is the same.
FWH18.08: New simplified and better approach:
The entire above code is replaced with
Adding the clause CENTERED centers the mdichild window inside the main mdi window.
Note:
If the definition of DIALOG in the Resource file contains the style WS_VISIBLE, that should be removed.
Advantages over the previous implementation:
1) Simplified code and lesser chance to commit mistakes/bugs.
2) Flicker: With the previous implementation, the dialog appears on the screen briefly for a fraction of a second and then disappears before the mdichild window is displayed. This flicker is eliminated.
3) After activation, the variable "oDlg" refers to the new mdichild window and not to the dialog object anymore.
oDlg can be used to refer to the mdichild window.
4) All codeblocks created with the dialog object oDlg are transferred to the new mdichild object, including contents of Cargo.
5) Though these codeblocks were written refering the oDlg object, during execution they act on the mdichild window but not on the dialog object, which anyway is already ended.
Eg: ACTION oDlg:End() now closes mdichild window.
oDlg:bRClicked now acts on mdichild window
etc.
Known issues (with both old and new methods):
1) Some controls like Say, Combobox, etc. flicker when the mdichild window is resized.
2) FocusRect is not painted around some controls like CheckBox, etc.
These are issues inherent with mdichild and have nothing to do with the method adopted. Even controls directly created on mdichild window have these issues. We are still working to eliminate them.
fwh\samples\mdidlg.prg: Demonstrating old and new methods:
mdidlg.rc
Code: Select all
ACTIVATE DIALOG oDlg AS MDICHILD
Present method:
A typical implementation looks like this:
Code: Select all
DEFINE DIALOG oDlg RESOURCE "resname"
// <REDEFINE all controls>
DEFINE WINDOW oWnd MDICHILD OF WndMain()
ACTIVATE DIALOG oDlg NOWAIT ON INIT ( ChangeParent( oDlg, oWnd ) )
oDlg:End()
ACTIVATE WINDOW oWnd
//---------------------------------------//
static function ChangeParent( oDlg, oWnd )
local oControl
for each oControl in oDlg:aControls
SetParent( oControl:hWnd, oWnd:hWnd )
AAdd( oWnd:aControls, oControl )
oControl:oWnd := oWnd
next
oWnd:SetSize( oDlg:nWidth, oDlg:nHeight )
oWnd:SetColor( oDlg:nClrText, oDlg:nClrPane, oDlg:oBrush )
return nil
FWH18.08: New simplified and better approach:
The entire above code is replaced with
Code: Select all
DEFINE DIALOG oDlg RESOURCE "resname"
// <REDEFINE all controls>
ACTIVATE DIALOG oDlg AS MDICHILD
Note:
If the definition of DIALOG in the Resource file contains the style WS_VISIBLE, that should be removed.
Advantages over the previous implementation:
1) Simplified code and lesser chance to commit mistakes/bugs.
2) Flicker: With the previous implementation, the dialog appears on the screen briefly for a fraction of a second and then disappears before the mdichild window is displayed. This flicker is eliminated.
3) After activation, the variable "oDlg" refers to the new mdichild window and not to the dialog object anymore.
oDlg can be used to refer to the mdichild window.
4) All codeblocks created with the dialog object oDlg are transferred to the new mdichild object, including contents of Cargo.
5) Though these codeblocks were written refering the oDlg object, during execution they act on the mdichild window but not on the dialog object, which anyway is already ended.
Eg: ACTION oDlg:End() now closes mdichild window.
oDlg:bRClicked now acts on mdichild window
etc.
Known issues (with both old and new methods):
1) Some controls like Say, Combobox, etc. flicker when the mdichild window is resized.
2) FocusRect is not painted around some controls like CheckBox, etc.
These are issues inherent with mdichild and have nothing to do with the method adopted. Even controls directly created on mdichild window have these issues. We are still working to eliminate them.
fwh\samples\mdidlg.prg: Demonstrating old and new methods:
Code: Select all
#include "fivewin.ch"
#define AS_MDICHILD 1
#define AS_DIALOG 2
//----------------------------------------------------------------------------//
function Main()
local oWnd, oBar, oMenu
SetGetColorFocus()
DEFINE WINDOW oWnd MDI TITLE "FWH18.08: DIALOG IN MDICHILD WINDOW"
DEFINE BUTTONBAR oBar OF oWnd SIZE 100,32 2007
DEFINE BUTTON OF oBar PROMPT "MDIDLG-OLD" CENTER ACTION DlgInMdiChildOld()
DEFINE BUTTON OF oBar PROMPT "MDIDLG-NEW" CENTER ACTION CreateDialog( AS_MDICHILD )
DEFINE BUTTON OF oBar PROMPT "DIALOG" CENTER ACTION CreateDialog( AS_DIALOG )
ACTIVATE WINDOW oWnd
return nil
//----------------------------------------------------------------------------//
static function CreateDialog( nAs )
local oDlg, oCbx, oChk, oFont, oBrush
local cVar1, cVar2
local lSwitch1, lSwitch2, lSwitch3
local cVar := "Two"
local aGrad := {{1, CLR_WHITE, CLR_HBLUE }}
cVar1 := cVar2 := Space( 50 )
lSwitch1 := lSwitch2 := lSwitch3 := .f.
DEFINE BRUSH oBrush GRADIENT aGrad
DEFINE FONT oFont NAME "Segoe UI" SIZE 0,-14
DEFINE DIALOG oDlg RESOURCE "MDIDLG" FONT oFont TITLE "MDI-DLG" BRUSH oBrush
RELEASE FONT oFont
RELEASE BRUSH oBrush
REDEFINE CHECKBOX oChk VAR lSwitch1 ID 1001 OF oDlg
oChk:lTransparent := .t.
REDEFINE CHECKBOX oChk VAR lSwitch2 ID 1002 OF oDlg
oChk:lTransparent := .t.
REDEFINE GET cVar1 ID 1005 OF oDlg
REDEFINE CHECKBOX oChk VAR lSwitch3 ID 1010 OF oDlg WHEN lSwitch1
oChk:lTransparent := .t.
REDEFINE COMBOBOX oCbx VAR cVar ITEMS { "One", "Two", "Three" } ID 1015 OF oDlg WHEN lSwitch2
REDEFINE GET cVar2 ID 1020 OF oDlg
REDEFINE SAY ID 1200 OF oDlg TRANSPARENT COLOR CLR_WHITE,CLR_WHITE
REDEFINE BTNBMP PROMPT "CLOSE" ID 2001 OF oDlg CENTER 2007 ACTION oDlg:End()
if nAs == AS_MDICHILD
ACTIVATE DIALOG oDlg AS MDICHILD ;
ON PAINT oDlg:Box( 8,8, 373, 584, CLR_HRED ) ;
ON RIGHT CLICK MsgInfo( oDlg:ClassName(), "oDlg:ClassName" )
elseif nAs == AS_DIALOG
ACTIVATE DIALOG oDlg CENTERED
endif
return oDlg
//----------------------------------------------------------------------------//
static function DlgInMdiChildOld()
local oWnd, oDlg
oDlg := CreateDialog()
DEFINE WINDOW oWnd MDICHILD OF WndMain() TITLE "Dialog"
ACTIVATE DIALOG oDlg NOWAIT ON INIT ( ChangeParent( oDlg, oWnd ) )
oDlg:End()
ACTIVATE WINDOW oWnd
return nil
//----------------------------------------------------------------------------//
static function ChangeParent( oDlg, oWnd )
local oControl
for each oControl in oDlg:aControls
SetParent( oControl:hWnd, oWnd:hWnd )
AAdd( oWnd:aControls, oControl )
oControl:oWnd := oWnd
next
oWnd:SetSize( oDlg:nWidth, oDlg:nHeight )
oWnd:SetColor( oDlg:nClrText, oDlg:nClrPane, oDlg:oBrush )
return nil
//----------------------------------------------------------------------------//
Code: Select all
#include <windows.h>
#ifndef __64__
1 24 "WinXP/WindowsXP.Manifest"
#else
1 24 "WinXP/WindowsXP.Manifest64"
#endif
MDIDLG DIALOG 0, 0, 394, 234
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "TXBrowse demo"
FONT 8, "MS Sans Serif"
{
AUTOCHECKBOX "Switch-1", 1001, 44, 22, 69, 9, 0, WS_EX_LEFT
AUTOCHECKBOX "Switch-2", 1002, 219, 23, 94, 8, 0, WS_EX_LEFT
EDITTEXT 1005, 45, 54, 294, 18, ES_AUTOHSCROLL, WS_EX_LEFT
AUTOCHECKBOX "CheckBox When Switch-1", 1010, 47, 86, 123, 12, 0, WS_EX_LEFT
COMBOBOX 1015, 202, 85, 139, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT
EDITTEXT 1020, 46, 116, 294, 18, ES_AUTOHSCROLL, WS_EX_LEFT
CTEXT "TRANSPARENT SAY", 1200, 44, 174, 131, 22, SS_CENTER, WS_EX_TRANSPARENT
PUSHBUTTON "OK", 2001, 256, 178, 69, 24, 0, WS_EX_LEFT
}