home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / deans.zip / DIALOG.CPP < prev    next >
C/C++ Source or Header  |  1994-09-14  |  38KB  |  1,063 lines

  1. //
  2. // NAME: CIDGui_Dialog.Cpp
  3. //
  4. // DESCRIPTION:
  5. //
  6. //    This module implements the DIALOGWND class. Note that we turn on the
  7. //  INCL_CIDLIB_GUICTRLS token, which forces all control window classes to
  8. //  be included.
  9. //
  10. //
  11. // AUTHOR: Dean Roddey
  12. //
  13. // CREATE DATE: 09/25/93
  14. //
  15. // COPYRIGHT: 1992..1994, 'CIDCorp
  16. //
  17. // CAVEATS/GOTCHAS:
  18. //
  19. //  1)  FRAMEWND's handling of presentation spaces are sufficient for
  20. //      DIALOGWND so it does not mess around with that stuff.
  21. //
  22. // MODIFICATION LOG:
  23. //
  24.  
  25.  
  26.  
  27. // -----------------------------------------------------------------------------
  28. //  Local defines
  29. // -----------------------------------------------------------------------------
  30. #define        CIDGUI_DIALOGWND_CPP
  31.  
  32. #define     INCL_WINBUTTONS
  33. #define     INCL_WINENTRYFIELDS
  34. #define     INCL_WINLISTBOXES
  35. #define     INCL_WINSCROLLBARS
  36. #define     INCL_WINSTATICS
  37.  
  38. #define     INCL_WINDIALOGS
  39. #define     INCL_WINFRAMEMGR
  40. #define     INCL_WINPOINTERS
  41. #define     INCL_WINWINDOWMGR
  42. #define     INCL_WINSYS
  43.  
  44. #define     INCL_CIDLIB_FACOBJECT
  45.  
  46. #define     INCL_CIDGUI_ERRORIDS
  47. #define     INCL_CIDGUI_FACOBJECT
  48. #define     INCL_CIDGUI_GUICTRLS
  49. #define     INCL_CIDGUI_DIALOGS
  50. #define     INCL_CIDGUI_GRAPHICS
  51. #define     INCL_CIDGUI_WINDOWS
  52.  
  53.  
  54.  
  55. // -----------------------------------------------------------------------------
  56. //  Standard includes
  57. // -----------------------------------------------------------------------------
  58. #include    <string.h>
  59. #include    <stdlib.h>
  60.  
  61.  
  62. // -----------------------------------------------------------------------------
  63. //  Facility specific includes
  64. // -----------------------------------------------------------------------------
  65. #include    "CIDGui_.Hpp"
  66.  
  67.  
  68. // -----------------------------------------------------------------------------
  69. //  Local functions
  70. // -----------------------------------------------------------------------------
  71.  
  72. //
  73. // FUNCTION/METHOD NAME: __clsMapPMClass(   pDlgTmpl, pDlgItem, ppCtlData
  74. //                                          , pc4CtlLen)
  75. //
  76. // DESCRIPTION:
  77. //
  78. //  This method will map the passed PM class type (and it's corresponding
  79. //  styles) into a equivilent CIDLib class name. It will also handle the
  80. //  control data for the control, if any. If not, it returns a 0 pointer.
  81. //  The caller is responsible for deleting the control data.
  82. //
  83. //  The PM class type does not have the usual high word of set bits, so we
  84. //  force it on before comparing to the PM class constants.
  85. // ---------------------------------------
  86. //   INPUT: pDlgTmpl is the address of the dialog template
  87. //          pDlgItem is the address of the dialog item for this control
  88. //
  89. //  OUTPUT: ppCtlData is a pointer to a pointer that will be filled in with
  90. //              the address of an allocated control data buffer. If none, it is
  91. //              set to 0.
  92. //          pc4CtlLen is filled in with the length of the control data
  93. //
  94. //  RETURN: A CIDCLASS object with the correct class name
  95. //
  96. static CIDCLASS __clsMapPMClass( const  PDLGTEMPLATE        pDlgTmpl
  97.                                 , const PDLGTITEM           pDlgItem
  98.                                 ,       tCIDLib::VOID**     ppCtlData
  99.                                 ,       tCIDLib::CARD4*     pc4CtlLen)
  100. {
  101.     tCIDLib::CARD4  c4Styles = pDlgItem->flStyle;
  102.     tCIDLib::CARD4  c4Tmp;
  103.     tCIDLib::VOID*  pClass = (tCIDLib::VOID*)(  0xFFFF0000
  104.                                                 | pDlgItem->offClassName);
  105.  
  106.     // Assume no control data
  107.     *ppCtlData  = 0;
  108.     *pc4CtlLen  = 0;
  109.  
  110.     if (pClass == WC_BUTTON)
  111.     {
  112.         //
  113.         //  Look at the styles to decide exactly what type of button we
  114.         //  are creating.
  115.         //
  116.         if (c4Styles & (BS_CHECKBOX | BS_AUTOCHECKBOX))
  117.         {
  118.             return CIDCLASS("CHECKBOXWND");
  119.         }
  120.          else if (c4Styles & (BS_RADIOBUTTON | BS_AUTORADIOBUTTON))
  121.         {
  122.             return CIDCLASS("RADIOBUTTWND");
  123.         }
  124.          else if (c4Styles & (BS_3STATE | BS_AUTO3STATE))
  125.         {
  126.             return CIDCLASS("TRIBUTTWND");
  127.         }
  128.          else
  129.         {
  130.             return CIDCLASS("PUSHBUTTWND");
  131.         }
  132.     }
  133.      else if (pClass == WC_CONTAINER)
  134.     {
  135.         return CIDCLASS("CONTAINERWND");
  136.     }
  137.      else if (pClass == WC_ENTRYFIELD)
  138.     {
  139.         return CIDCLASS("ENTRYFLDWND");
  140.     }
  141.      else if (pClass == WC_MLE)
  142.     {
  143.         return CIDCLASS("MLEWND");
  144.     }
  145.      else if (pClass == WC_STATIC)
  146.     {
  147.         //
  148.         //  Look at the styles and decide what type we really need. Static
  149.         //  styles are not bits, but are a numeric value embedded into the
  150.         //  lower 7 bits.
  151.         //
  152.         c4Tmp = (c4Styles & 0x7FL);
  153.  
  154.         if (c4Tmp == SS_GROUPBOX)
  155.         {
  156.             return CIDCLASS("GROUPBOXWND");
  157.         }
  158.          else if (c4Tmp == SS_TEXT)
  159.         {
  160.             return CIDCLASS("STATTXTWND");
  161.         }
  162.          else if ((c4Tmp == SS_FGNDRECT) || (c4Tmp == SS_BKGNDRECT))
  163.         {
  164.             return CIDCLASS("CLRAREAWND");
  165.         }
  166.          else if ((c4Tmp == SS_ICON) || (c4Tmp == SS_BITMAP))
  167.         {
  168.             //
  169.             //  Get the id of the icon and put into the control data. It is
  170.             //  in the window text in the form #xxx where xxx is the icon
  171.             //  id.
  172.             //
  173.             if (pDlgItem->cchText == 0)
  174.             {
  175.                 facCIDGui.LogMsg(   __FILE__
  176.                                     , "__clsMapPMClass"
  177.                                     , __LINE__
  178.                                     , "ICONWND or BMPWND text must be "
  179.                                                             "in form #xxx"
  180.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  181.             }
  182.  
  183.             tCIDLib::CH* pszTmp = new tCIDLib::CH[pDlgItem->cchText+1];
  184.             strcpy(pszTmp, (((tCIDLib::CH*)pDlgTmpl)+pDlgItem->offText));
  185.  
  186.             if ((pszTmp[0] != '#') || (strlen(pszTmp) < 2))
  187.             {
  188.                 facCIDGui.LogMsg(   __FILE__
  189.                                     , "__clsMapPMClass"
  190.                                     , __LINE__
  191.                                     , "ICONWND or BMPWND text must be "
  192.                                                             "in form #xxx"
  193.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  194.             }
  195.             tCIDLib::CARD4  c4Id = atoi(&pszTmp[1]);
  196.  
  197.             // Allocate the control data and fill it in
  198.             *ppCtlData = new tCIDLib::CARD4;
  199.             *((tCIDLib::CARD4*)*ppCtlData) = c4Id;
  200.             *pc4CtlLen = sizeof(tCIDLib::CARD4);
  201.  
  202.             if (c4Tmp == SS_ICON)
  203.                 return CIDCLASS("ICONWND");
  204.              else
  205.                 return CIDCLASS("BMPWND");
  206.         }
  207.     }
  208.      else if (pClass == WC_LISTBOX)
  209.     {
  210.         return CIDCLASS("LISTBOXWND");
  211.     }
  212.      else if (pClass == WC_NOTEBOOK)
  213.     {
  214.         return CIDCLASS("NOTEBOOKWND");
  215.     }
  216.      else if (pClass == WC_SCROLLBAR)
  217.     {
  218.         return CIDCLASS("SCRBARWND");
  219.     }
  220.  
  221.     //
  222.     //  Was not one of the pre-defined classes, so we need to return it
  223.     //  as text.
  224.     //
  225.     tCIDLib::CH*  pszClass = (tCIDLib::CH*)pDlgTmpl;
  226.     pszClass += pDlgItem->offClassName;
  227.  
  228.     // Make the compiler happy
  229.     return CIDCLASS(pszClass);
  230. }
  231.  
  232.  
  233. //
  234. // FUNCTION/METHOD NAME: __pfnDlgProc(hwndDlg, c4Msg, mp1, mp2)
  235. //
  236. // DESCRIPTION:
  237. //
  238. //  This guy is the dialog proc for all dialogs. Dialogs get some messages
  239. //  before the WM_INITDLG so we have to filter those out and pass them to the
  240. //  default dialog handler. Once we see that the init dialog has been handled,
  241. //  we can start passing messages to the regular handler.
  242. // ---------------------------------------
  243. //   INPUT: hwndDlg is the handle of the dialog
  244. //          c4Msg is the message being recieved
  245. //          mp1, mp2 are the message parameters.
  246. //
  247. //  OUTPUT: None
  248. //
  249. //  RETURN: Depends upon the message
  250. //
  251. MRESULT WPROCEXP __pfnwpDlgProc(HWND                hwndDlg
  252.                                 , tCIDLib::CARD4    c4Msg
  253.                                 , MPARAM            mp1
  254.                                 , MPARAM            mp2)
  255. {
  256.     DIALOGWND*  pdlgTmp;
  257.  
  258.     if (c4Msg == WM_INITDLG)
  259.     {
  260.         WinSetWindowPtr(hwndDlg, QWL_USER, mp2);
  261.         return 0;
  262.     }
  263.  
  264.     // Get the window data to see if it is set up yet
  265.     pdlgTmp = (DIALOGWND*)WinQueryWindowPtr(hwndDlg, QWL_USER);
  266.  
  267.     //
  268.     //  If it is set up, then check for some messages that we want to handle
  269.     //  specially. If not one of those, then let it go to the normal handler.
  270.     //
  271.     if (pdlgTmp)
  272.     {
  273.         if (c4Msg == WM_CLOSE)
  274.         {
  275.             WinDismissDlg(hwndDlg, 0xFFFF);
  276.             return 0;
  277.         }
  278.         return _pfnwpMainSub(hwndDlg, c4Msg, mp1, mp2);
  279.     }
  280.  
  281.     // Otherwise, we have to let it go to the default handler
  282.     return WinDefDlgProc(hwndDlg, c4Msg, mp1, mp2);
  283. }
  284.  
  285.  
  286. //
  287. // FUNCTION/METHOD NAME: __pwndMakeCtrl(dlgwParent, clsCtrl, areaCtrl
  288. //                                      , c4Styles, c4Id, pCtlData)
  289. //
  290. // DESCRIPTION:
  291. //
  292. //  This method is called (by the constructor) for each control in the dialog
  293. //  if the user does not provide a callout, or if the user's callout returns
  294. //  0 to indicate that it wants us to create the control.
  295. // ---------------------------------------
  296. //   INPUT: dlgwParent is the parent dialog window that is calling.
  297. //          clsCtrl is the class name.
  298. //          areaCtrl is the area of the control.
  299. //          c4Styles are the style flags.
  300. //          c4Id is the id of the control.
  301. //          pCtlData is the control data if any. If none, then it is 0.
  302. //
  303. //  OUTPUT: None
  304. //
  305. //  RETURN: A pointer to the window object created
  306. //
  307. static WINDOW* __pwndMakeCtrl(  const   DIALOGWND&          dlgwParent
  308.                                 , const CIDCLASS&           clsCtrl
  309.                                 , const AREA&               areaCtrl
  310.                                 ,       tCIDLib::CARD4      c4Styles
  311.                                 ,       tCIDLib::CARD4      c4Id
  312.                                 , const tCIDLib::CH*        pszText
  313.                                 , const tCIDLib::VOID*      pCtlData)
  314. {
  315.     //
  316.     //  Switch on the class name and create the correct type of control. If
  317.     //  not a supported class type, then abort.
  318.     //
  319.     tCIDLib::eBOOL  bAuto;
  320.  
  321.     if (clsCtrl == CIDCLASS("BMPWND"))
  322.     {
  323.         // The control data contains the bitmap id
  324.         tCIDLib::CARD4  c4BmpId = *(tCIDLib::CARD4*)pCtlData;
  325.  
  326.         return new BMPWND(  dlgwParent
  327.                             , dlgwParent
  328.                             , tCIDGui::eSTATICSTYLES(c4Styles)
  329.                             , facCIDGui.wndTOP
  330.                             , c4BmpId
  331.                             , areaCtrl
  332.                             , c4Id);
  333.     }
  334.      else if (clsCtrl == CIDCLASS("CLRAREAWND"))
  335.     {
  336.         return new CLRAREAWND(  dlgwParent
  337.                                 , dlgwParent
  338.                                 , tCIDGui::eSTATICSTYLES(c4Styles)
  339.                                 , facCIDGui.wndTOP
  340.                                 , areaCtrl
  341.                                 , c4Id);
  342.     }
  343.      else if (clsCtrl == CIDCLASS("CHECKBOXWND"))
  344.     {
  345.         bAuto = (c4Styles & BS_AUTOCHECKBOX) ? tCIDLib::eTRUE : tCIDLib::eFALSE;
  346.         return new CHECKBOXWND( dlgwParent
  347.                                 , dlgwParent
  348.                                 , tCIDGui::eBUTTSTYLES(c4Styles)
  349.                                 , facCIDGui.wndTOP
  350.                                 , areaCtrl
  351.                                 , STRG256(pszText)
  352.                                 , c4Id
  353.                                 , bAuto);
  354.     }
  355.      else if (clsCtrl == CIDCLASS("MLEWND"))
  356.     {
  357.         return new MLEWND(  dlgwParent
  358.                             , dlgwParent
  359.                             , tCIDGui::eMLESTYLES(c4Styles)
  360.                             , facCIDGui.wndTOP
  361.                             , areaCtrl
  362.                             , STRG256(pszText)
  363.                             , c4Id);
  364.     }
  365.      else if (clsCtrl == CIDCLASS("ENTRYFLDWND"))
  366.     {
  367.         return new ENTRYFLDWND( dlgwParent
  368.                                 , dlgwParent
  369.                                 , tCIDGui::eEFLDSTYLES(c4Styles)
  370.                                 , facCIDGui.wndTOP
  371.                                 , areaCtrl
  372.                                 , STRG256(pszText)
  373.                                 , c4Id);
  374.     }
  375.      else if (clsCtrl == CIDCLASS("ICONWND"))
  376.     {
  377.         // The control data contains the icon id
  378.         tCIDLib::CARD4  c4IconId = *(tCIDLib::CARD4*)pCtlData;
  379.  
  380.         return new ICONWND( dlgwParent
  381.                             , dlgwParent
  382.                             , tCIDGui::eSTATICSTYLES(c4Styles)
  383.                             , facCIDGui.wndTOP
  384.                             , c4IconId
  385.                             , areaCtrl
  386.                             , c4Id);
  387.     }
  388.      else if (clsCtrl == CIDCLASS("GROUPBOXWND"))
  389.     {
  390.         return new GROUPBOXWND( dlgwParent
  391.                                 , dlgwParent
  392.                                 , tCIDGui::eSTATICSTYLES(c4Styles)
  393.                                 , facCIDGui.wndTOP
  394.                                 , areaCtrl
  395.                                 , STRG256(pszText)
  396.                                 , c4Id);
  397.     }
  398.      else if (clsCtrl == CIDCLASS("LISTBOXWND"))
  399.     {
  400.         //
  401.         //  Pass 0 for height and width of items, this will cause them to be
  402.         //  set to defaults, which will work for text list box in default
  403.         //  font.
  404.         //
  405.         return new LISTBOXWND(  dlgwParent
  406.                                 , dlgwParent
  407.                                 , tCIDGui::eLBSTYLES(c4Styles)
  408.                                 , facCIDGui.wndTOP
  409.                                 , 0, 0
  410.                                 , tCIDLib::eDEL_NODELETE
  411.                                 , tCIDLib::eFALSE
  412.                                 , areaCtrl
  413.                                 , c4Id);
  414.     }
  415.      else if (clsCtrl == CIDCLASS("NOTEBOOKWND"))
  416.     {
  417.         return new NOTEBOOKWND( dlgwParent
  418.                                 , dlgwParent
  419.                                 , tCIDGui::eBKSTYLES(c4Styles)
  420.                                 , facCIDGui.wndTOP
  421.                                 , areaCtrl
  422.                                 , c4Id);
  423.     }
  424.      else if (clsCtrl == CIDCLASS("PUSHBUTTWND"))
  425.     {
  426.         return new PUSHBUTTWND( dlgwParent
  427.                                 , dlgwParent
  428.                                 , tCIDGui::eBUTTSTYLES(c4Styles)
  429.                                 , facCIDGui.wndTOP
  430.                                 , areaCtrl
  431.                                 , STRG256(pszText)
  432.                                 , c4Id);
  433.     }
  434.      else if (clsCtrl == CIDCLASS("RADIOBUTTWND"))
  435.     {
  436.         bAuto = (c4Styles & BS_AUTORADIOBUTTON) ?
  437.                                     tCIDLib::eTRUE : tCIDLib::eFALSE;
  438.         return new RADIOBUTTWND(dlgwParent
  439.                                 , dlgwParent
  440.                                 , tCIDGui::eBUTTSTYLES(c4Styles)
  441.                                 , facCIDGui.wndTOP
  442.                                 , areaCtrl
  443.                                 , STRG256(pszText)
  444.                                 , c4Id
  445.                                 , bAuto);
  446.     }
  447.      else if (clsCtrl == CIDCLASS("SCRBARWND"))
  448.     {
  449.         //
  450.         //  We give the scroll bar a default range of 0..0 with the current
  451.         //  value of 0, which will insure that it is disabled until the user
  452.         //  sets it up.
  453.         //
  454.         return new SCRBARWND(   dlgwParent
  455.                                 , dlgwParent
  456.                                 , tCIDGui::eSBSTYLES(c4Styles)
  457.                                 , facCIDGui.wndTOP
  458.                                 , 0, 0, 0, 0, 0
  459.                                 , areaCtrl
  460.                                 , c4Id);
  461.     }
  462.      else if (clsCtrl == CIDCLASS("STATTXTWND"))
  463.     {
  464.         return new STATTXTWND(  dlgwParent
  465.                                 , dlgwParent
  466.                                 , tCIDGui::eSTATICSTYLES(c4Styles)
  467.                                 , facCIDGui.wndTOP
  468.                                 , areaCtrl
  469.                                 , STRG256(pszText)
  470.                                 , c4Id);
  471.     }
  472.      else if (clsCtrl == CIDCLASS("TRIBUTTWND"))
  473.     {
  474.         bAuto = (c4Styles & BS_AUTO3STATE) ? tCIDLib::eTRUE : tCIDLib::eFALSE;
  475.         return new TRIBUTTWND(  dlgwParent
  476.                                 , dlgwParent
  477.                                 , tCIDGui::eBUTTSTYLES(c4Styles)
  478.                                 , facCIDGui.wndTOP
  479.                                 , areaCtrl
  480.                                 , STRG256(pszText)
  481.                                 , c4Id
  482.                                 , bAuto);
  483.     }
  484.  
  485.     // It failed, so abort
  486.     facCIDGui.LogErr(   __FILE__
  487.                         , "DIALOGWND::_MakeCtrl"
  488.                         , __LINE__
  489.                         , GUIERR_DLG_TYPE_NOT_SUPPORTED
  490.                         , tCIDLib::eSEV_PROCESS_FATAL
  491.                         , tCIDLib::eCLASS_BADPARMS
  492.                         , clsCtrl);
  493.  
  494.     // Make the compiler happy
  495.     return 0;
  496. }
  497.  
  498.  
  499.  
  500. // -----------------------------------------------------------------------------
  501. //   CLASS: DIALOGWND
  502. //  PREFIX: dlgw
  503. //
  504. //  This class is the standard main window class.
  505. // -----------------------------------------------------------------------------
  506.  
  507. // -----------------------------------------------------------------------------
  508. //  DIALOGWND: Constructors/Destructors
  509. // -----------------------------------------------------------------------------
  510.  
  511. //
  512. // FUNCTION/METHOD NAME: DIALOGWND( wndOwner, c4Id, facSrc, pwndMakeCtrl
  513. //                                  , bDefMenus)
  514. //
  515. // DESCRIPTION:
  516. //
  517. //  This is the only constructor for dialog windows. Note that we do not
  518. //  subclass the frame here, because we can get the needed control via the
  519. //  dialog window mechanism which is really setting up the subclass for us.
  520. // ---------------------------------------
  521. //   INPUT: wndOwner is the owner window object.
  522. //          c4Id is the id value to give to the window. Defaults to 0.
  523. //          facSrc is the facility from which the dialog will be loaded.
  524. //          pwndMakeCtrl is the optional callout that the caller can provide
  525. //              that will be called for each control. This function should
  526. //              create the control object and return a pointer to it. If it
  527. //              is 0 or returns 0 for a particular control, then a local
  528. //              creation function will be called. It defaults to 0.
  529. //          bDefMenus indicates whether the child controls' default popup
  530. //              menus should be installed. It defaults to eTRUE.
  531. //
  532. //  OUTPUT: None
  533. //
  534. //  RETURN: None
  535. //
  536. PROCEXP DIALOGWND::DIALOGWND(   const   WINDOW&                 wndOwner
  537.                                 ,       tCIDLib::CARD4          c4Id
  538.                                 , const CIDFAC&                 facSrc
  539.                                 ,       tCIDGui::PFNMAKECTRL    pwndMakeCtrl
  540.                                 ,       tCIDLib::eBOOL          bDefMenus) :
  541.     FRAMEWND()
  542.     , __bModalProcessing(tCIDLib::eFALSE)
  543. {
  544.     POINTL          aptlMap[2];
  545.     tCIDLib::CARD4  c4Children;
  546.     HWND            hwndOwner, hwndDesktop, hwndTmp;
  547.     PCH             pchDlgBuf;
  548.     PDLGTEMPLATE    pDlg;
  549.     PDLGTITEM       pDlgItem;
  550.     tCIDLib::VOID*  pDlgRscBuf;
  551.     POINTL          ptlMouse;
  552.     WINDOW*         pwndCtrl;
  553.     RECTL           rectlFrame;
  554.  
  555.  
  556.     // Store the id away
  557.     _c4Id(c4Id);
  558.  
  559.     // We need to know the screen size in a couple of places below
  560.     LONG   lScrX = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
  561.     LONG   lScrY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
  562.  
  563.     //
  564.     //  Now we need to load the dialog resource. We will get back a readonly
  565.     //  memory buffer that we can trash after we have created the dialog.
  566.     //
  567.     facSrc.LoadResource(tCIDLib::eRSCTYPE_DIALOG, c4Id, &pDlgRscBuf);
  568.  
  569.     //
  570.     //  Get a pointer to the buffer as a dialog template and start
  571.     //  interpreting it. The 0th entry in the pDlb->adlgti[] array is the
  572.     //  record for the dialog itself. All the controls are children of it.
  573.     //  It contains a field that tells us how many children it has.
  574.     //
  575.     //  Also, get a pointer to the buffer as a character pointer which will be
  576.     //  used to access data at particular offsets in the buffer.
  577.     //
  578.     pDlg        = (PDLGTEMPLATE)pDlgRscBuf;
  579.     pchDlgBuf   = (PCH)pDlgRscBuf;
  580.     pDlgItem    = &(pDlg->adlgti[0]);
  581.     c4Children  = pDlgItem->cChildren;
  582.  
  583.     //
  584.     //  According to the styles, the origin is relative to the screen, parent
  585.     //  window, or mouse. If relative to the mouse, get the mouse position and
  586.     //  add that to the origin.
  587.     //
  588.     aptlMap[0].x = pDlgItem->x;
  589.     aptlMap[0].y = pDlgItem->y;
  590.     aptlMap[1].x = pDlgItem->x + pDlgItem->cx;
  591.     aptlMap[1].y = pDlgItem->y + pDlgItem->cy;
  592.  
  593.     // Map the dialog coordinates into window coordinates
  594.     WinMapDlgPoints(HWND_DESKTOP, aptlMap, 2, 1);
  595.  
  596.     if (pDlgItem->flStyle & FS_MOUSEALIGN)
  597.     {
  598.         WinQueryPointerPos(HWND_DESKTOP, &ptlMouse);
  599.         aptlMap[0].x += ptlMouse.x;
  600.         aptlMap[0].y += ptlMouse.y;
  601.         aptlMap[1].x += ptlMouse.x;
  602.         aptlMap[1].y += ptlMouse.y;
  603.     }
  604.  
  605.     //
  606.     //  Decide who the owner really is. It is the first window up the parent
  607.     //  chain that is a direct child of HWND_DESKTOP, or NULL if we don't find
  608.     //  one. This insures correct disabling of the application's windows when
  609.     //  the dialog is processed modally.
  610.     //
  611.     hwndOwner   = wndOwner.hwndThis();
  612.     hwndDesktop = WinQueryDesktopWindow(WinQueryAnchorBlock(hwndOwner)
  613.                                         , HDC(0));
  614.     while (1)
  615.     {
  616.         hwndTmp = WinQueryWindow(hwndOwner, QW_PARENT);
  617.         if (hwndTmp == hwndDesktop)
  618.             break;
  619.  
  620.         hwndOwner = hwndTmp;
  621.         if (!hwndOwner)
  622.             break;
  623.     }
  624.  
  625.     //
  626.     //  Create the frame window that will serve as the dialog frame. Make
  627.     //  sure that it is initially invisible. The frame creation flags are
  628.     //  in the dialog tempalte as is the frame text. It is also 0 sized
  629.     //  and positioned since we don't know these values yet.
  630.     //
  631.     FRAMECDATA              FrameData;
  632.     FrameData.cb            = sizeof(FrameData);
  633.     FrameData.flCreateFlags = *(ULONG*)(pchDlgBuf + pDlgItem->offCtlData);
  634.     FrameData.hmodResources = 0;
  635.     FrameData.idResources   = -1;
  636.  
  637.     _hwndThis(  WinCreateWindow(HWND_DESKTOP
  638.                                 , WC_FRAME
  639.                                 , PSZ(pchDlgBuf + pDlgItem->offText)
  640.                                 , pDlgItem->flStyle & ~WS_VISIBLE
  641.                                 , 0
  642.                                 , 0
  643.                                 , 0
  644.                                 , 0
  645.                                 , hwndOwner
  646.                                 , HWND_TOP
  647.                                 , pDlgItem->id
  648.                                 , &FrameData
  649.                                 , 0));
  650.     if (!hwndThis())
  651.     {
  652.         // It failed, so we need to log a message and abort
  653.         facCIDGui.LogLastSysErr(    __FILE__
  654.                                     , "DIALOGWND::DIALOGWND"
  655.                                     , __LINE__
  656.                                     , "WinCreateWindow failed"
  657.                                     , tCIDLib::eSEV_PROCESS_FATAL);
  658.     }
  659.  
  660.     // Store the object pointer in the window's spare data
  661.     WinSetWindowPtr(hwndThis(), QWL_USER, (tCIDLib::VOID*)((WINDOW*)this));
  662.  
  663.     //
  664.     //  Calculate the size of a frame that would surround a client area of
  665.     //  the size of the dialog.
  666.     //
  667.     rectlFrame.xLeft       = aptlMap[0].x;
  668.     rectlFrame.yBottom     = aptlMap[0].y;
  669.     rectlFrame.xRight      = aptlMap[1].x;
  670.     rectlFrame.yTop        = aptlMap[1].y;
  671.     WinCalcFrameRect(hwndThis(), &rectlFrame, FALSE);
  672.  
  673.     //
  674.     //  Make sure that the dialog does not go off of the screen. If so, bring
  675.     //  it back as long as it would not make the origin go negative.
  676.     //
  677.     if (rectlFrame.xRight > lScrX)
  678.     {
  679.         LONG   lTmp;
  680.         if ((rectlFrame.xLeft - (rectlFrame.xRight-lScrX)) < 0)
  681.             lTmp = rectlFrame.xLeft;
  682.          else
  683.             lTmp = rectlFrame.xRight-lScrX;
  684.         rectlFrame.xLeft    -= lTmp;
  685.         rectlFrame.xRight   -= lTmp;
  686.     }
  687.  
  688.     if (rectlFrame.yTop > lScrY)
  689.     {
  690.         LONG   lTmp;
  691.         if ((rectlFrame.yBottom - (rectlFrame.yTop-lScrY)) < 0)
  692.             lTmp = rectlFrame.yBottom;
  693.          else
  694.             lTmp = rectlFrame.yTop-lScrY;
  695.         rectlFrame.yBottom  -= lTmp;
  696.         rectlFrame.yTop     -= lTmp;
  697.     }
  698.  
  699.     // Now size the frame to the calculated size
  700.     WinSetWindowPos(hwndThis()
  701.                     , 0
  702.                     , rectlFrame.xLeft
  703.                     , rectlFrame.yBottom
  704.                     , (rectlFrame.xRight-rectlFrame.xLeft)
  705.                     , (rectlFrame.yTop-rectlFrame.yBottom)
  706.                     , SWP_SIZE | SWP_MOVE);
  707.  
  708.     //
  709.     //  Use pres params to make the frame window paint its background using
  710.     //  the dialog background color, not the usual window color.
  711.     //
  712.     LONG lTmp = WinQuerySysColor(HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0);
  713.     WinSetPresParam(hwndThis()
  714.                     , PP_BACKGROUNDCOLOR
  715.                     , sizeof(LONG)
  716.                     , &lTmp);
  717.  
  718.     // Force the frame to update it's controls
  719.     WinSendMsg(hwndThis(), WM_UPDATEFRAME, MPARAM(FrameData.flCreateFlags), 0);
  720.  
  721.     //
  722.     //  Set the default handler to the PM frame proc. If the c4Process()
  723.     //  method is called later, we will change this to the default dialog
  724.     //  proc.
  725.     //
  726.     _pfnWndProc(WinSubclassWindow(hwndThis(), _pfnwpMainSub));
  727.  
  728.     if (!_pfnWndProc())
  729.     {
  730.         // It failed, so we need to log a message and abort
  731.         facCIDGui.LogLastSysErr(__FILE__
  732.                                 , "DIALOGWND::DIALOGWND"
  733.                                 , __LINE__
  734.                                 , "WinSubclassWindow failed"
  735.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  736.     }
  737.  
  738.     //
  739.     //  Query the size of the border. Since dialogs don't have a client
  740.     //  window, we have to offset all of the control origins by the width
  741.     //  of the dialog border.
  742.     //
  743.     WPOINT  wpntBorder;
  744.     WinSendMsg(hwndThis(), WM_QUERYBORDERSIZE, MPARAM(&wpntBorder), 0);
  745.  
  746.     //
  747.     //  Now loop through the children and create window objects for each one.
  748.     //  We call the callout routine for each one to do the creation. This
  749.     //  allows derived classes to handle the creation.
  750.     //
  751.     //  Before we enter the loop, bump up the dialog item pointer to point to
  752.     //  the last child. This is because of the way that the WS_GROUP style is
  753.     //  used. Creating the children in reverse will cause the groups to work
  754.     //  correctly.
  755.     //
  756.     CIDCLASS        clsCtrl("");
  757.     tCIDLib::VOID*  pCtlData;
  758.     tCIDLib::CARD4  c4CtlLen;
  759.     tCIDLib::CH*    pszText;
  760.  
  761.     pDlgItem += c4Children;
  762.     for (tCIDLib::INT4 i4Ind = c4Children-1; i4Ind >= 0; i4Ind--)
  763.     {
  764.         //
  765.         //  Make the dialog coordinates into window coordinates. Make sure to
  766.         //  add in the border width to the origin.
  767.         //
  768.         aptlMap[0].x = pDlgItem->x+wpntBorder.x;
  769.         aptlMap[0].y = pDlgItem->y+wpntBorder.y;
  770.         aptlMap[1].x = pDlgItem->cx;
  771.         aptlMap[1].y = pDlgItem->cy;
  772.         WinMapDlgPoints(HWND_DESKTOP, aptlMap, 2, 1);
  773.  
  774.         // Get the class name and control data
  775.         clsCtrl = __clsMapPMClass(pDlg, pDlgItem, &pCtlData, &c4CtlLen);
  776.  
  777.         // Get a pointer to the text, if any
  778.         pszText = 0;
  779.         if (pDlgItem->cchText)
  780.             pszText = (tCIDLib::CH*)(pchDlgBuf+pDlgItem->offText);
  781.  
  782.         //
  783.         //  Now we call the user's callout (if he provided one). If not, or his
  784.         //  returns 0, we call the local default.
  785.         //
  786.         pwndCtrl = 0;
  787.         if (pwndMakeCtrl)
  788.         {
  789.             pwndCtrl = pwndMakeCtrl(*this
  790.                                     , clsCtrl
  791.                                     , AREA( aptlMap[0].x
  792.                                             , aptlMap[0].y
  793.                                             , aptlMap[1].x
  794.                                             , aptlMap[1].y)
  795.                                     , pDlgItem->flStyle
  796.                                     , pDlgItem->id
  797.                                     , pszText
  798.                                     , pCtlData);
  799.         }
  800.  
  801.         if (!pwndCtrl)
  802.         {
  803.             //
  804.             //  We can tell PM controls because the class name length is 0.
  805.             //  This is possible because the PM classes are numeric, not
  806.             //  text.
  807.             //
  808.             if (pDlgItem->cchClassName != 0)
  809.             {
  810.                 // Just log a message and go to the next child
  811.                 facCIDGui.LogErr(   __FILE__
  812.                                     , "DIALOGWND::DIALOGWND"
  813.                                     , __LINE__
  814.                                     , GUIERR_DLG_TYPE_NOT_SUPPORTED
  815.                                     , tCIDLib::eSEV_WARNING
  816.                                     , tCIDLib::eCLASS_BADPARMS
  817.                 , STRG128((tCIDLib::CH*)(pchDlgBuf+pDlgItem->offClassName)));
  818.                 pDlgItem--;
  819.                 continue;
  820.             }
  821.  
  822.             pwndCtrl =
  823.                 __pwndMakeCtrl( *this
  824.                                 , clsCtrl
  825.                                 , AREA( aptlMap[0].x
  826.                                         , aptlMap[0].y
  827.                                         , aptlMap[1].x
  828.                                         , aptlMap[1].y)
  829.                                 , pDlgItem->flStyle
  830.                                 , pDlgItem->id
  831.                                 , pszText
  832.                                 , pCtlData);
  833.         }
  834.  
  835.         // Now apply the default menu if we need to
  836.         if (bDefMenus)
  837.             pwndCtrl->SetDefMenu();
  838.  
  839.         //
  840.         //  Now, if there are any presentation parameters, set them on
  841.         //  the window. We don't know how many parms but know the size of
  842.         //  the parm buffer. So we track the count of bytes processed and
  843.         //  fall out when we exceed the amount available.
  844.         //
  845.         if (pDlgItem->offPresParams != tCIDLib::c2MAXCARD)
  846.         {
  847.             tCIDLib::CARD4  c4ByteCnt = 8;
  848.             PARAM*          pParm;
  849.             PRESPARAMS*     pPresParms;
  850.  
  851.             pPresParms = (PRESPARAMS*)(pchDlgBuf+pDlgItem->offPresParams);
  852.             pParm = (PARAM*)(pchDlgBuf+(pDlgItem->offPresParams+4));
  853.             while (c4ByteCnt < pPresParms->cb)
  854.             {
  855.                 if (!WinSetPresParam(   *pwndCtrl
  856.                                         , pParm->id
  857.                                         , pParm->cb
  858.                                         , (tCIDLib::VOID*)pParm->ab))
  859.                 {
  860.                     facCIDGui.LogLastSysErr(__FILE__
  861.                                             , "DIALOGWND::DIALOGWND"
  862.                                             , __LINE__
  863.                                             , "WinSetPresParam failed"
  864.                                             , tCIDLib::eSEV_PROCESS_FATAL);
  865.                 }
  866.  
  867.                 // Move to the next param
  868.                 pParm = (PARAM*)(((tCIDLib::CARD1*)pParm) + 8 + pParm->cb);
  869.  
  870.                 // Bump up the count of bytes processed.
  871.                 c4ByteCnt += 8 + pParm->cb;
  872.             }
  873.         }
  874.  
  875.         //
  876.         //  Delete the control data, if any. The control will have made its
  877.         //  own copy of the data.
  878.         //
  879.         if (pCtlData)
  880.             delete pCtlData;
  881.  
  882.         //
  883.         //  If this is the index of the control that is to get the initial
  884.         //  focus, then give it the focus now.
  885.         //
  886.         if (pDlg->iItemFocus == i4Ind)
  887.             pwndCtrl->TakeFocus();
  888.  
  889.         // Move to the next child
  890.         pDlgItem--;
  891.     }
  892.  
  893.     //
  894.     //  If there was no focus item, then we have to pick one. So look for
  895.     //  the first tab item.
  896.     //
  897.     if (pDlg->iItemFocus == 0xFFFF)
  898.     {
  899.         WinSetFocus(HWND_DESKTOP
  900.                     , WinEnumDlgItem(   *this
  901.                                         , 0
  902.                                         , EDI_FIRSTTABITEM));
  903.     }
  904.  
  905.     // Activate the frame
  906.     Activate();
  907.  
  908.     // Free the dialog template buffer now since we are done with it
  909.     facCIDLib.FreeResource(pDlgRscBuf);
  910. }
  911.  
  912.  
  913. //
  914. // FUNCTION/METHOD NAME: ~DIALOGWND()
  915. //
  916. // DESCRIPTION:
  917. //
  918. //  The destructor does not need to do anything at this time.
  919. // ---------------------------------------
  920. //   INPUT: None
  921. //
  922. //  OUTPUT: None
  923. //
  924. //  RETURN: None
  925. //
  926. PROCEXP DIALOGWND::~DIALOGWND()
  927. {
  928.     
  929. }
  930.  
  931.  
  932. // -----------------------------------------------------------------------------
  933. //  DIALOGWND: Public, inherited methods
  934. // -----------------------------------------------------------------------------
  935.  
  936. //
  937. // FUNCTION/METHOD NAME: FormatToStr(strbDest) const
  938. //
  939. // DESCRIPTION:
  940. //
  941. //  This method will format this object to the passed string buffer. For this
  942. //  class, we just format some debug info since this guy has no outwardly
  943. //  visible data members.
  944. // ---------------------------------------
  945. //   INPUT: None
  946. //
  947. //  OUTPUT: strbDest is the string buffer to format into.
  948. //
  949. //  RETURN: None
  950. //
  951. tCIDLib::VOID PROCEXP DIALOGWND::FormatToStr(STRGBUF& strbDest) const
  952. {
  953.     strbDest << "Duh?";
  954. }
  955.  
  956.  
  957. // -----------------------------------------------------------------------------
  958. //  DIALOGWND: Public, virtual methods
  959. // -----------------------------------------------------------------------------
  960.  
  961. //
  962. // FUNCTION/METHOD NAME: c4Process()
  963. //
  964. // DESCRIPTION:
  965. //
  966. //  This method will process the dialog window modally.
  967. // ---------------------------------------
  968. //   INPUT: None
  969. //
  970. //  OUTPUT: None
  971. //
  972. //  RETURN: The value passed to the Dismiss() method will be returned.
  973. //
  974. tCIDLib::CARD4 PROCEXP DIALOGWND::c4Process()
  975. {
  976.     // Set the modal processing flag
  977.     __bModalProcessing = tCIDLib::eTRUE;
  978.  
  979.     // Change the default proc to the default dialog proc
  980.     _pfnWndProc(WinDefDlgProc);
  981.  
  982.     // Process the dialog
  983.     tCIDLib::CARD4 c4Ret = WinProcessDlg(*this);
  984.  
  985.     return c4Ret;
  986. }
  987.  
  988.  
  989. //
  990. // FUNCTION/METHOD NAME: Dismiss(c4RetStatus)
  991. //
  992. // DESCRIPTION:
  993. //
  994. //  This method will dismiss the dialog window, which should currently be in
  995. //  a modal processing state. If not, a fatal error will be generated.
  996. // ---------------------------------------
  997. //   INPUT: c4RetStatus is returned to the thread that called c4Process() as
  998. //              the return value of c4Process().
  999. //
  1000. //  OUTPUT: None
  1001. //
  1002. //  RETURN: The return status that should be passed back to the caller of
  1003. //              c4Process().
  1004. //
  1005. tCIDLib::VOID PROCEXP DIALOGWND::Dismiss(tCIDLib::CARD4 c4RetStatus)
  1006. {
  1007.     if (!__bModalProcessing)
  1008.     {
  1009.         facCIDGui.LogMsg(   __FILE__
  1010.                             , "DIALOGWND::Dismiss"
  1011.                             , __LINE__
  1012.                             , "Dialog was not being modally processed"
  1013.                             , tCIDLib::eSEV_PROCESS_FATAL);
  1014.     }
  1015.  
  1016.     // Clear the modal processing flag
  1017.     __bModalProcessing = tCIDLib::eFALSE;
  1018.  
  1019.     // Dismiss the dialog
  1020.     if (!WinDismissDlg(*this, c4RetStatus))
  1021.     {
  1022.         facCIDGui.LogLastSysErr(__FILE__
  1023.                                 , "DIALOGWND::Dismiss"
  1024.                                 , __LINE__
  1025.                                 , "Dialog dismiss failed"
  1026.                                 , tCIDLib::eSEV_PROCESS_FATAL);
  1027.     }
  1028. }
  1029.  
  1030.  
  1031. // -----------------------------------------------------------------------------
  1032. //  DIALOGWND: Protected, inherited methods
  1033. // -----------------------------------------------------------------------------
  1034.  
  1035. //
  1036. // FUNCTION/METHOD NAME: _bIsEqual(objTarget) const
  1037. //
  1038. // DESCRIPTION:
  1039. //
  1040. //  This method will see if this object is equal to the passed object. If the
  1041. //  passed object is not a DIALOGWND object, then eFALSE is returned, else the
  1042. //  data members are compared.
  1043. // ---------------------------------------
  1044. //   INPUT: objTarget is the target object to compare against
  1045. //
  1046. //  OUTPUT: None
  1047. //
  1048. //  RETURN: eTRUE if the objects are equal, else eFALSE.
  1049. //
  1050. tCIDLib::eBOOL PROCEXP DIALOGWND::_bIsEqual(const CIDOBJECT& objTarget) const
  1051. {
  1052.     //
  1053.     //  Call our parent's version first. We call it regardless of the depth of
  1054.     //  the comparison
  1055.     //
  1056.     if (!FRAMEWND::_bIsEqual(objTarget))
  1057.         return tCIDLib::eFALSE;
  1058.  
  1059.     // Look at the object as a DIALOGWND object
  1060.  
  1061.     return tCIDLib::eTRUE;
  1062. }
  1063.