[Back to WIN-OS2 SWAG index] [Back to Main SWAG index] [Original]

    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 *****

[Back to WIN-OS2 SWAG index] [Back to Main SWAG index] [Original]