PROGRAM ListDlg; { This code demonstrates how to display different dialogs in one dialog. You can also use this code to build a dialog with register cards. (c) 1997 U. Conrad, uconrad1@gwdg.de } {$R MULTIDLG.RES } { located at the end .. use XX34 to decode } USES OWindows,ODialogs,Strings,Objects,WinProcs,WinTypes; CONST idd_ListBox = 301; idd_Anchor = 302; CONST wm_MyFocus = wm_User + 1000; TYPE PHwnd = ^HWnd; PAtom = ^TAtom; TYPE TDemoApp=OBJECT(TApplication) PROCEDURE InitMainWindow; virtual; END; TYPE DlgInfoStruct = RECORD { contains informations about a sub dialog } szListText : array[0..50] of char; { title which should be displayed in the list box } ResName : array[0..50] of char; { ID of the sub dialog } fPresent : boolean; { loaded or not, that's the question } pCtrlHndls : THandle; { handle for hwnd of controls } pCtrlTexts : THandle; { handle for atoms of controls } CntCntrls : byte; { number of control elements in this dialog } END; TYPE PDemoDlg = ^TDemoDlg; TDemoDlg = OBJECT(TDialog) diDlgs : array[0..2] of DlgInfoStruct; iCurDlg : integer; CONSTRUCTOR Init(AParent : PWindowsObject;AName : PChar); PROCEDURE SetupWindow; virtual; PROCEDURE MyFocus(var Msg : TMessage); virtual wm_First + wm_MyFocus; PROCEDURE ListBox(var Msg : TMessage); virtual id_First + idd_ListBox; PROCEDURE ChildDialogVisible(iDialog : integer;State : boolean); PROCEDURE LoadAndCreateControls(iDialog : integer); PROCEDURE WMDestroy(var Msg : TMessage); virtual wm_First + wm_Destroy; PROCEDURE Ok(var Msg : TMessage); virtual id_First + id_ok; DESTRUCTOR Done; virtual; END; { ================== Methods of the program dialog object ===================== } CONSTRUCTOR TDemoDlg.Init(AParent : PWindowsObject;AName : PChar); VAR b : byte; BEGIN inherited Init(AParent,AName); { Initializing sub dialog informations } FillChar(diDlgs[0],SizeOf(diDlgs[0]),#0); StrCopy(diDlgs[0].szListText,'Identification'); StrCopy(diDlgs[0].ResName,'DLG_IDEN'); FillChar(diDlgs[1],SizeOf(diDlgs[1]),#0); StrCopy(diDlgs[1].szListText,'Preferences'); StrCopy(diDlgs[1].ResName,'DLG_PREF'); FillChar(diDlgs[2],SizeOf(diDlgs[2]),#0); StrCopy(diDlgs[2].szListText,'Wishes'); StrCopy(diDlgs[2].ResName,'DLG_WISH'); iCurDlg:=-1; { no dialog displayed 'til yet } END; PROCEDURE TDemoDlg.SetupWindow; VAR i : integer; BEGIN inherited SetupWindow; FOR i:=0 TO 2 DO BEGIN LoadAndCreateControls(i); { load control elements of one child dialog } ChildDialogVisible(i,false); { and hide them, they will be visible after selecting one from the listbox } SendDlgItemMessage(HWindow,idd_ListBox,lb_AddString,0,LongInt(@diDlgs[i].szListText)); END; { If you want to init the control elements do it here } SetDlgItemText(HWindow,1000,'My'); SetDlgItemText(HWindow,1001,'Name'); { fill list box with dialog titles } SendDlgItemMessage(HWindow,idd_ListBox,lb_SetCurSel,0,0); { select first dialog and make it visible } PostMessage(HWindow,wm_command,idd_ListBox,MakeLong(GetDlgItem(HWindow,idd_ListBox),lbn_SelChange)); { pretend a user's selection in the list box } PostMessage(HWindow,wm_MyFocus,0,0); END; PROCEDURE TDemoDlg.ListBox(var Msg : TMessage); VAR lCurSel : integer; BEGIN IF Msg.lParamHi=lbn_SelChange THEN BEGIN { new child dialog selected } lCurSel:=SendDlgItemMessage(HWindow,idd_ListBox,lb_GetCurSel,0,0); IF lCurSel=-1 THEN Exit; IF lCurSel<>iCurDlg THEN BEGIN { a different child dialog was selected } ChildDialogVisible(iCurDlg,false); { hide actual child dialog } iCurDlg:=lCurSel; { new actual child dialog } ChildDialogVisible(iCurDlg,true); { show new actual child dialog } END; END; Msg.Receiver:=0; END; PROCEDURE TDemoDlg.MyFocus(var Msg : TMessage); BEGIN SetFocus(GetDlgItem(HWindow,idd_ListBox)); { will give the focus back to the list box } Msg.Receiver:=0; END; PROCEDURE TDemoDlg.LoadAndCreateControls(iDialog : integer); { This function will load the resource of a child dialog and put its control elements to the dialog } VAR hDlgFont : HFont; hDlgRes : THandle; hDlgResMem : THandle; lpDlgRes : PChar; style : longint; bNumOfCtrls : byte; bCurCtrl : byte; xOffset, yOffset : integer; hAnchor : HWnd; rc, trc : TRect; pt : TPoint; wID : word; classname : PChar; phw : PHWnd; PTmp : PAtom; BEGIN hDlgFont:=SendMessage(HWindow,wm_GetFont,0,0); { First we need to know which font is used in the dialog so we can set the font of the child controls. } hDlgRes:=FindResource(hInstance,diDlgs[iDialog].ResName,rt_dialog); hDlgResMem:=LoadResource(hInstance,hDlgRes); { load the resource } lpDlgRes:=LockResource(hDlgResMem); { get a pointer to the resource } style:=PLongint(lpDlgRes)^; { get the dialog's style. This and the following operations get their information from the dialog header. It's structur is described in the help under the topic " dialog box header" } lpDlgRes:=lpDlgRes+SizeOf(Style); { increment pointer } bNumOfCtrls:=PByte(lpDlgRes)^; { get number of controls } diDlgs[iDialog].CntCntrls:=bNumOfCtrls; lpDlgRes:=lpDlgRes+SizeOf(byte); { increment pointer } lpDlgRes:=lpDlgRes+(4*SizeOf(word)); { ingnore x, y, cx, and cy of dialog } IF PByte(lpDlgRes)^=$FF THEN lpDlgRes:=lpDlgRes+3 ELSE WHILE lpDlgRes^<>#0 DO lpDlgRes:=lpDlgRes+1; { ignore menu } lpDlgRes:=lpDlgRes+1; WHILE lpDlgRes^<>#0 DO lpDlgRes:=lpDlgRes+1; lpDlgRes:=lpDlgRes+1; { pass the class name } WHILE lpDlgRes^<>#0 DO lpDlgRes:=lpDlgRes+1; lpDlgRes:=lpDlgRes+1; { pass the caption } IF style and ds_SetFont<>0 THEN BEGIN { if ds_SetFont is set we have to skip font information } lpDlgRes:=lpDlgRes+SizeOf(word); { pass point size } WHILE lpDlgRes^<>#0 DO lpDlgRes:=lpDlgRes+1; lpDlgRes:=lpDlgRes+1; { pass the font name } END; diDlgs[iDialog].pCtrlHndls:=LocalAlloc(lptr,SizeOf(HWnd)+SizeOf(HWnd)*bNumOfCtrls); { get memory for control's window handles } diDlgs[iDialog].pCtrlTexts:=LocalAlloc(lptr,SizeOf(TAtom)*bNumOfCtrls); { get memory for control's atom handles } pTmp:=PAtom(LocalLock(diDlgs[iDialog].pCtrlTexts)); FOR bCurCtrl:=1 TO bNumOfCtrls DO BEGIN { initialize atoms } pTmp^:=AddAtom(''); pTmp:=PAtom(Pchar(PTmp)+SizeOf(TAtom)); END; LocalUnlock(diDlgs[iDialog].pCtrlTexts); hAnchor:=GetDlgItem(HWindow,idd_Anchor); GetWindowRect (hAnchor,rc); { get position of anchor } pt.x:=rc.left; pt.y:=rc.top; ScreenToClient(HWindow,pt); rc.left:=pt.x; rc.top:=pt.y; pt.x:=rc.right; pt.y:=rc.bottom; ScreenToClient(HWindow,pt); rc.right:=pt.x; rc.bottom:=pt.y; xOffset:=rc.right; yOffset:=rc.top; { get offset for control elements in client coordinates } phw:=PHwnd(LocalLock(diDlgs[iDialog].pCtrlHndls)); FOR bCurCtrl:=1 TO bNumOfCtrls DO BEGIN { start creating controls } WITH trc DO BEGIN left:=PInteger(lpDlgRes)^; lpDlgRes:=lpDlgRes+SizeOf(integer); { increment pointer } top:=PInteger(lpDlgRes)^; lpDlgRes:=lpDlgRes+SizeOf(integer); { increment pointer } right:=PInteger(lpDlgRes)^; lpDlgRes:=lpDlgRes+SizeOf(integer); { increment pointer } bottom:=PInteger(lpDlgRes)^; lpDlgRes:=lpDlgRes+SizeOf(integer); { increment pointer } END; CopyRect(rc,trc); { get the control's coordinates } MapDialogRect(HWindow,rc); { convert to pixels } rc.left:=rc.left+xOffset; { add offset } rc.top:=rc.top+yOffset; wID:=PWord(lpDlgRes)^; { get the control's ID } lpDlgRes:=lpDlgRes+SizeOf(word); { increment pointer } style:=PLongint(lpDlgRes)^; { get the control's styles } lpDlgRes:=lpDlgRes+SizeOf(longint); { increment pointer } CASE PByte(lpDlgRes)^ OF $80 : classname:='button'; $81 : classname:='edit'; $82 : classname:='static'; $83 : classname:='listbox'; $84 : classname:='scrollbar'; $85 : classname:='combobox'; ELSE BEGIN { get the special class name } classname:=lpDlgRes; WHILE lpDlgRes^<>#0 DO lpDlgRes:=lpDlgRes+1; END; END; lpDlgRes:=lpDlgRes+1; phw^:=CreateWindow(Classname,lpDlgRes,style,rc.left,rc.top,rc.right,rc.bottom,HWindow,wID,hInstance,nil); { create the control element } IF hDlgFont<>0 THEN SendMessage(pHW^,wm_SetFont,hDlgFont,0); { give the control the right font } WHILE lpDlgRes^<>#0 DO lpDlgRes:=lpDlgRes+1; { skip window text } lpDlgRes:=lpDlgRes+1; { skip null terminator } lpDlgRes:=lpDlgRes+1; { skip second null terminator } phw:=PHWnd(PChar(phw)+SizeOf(HWnd)); END; LocalUnlock(diDlgs[iDialog].pCtrlHndls); UnlockResource(hDlgResMem); FreeResource(hDlgResMem); { the resource isn't needed any more, so free it } diDlgs[iDialog].fPresent:=true; END; PROCEDURE TDemoDlg.ChildDialogVisible(iDialog : integer;State : boolean); VAR hCtl : PHwnd; i : integer; pa : PAtom; buf : array[0..80] of char; dwCtlCode : longint; IgnoreText : boolean; lStyle : longint; BEGIN IF iDialog<0 THEN Exit; hCtl:=PHwnd(LocalLock(diDlgs[iDialog].pCtrlHndls)); pa:=PAtom(LocalLock(diDlgs[iDialog].pCtrlTexts)); IF State THEN BEGIN { show the dialog } FOR i:=1 TO diDlgs[iDialog].CntCntrls DO BEGIN IF pa^<>0 THEN BEGIN GetAtomName(pa^,buf,SizeOf(buf)); SetWindowText(hCtl^,buf); DeleteAtom(pa^); END; ShowWindow(hCtl^,sw_Show); pa:=PAtom(PChar(pa)+SizeOf(TAtom)); hCtl:=PHWnd(Pchar(hCtl)+SizeOf(HWnd)); END; END ELSE BEGIN { hide the dialog } FOR i:=1 TO diDlgs[iDialog].CntCntrls DO BEGIN ShowWindow(hCtl^,sw_Hide); dwCtlCode:=SendMessage(hCtl^,wm_GetDlgCode,0,0); ignoreText:=false; IF dwCtlCode and dlgc_WantChars<>0 THEN BEGIN pa^:=0; IgnoreText:=true; END; IF dwCtlCode and dlgc_Static<>0 THEN BEGIN lStyle:=GetWindowLong(hCtl^,gwl_Style); IF lStyle and ss_NoPrefix<>0 THEN BEGIN pa^:=0; IgnoreText:=true; END; END; IF not IgnoreText THEN BEGIN GetWindowText(hCtl^,buf,SizeOf(buf)); pa^:=AddAtom(buf); SetWindowText(hCtl^,''); END; pa:=PAtom(PChar(pa)+SizeOf(TAtom)); hCtl:=PHWnd(Pchar(hCtl)+SizeOf(HWnd)); END; END; LocalUnlock(diDlgs[iDialog].pCtrlTexts); LocalUnlock(diDlgs[iDialog].pCtrlHndls); END; PROCEDURE TDemoDlg.Ok(var Msg : TMessage); VAR buf : array[0..255] of char; BEGIN GetDlgItemText(HWindow,1000,buf,SizeOf(buf)-1); { here you can receive the state of all dialog control elements, for example the "First" edit } EndDlg(id_ok); { finally close this dialog } END; PROCEDURE TDemoDlg.WMDestroy(var Msg : TMessage); VAR i : integer; BEGIN FOR i:=0 TO 2 DO IF diDlgs[i].fPresent THEN BEGIN { free handles of controls } LocalFree(diDlgs[i].pCtrlHndls); LocalFree(diDlgs[i].pCtrlTexts); END; inherited WMDestroy(Msg); END; DESTRUCTOR TDemoDlg.Done; BEGIN inherited done; END; { ================== Methods of the application ===================== } PROCEDURE TDemoApp.InitMainWindow; BEGIN MainWindow:=New(PDemoDlg,Init(nil,'DLG_Main')); { will create a window from dialog template DLG_Main } END; { ***************** Program ******************* } VAR DemoApp : TDemoApp; BEGIN DemoApp.Init('DemoApp'); DemoApp.Run; DemoApp.Done; END. END. { the following contains additional files that should be included with this file. To extract, you need XX3402 available with the SWAG distribution. 1. Cut the text below out, and save to a file .. filename.xx 2. Use XX3402 : xx3402 d filename.xx 3. The decoded file should be created in the same directory. 4. If the file is a archive file, use the proper archive program to extract the members. { ------------------ CUT ----------------------} *XX3402-000956-290697--72--85-61452----MULTIDLG.RES--1-OF--1 zkI+F2l5LoZ2FIs+A-0w++++E+0+U+V4++Y+YU-N++++++U+HJAUIq3iQm-HNL7dNU+3++2+ 5U+8+Cs1+++0I66aFaZmQrE+++I+1++d++w+u+C++63EUE++BE+-+-s+0k1j+k+++Z007YlV QrE++1I+1+-I++w+uEC++63EUE++-E+S+-s+0E1k+k+++Z007Y3YN57ZQrAu+++3+0U+V++D +Cc1U+0-I62+++I+C+02++w+v+C++63EUE++-E-6+6E+1k1h+s++UJ0-++1z-E-2H2RTHI37 HU+k26o+++1++AWE-46+9+1Z+4w+++-BRKloOG-YOK3gPqQUN4JhPqtnR57VR4ZjPU+6+2pH 63BVPbAUIqJmOKM+0k-7+16+1U+-++2++J0+Hog+++g+KU+m++s++U++++3EU2BVPaBZP+++ 0k+7+1Y+0++i+E+++Z007YFdMKljNk++0k+J+16+9++h+E2-cJ01++1z-E-2H2RTI373FU+k 2+w-++-++60+0YM+0E0G+3U+++++0+-BIm-HMKtn63BZQaZa++A+-+-2+2E+oEQ5++3EU2Jb NrA+++Y+2U+t++g+oUQ7++7EU0NHMr7VPK7gNKE+++Y+5k+t++g+okQ7++-EU0NDRaJm9KJV QrY+++Y+9++n++g+p+Q7++-EU0N6ML7Y627jOKlZN+++0E+t+0s+0k1J-kY++30+7Z7VRk++ H++2+2++Ak1E-kQ++p0+Ea3b++-F+-++BE+9+BM50E+0I6+aI43kNL6++32+5++r++g+pkQ7 ++-EU3+aP43nR4ZX++-F+0U+Bk+9+BU50E++I6+aEqljR4U++2k+DU-+++s+qEQ+++BEU0N2 OKtbQk++zkI+F2l5LpR7IoU+A-1+++++E+0+U+N4++Y+YU-M++++++U+HJAUIq3iQm-HNL7d NU+5++E+6U+C+9c9+k+-I6+aH4xqNE++-k+H+2w+1U0s0kA++J0+IqJiQqIUPqMU7Z-pQb-j QqI+++Q+6U+x++s+ikg1++3EU0N4RKlaOKlgPKJiR+++-k+l+2o+1U0t0kA++J0+FaJZP4Zi Nm-jNW+aJqxmR4U+++Q+FU+W++g+j+g1++3EU0NDR4VZQXc++0c+F+-a+-2+jEi++63EUE++ zkw+zk2+A-lE++++2++3++4++2FAFpx7F2JC+-++-E+0U+-2H2RTHI37HU+E++I++s++F2l5 Lp-GFIM+2++3++G++2FAFpxLGJB6++++++++++++++++++++++++ ***** END OF BLOCK 1 *****