home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR24 / EDMI5.ZIP / CNR2.ZIP / CNR2.C < prev    next >
Text File  |  1993-06-18  |  23KB  |  584 lines

  1. #define INCL_WININPUT
  2. #define INCL_WINMENUS
  3. #define INCL_WINPOINTERS
  4. #define INCL_WINSTDCNR
  5. #define INCL_WINSYS
  6. #define INCL_WINWINDOWMGR
  7. #include <os2.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "rc.h"
  12.  
  13. #define CLS_CLIENT               "Cnr2Class"
  14.  
  15. #define NUM_YEARS                10
  16.  
  17. //-------------------------------------------------------------------------
  18. // Useful macros:
  19. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  20. // SETMENUATTR sets the specified attribute of the menuitem having the
  21. // specified id.
  22. //-------------------------------------------------------------------------
  23. #define SETMENUATTR(hwndMenu,usId,usAttr,bSet) \
  24. WinSendMsg(hwndMenu, \
  25.            MM_SETITEMATTR, \
  26.            MPFROM2SHORT(usId,TRUE), \
  27.            MPFROM2SHORT(usAttr,(bSet?usAttr:0)))
  28.  
  29. typedef struct _CLIENTDATA {                          // @1
  30.    USHORT usSzStruct;         // Size of the structure
  31.    HAB habAnchor;             // Anchor block of the window
  32.    HWND hwndFrame;            // Frame of the client (== parent)
  33.    HWND hwndCnr;              // Container window
  34.    HPOINTER hptrYear;         // Icon for the year records
  35.    HPOINTER hptrMonth;        // Icon for the month records
  36.    HWND hwndWndMenu;          // Menu window
  37. } CLIENTDATA, *PCLIENTDATA;
  38.  
  39. typedef struct _MYCNRREC {
  40.    MINIRECORDCORE mrcCore;    // Base structure
  41.    CHAR achText[64];          // Icon text
  42. } MYCNRREC, *PMYCNRREC;
  43.  
  44. //-------------------------------------------------------------------------
  45. // PFNSRCH is used by searchCnr().  The parameters are:  container window
  46. // handle, record pointer, and user-data pointer, respectively.
  47. //-------------------------------------------------------------------------
  48. typedef BOOL (*PFNSRCH)(HWND,PVOID,PVOID);
  49.  
  50. const PCHAR apchMonths[]={
  51.    "January",
  52.    "February",
  53.    "March",
  54.    "April",
  55.    "May",
  56.    "June",
  57.    "July",
  58.    "August",
  59.    "September",
  60.    "October",
  61.    "November",
  62.    "December"
  63. };
  64.  
  65. BOOL searchSelect(HWND hwndCnr,PMYCNRREC pmcrRecord,PBOOL pbSelect)
  66. //-------------------------------------------------------------------------
  67. // This function is used to select/deselect all records.  Note that it
  68. // always returns FALSE, so that searchCnr() will traverse the entire
  69. // record list.
  70. //
  71. // Input:  hwndCnr - handle of the container window
  72. //         pmcrRecord - pointer to the container record
  73. //         pbSelect - pointer to a BOOL specifying whether to select the
  74. //                    record or not
  75. //-------------------------------------------------------------------------
  76. {
  77.    WinSendMsg(hwndCnr,
  78.               CM_SETRECORDEMPHASIS,
  79.               MPFROMP(pmcrRecord),
  80.               MPFROM2SHORT(*pbSelect,CRA_SELECTED));
  81.    return FALSE;
  82. }
  83.  
  84. BOOL initCnr(PCLIENTDATA pcdData)
  85. //-------------------------------------------------------------------------
  86. // This function creates and inserts all of the container records
  87. //
  88. // Input:  pcdData - points to the CLIENTDATA structure for the client
  89. // Returns:  TRUE if successful, FALSE otherwise
  90. //-------------------------------------------------------------------------
  91. {
  92.    USHORT usYear;
  93.    PMYCNRREC pmcrYear;
  94.    RECORDINSERT riInsert;
  95.    USHORT usMonth;
  96.    PMYCNRREC pmcrMonth;
  97.    PMYCNRREC pmcrCurrent;
  98.  
  99.    //----------------------------------------------------------------------
  100.    // As much as I would have liked to allocate 12*NUM_YEARS records
  101.    // and simply call CM_INSERTRECORD the appropriate number of times to
  102.    // establish the correct hierarchy, the container apparently doesn't
  103.    // like it when you say there's only 1 record, yet the preccNextRecord
  104.    // field is not NULL.
  105.    //
  106.    // So, we gotta allocate and insert one record for the year, then 12
  107.    // records for that year's months, repeat ad nauseum.
  108.    //----------------------------------------------------------------------
  109.  
  110.    for (usYear=0; usYear<NUM_YEARS; usYear++) {       // @2
  111.       //-------------------------------------------------------------------
  112.       // Allocate, initialize, and insert the year record
  113.       //-------------------------------------------------------------------
  114.       pmcrYear=(PMYCNRREC)PVOIDFROMMR(WinSendMsg(pcdData->hwndCnr,
  115.                                                  CM_ALLOCRECORD,
  116.                                                  MPFROMLONG(sizeof(MYCNRREC)-
  117.                                                                sizeof(MINIRECORDCORE)),
  118.                                                  MPFROMSHORT(1)));
  119.       if (pmcrYear==NULL) {
  120.          WinAlarm(HWND_DESKTOP,WA_ERROR);
  121.          return FALSE;
  122.       } /* endif */
  123.  
  124.       sprintf(pmcrYear->achText,"Year %04d",1993-usYear);
  125.  
  126.       pmcrYear->mrcCore.pszIcon=pmcrYear->achText;
  127.       pmcrYear->mrcCore.hptrIcon=pcdData->hptrYear;
  128.  
  129.       riInsert.cb=sizeof(RECORDINSERT);
  130.       riInsert.pRecordOrder=(PRECORDCORE)CMA_FIRST;
  131.       riInsert.pRecordParent=NULL;
  132.       riInsert.fInvalidateRecord=FALSE;
  133.       riInsert.zOrder=CMA_TOP;
  134.       riInsert.cRecordsInsert=1;
  135.  
  136.       WinSendMsg(pcdData->hwndCnr,
  137.                  CM_INSERTRECORD,
  138.                  MPFROMP(pmcrYear),
  139.                  MPFROMP(&riInsert));
  140.  
  141.       //-------------------------------------------------------------------
  142.       // Allocate, initialize, and insert the month records
  143.       //-------------------------------------------------------------------
  144.       pmcrMonth=(PMYCNRREC)PVOIDFROMMR(WinSendMsg(pcdData->hwndCnr,
  145.                                                   CM_ALLOCRECORD,
  146.                                                   MPFROMLONG(sizeof(MYCNRREC)-
  147.                                                                 sizeof(MINIRECORDCORE)),
  148.                                                   MPFROMSHORT(12)));
  149.       if (pmcrMonth==NULL) {
  150.          WinAlarm(HWND_DESKTOP,WA_ERROR);
  151.          return FALSE;
  152.       } /* endif */
  153.  
  154.       pmcrCurrent=pmcrMonth;
  155.  
  156.       for (usMonth=0; usMonth<12; usMonth++) {
  157.          strcpy(pmcrCurrent->achText,apchMonths[usMonth]);
  158.  
  159.          pmcrCurrent->mrcCore.pszIcon=pmcrCurrent->achText;
  160.          pmcrCurrent->mrcCore.hptrIcon=pcdData->hptrMonth;
  161.  
  162.          pmcrCurrent=(PMYCNRREC)pmcrCurrent->mrcCore.preccNextRecord;
  163.       } /* endfor */
  164.  
  165.       riInsert.cb=sizeof(RECORDINSERT);
  166.       riInsert.pRecordOrder=(PRECORDCORE)CMA_FIRST;
  167.       riInsert.pRecordParent=(PRECORDCORE)pmcrYear;
  168.       riInsert.fInvalidateRecord=FALSE;
  169.       riInsert.zOrder=CMA_TOP;
  170.       riInsert.cRecordsInsert=12;
  171.  
  172.       WinSendMsg(pcdData->hwndCnr,
  173.                  CM_INSERTRECORD,
  174.                  MPFROMP(pmcrMonth),
  175.                  MPFROMP(&riInsert));
  176.    } /* endfor */
  177.  
  178.    //----------------------------------------------------------------------
  179.    // Arrange the records and invalidate them so that they get redrawn in
  180.    // their proper positions.
  181.    //----------------------------------------------------------------------
  182.    WinSendMsg(pcdData->hwndCnr,CM_ARRANGE,0,0);
  183.  
  184.    WinSendMsg(pcdData->hwndCnr,                       // @3
  185.               CM_INVALIDATERECORD,
  186.               MPFROMP(NULL),
  187.               MPFROM2SHORT(0,CMA_REPOSITION|CMA_ERASE|CMA_TEXTCHANGED));
  188.    return TRUE;
  189. }
  190.  
  191. BOOL setCascadeDefault(HWND hwndMenu,USHORT usSubmenu,USHORT usDefault)
  192. //-------------------------------------------------------------------------
  193. // This function sets the default menuitem for the specified cascade menu.
  194. //
  195. // Input:  hwndMenu - specifies the menu window handle.
  196. //         usSubmenu - specifies the id of the cascade menu.
  197. //         usDefault - specifies the id of the default menuitem.
  198. // Returns:  TRUE if successful, FALSE otherwise.
  199. //-------------------------------------------------------------------------
  200. {
  201.    MENUITEM miItem;                                   // @4
  202.    ULONG ulStyle;
  203.  
  204.    WinSendMsg(hwndMenu,
  205.               MM_QUERYITEM,
  206.               MPFROM2SHORT(usSubmenu,TRUE),
  207.               MPFROMP(&miItem));
  208.    ulStyle=WinQueryWindowULong(miItem.hwndSubMenu,QWL_STYLE);
  209.    ulStyle|=MS_CONDITIONALCASCADE;
  210.    WinSetWindowULong(miItem.hwndSubMenu,QWL_STYLE,ulStyle);
  211.  
  212.    WinSendMsg(miItem.hwndSubMenu,
  213.               MM_SETDEFAULTITEMID,
  214.               MPFROM2SHORT(usDefault,FALSE),
  215.               0L);
  216.    SETMENUATTR(miItem.hwndSubMenu,usDefault,MIA_CHECKED,TRUE);
  217.  
  218.    return TRUE;
  219. }
  220.  
  221. PVOID searchCnr(HWND hwndCnr,PFNSRCH pfnSearch,PVOID pvUser,PVOID pvRsrvd)
  222. //-------------------------------------------------------------------------
  223. // This function performs a post-traversal search on the container records
  224. // until either 1) pfnSearch() returns TRUE (specifying that the record
  225. // matched the criteria in pvUser) or 2) the last record is checked without
  226. // a match being found.  The record, if any, is returned.
  227. //
  228. // Input:  hwndCnr - handle of the container
  229. //         pfnSearch - pointer to the search function
  230. //         pvUser - pointer to user-data, passed to pfnSearch()
  231. //         pvRsrvd - reserved and must be NULL
  232. // Returns:  record found, or NULL otherwise
  233. //-------------------------------------------------------------------------
  234. {
  235.    PVOID pvChild;                                     // @5
  236.    PVOID pvResult;
  237.  
  238.    //----------------------------------------------------------------------
  239.    // If the reserved parm is NULL, this is not a recursive call.  Get the
  240.    // first child of the record specified here (or the first record if
  241.    // pvRsrvd is NULL).
  242.    //----------------------------------------------------------------------
  243.    if (pvRsrvd==NULL) {
  244.       pvChild=PVOIDFROMMR(WinSendMsg(hwndCnr,
  245.                                      CM_QUERYRECORD,
  246.                                      MPFROMP(NULL),
  247.                                      MPFROM2SHORT(CMA_FIRST,CMA_ITEMORDER)));
  248.    } else {
  249.       pvChild=PVOIDFROMMR(WinSendMsg(hwndCnr,
  250.                                      CM_QUERYRECORD,
  251.                                      MPFROMP(pvRsrvd),
  252.                                      MPFROM2SHORT(CMA_FIRSTCHILD,CMA_ITEMORDER)));
  253.    } /* endif */
  254.  
  255.    //----------------------------------------------------------------------
  256.    // Process each child
  257.    //----------------------------------------------------------------------
  258.    while (pvChild!=NULL) {
  259.       pvResult=searchCnr(hwndCnr,pfnSearch,pvUser,pvChild);
  260.       if (pvResult!=NULL) {
  261.          return pvResult;
  262.       } /* endif */
  263.  
  264.       pvChild=PVOIDFROMMR(WinSendMsg(hwndCnr,
  265.                                      CM_QUERYRECORD,
  266.                                      MPFROMP(pvChild),
  267.                                      MPFROM2SHORT(CMA_NEXT,CMA_ITEMORDER)));
  268.    } /* endwhile */
  269.  
  270.    //----------------------------------------------------------------------
  271.    // Finally, check ourselves
  272.    //----------------------------------------------------------------------
  273.    if (pvRsrvd!=NULL) {
  274.       if ((*pfnSearch)(hwndCnr,pvRsrvd,pvUser)) {
  275.          return pvRsrvd;
  276.       } else {
  277.          return NULL;
  278.       } /* endif */
  279.    } else {
  280.       //-------------------------------------------------------------------
  281.       // If we reach here, it means we traversed the entire container
  282.       // without finding a match
  283.       //-------------------------------------------------------------------
  284.       return NULL;
  285.    } /* endif */
  286. }
  287.  
  288. MRESULT EXPENTRY clientProc(HWND hwndWnd,
  289.                             ULONG ulMsg,
  290.                             MPARAM mpParm1,
  291.                             MPARAM mpParm2)
  292. {
  293.    PCLIENTDATA pcdData;
  294.  
  295.    pcdData=WinQueryWindowPtr(hwndWnd,0);
  296.  
  297.    switch (ulMsg) {
  298.    case WM_CREATE:
  299.       {
  300.          CHAR achFont[64];
  301.  
  302.          //----------------------------------------------------------------
  303.          // Allocate memory for the instance data and initialize it
  304.          //----------------------------------------------------------------
  305.          pcdData=malloc(sizeof(CLIENTDATA));          // @6
  306.          if (pcdData==NULL) {
  307.             WinAlarm(HWND_DESKTOP,WA_ERROR);
  308.             return MRFROMSHORT(TRUE);
  309.          } /* endif */
  310.  
  311.          WinSetWindowPtr(hwndWnd,0,pcdData);
  312.  
  313.          pcdData->usSzStruct=sizeof(CLIENTDATA);
  314.          pcdData->habAnchor=WinQueryAnchorBlock(hwndWnd);
  315.          pcdData->hwndFrame=WinQueryWindow(hwndWnd,QW_PARENT);
  316.  
  317.          //----------------------------------------------------------------
  318.          // Create the container.  Note the window styles used.
  319.          //----------------------------------------------------------------
  320.          pcdData->hwndCnr=WinCreateWindow(hwndWnd,
  321.                                           WC_CONTAINER,
  322.                                           "",
  323.                                           CCS_MINIRECORDCORE | CCS_EXTENDSEL,
  324.                                           0,
  325.                                           0,
  326.                                           0,
  327.                                           0,
  328.                                           hwndWnd,
  329.                                           HWND_TOP,
  330.                                           WND_CNR,
  331.                                           NULL,
  332.                                           NULL);
  333.          if (pcdData->hwndCnr==NULLHANDLE) {
  334.             free(pcdData);
  335.             WinAlarm(HWND_DESKTOP,WA_ERROR);
  336.             return MRFROMSHORT(TRUE);
  337.          } /* endif */
  338.  
  339.          //----------------------------------------------------------------
  340.          // Change the container's font to 8 point Helvetica
  341.          //----------------------------------------------------------------
  342.          strcpy(achFont,"8.Helv");
  343.          WinSetPresParam(pcdData->hwndCnr,
  344.                          PP_FONTNAMESIZE,
  345.                          strlen(achFont)+1,
  346.                          achFont);
  347.  
  348.          //----------------------------------------------------------------
  349.          // Load the icons and the menu used
  350.          //----------------------------------------------------------------
  351.          pcdData->hptrYear=WinLoadPointer(HWND_DESKTOP,NULLHANDLE,ICO_YEAR);
  352.          if (pcdData->hptrYear==NULLHANDLE) {
  353.             WinDestroyWindow(pcdData->hwndCnr);
  354.             free(pcdData);
  355.             WinAlarm(HWND_DESKTOP,WA_ERROR);
  356.             return MRFROMSHORT(TRUE);
  357.          } /* endif */
  358.  
  359.          pcdData->hptrMonth=WinLoadPointer(HWND_DESKTOP,NULLHANDLE,ICO_MONTH);
  360.          if (pcdData->hptrYear==NULLHANDLE) {
  361.             WinDestroyPointer(pcdData->hptrYear);
  362.             WinDestroyWindow(pcdData->hwndCnr);
  363.             free(pcdData);
  364.             WinAlarm(HWND_DESKTOP,WA_ERROR);
  365.             return MRFROMSHORT(TRUE);
  366.          } /* endif */
  367.  
  368.          pcdData->hwndWndMenu=WinLoadMenu(HWND_OBJECT,NULLHANDLE,RES_CLIENT);
  369.          if (pcdData->hwndWndMenu==NULLHANDLE) {
  370.             WinDestroyPointer(pcdData->hptrMonth);
  371.             WinDestroyPointer(pcdData->hptrYear);
  372.             WinDestroyWindow(pcdData->hwndCnr);
  373.             free(pcdData);
  374.             WinAlarm(HWND_DESKTOP,WA_ERROR);
  375.             return MRFROMSHORT(TRUE);
  376.          } /* endif */
  377.  
  378.          setCascadeDefault(pcdData->hwndWndMenu,M_VIEW,MI_ICONVIEW);
  379.  
  380.          initCnr(pcdData);
  381.       }
  382.       break;
  383.    case WM_DESTROY:
  384.       //-------------------------------------------------------------------
  385.       // Cleanup
  386.       //-------------------------------------------------------------------
  387.       WinDestroyWindow(pcdData->hwndWndMenu);
  388.       WinDestroyPointer(pcdData->hptrMonth);
  389.       WinDestroyPointer(pcdData->hptrYear);
  390.       WinDestroyWindow(pcdData->hwndCnr);
  391.       free(pcdData);
  392.       break;
  393.    case WM_SIZE:
  394.       //-------------------------------------------------------------------
  395.       // Size the container to complete cover the client
  396.       //-------------------------------------------------------------------
  397.       WinSetWindowPos(pcdData->hwndCnr,
  398.                       NULLHANDLE,
  399.                       0,
  400.                       0,
  401.                       SHORT1FROMMP(mpParm2),
  402.                       SHORT2FROMMP(mpParm2),
  403.                       SWP_MOVE|SWP_SIZE|SWP_SHOW|SWP_ACTIVATE);
  404.       break;
  405.    case WM_PAINT:
  406.       {
  407.          HPS hpsWnd;
  408.  
  409.          //----------------------------------------------------------------
  410.          // Since the container covers us completely, the call to GpiErase()
  411.          // is unnecessary
  412.          //----------------------------------------------------------------
  413.          hpsWnd=WinBeginPaint(hwndWnd,NULLHANDLE,NULL);
  414.          GpiErase(hpsWnd);
  415.          WinEndPaint(hpsWnd);
  416.       }
  417.       break;
  418.    case WM_CONTEXTMENU:
  419.       {
  420.          POINTL ptlMouse;
  421.  
  422.          //----------------------------------------------------------
  423.          // The user requested that the menu be displayed.  Note
  424.          // that there's a bug in the container such that if the
  425.          // user uses the keyboard to do this, we don't get notified,
  426.          // so that is why the code is duplicated here.
  427.          //----------------------------------------------------------
  428.          WinQueryPointerPos(HWND_DESKTOP,&ptlMouse);  // @7
  429.  
  430.          WinPopupMenu(HWND_DESKTOP,
  431.                       hwndWnd,
  432.                       pcdData->hwndWndMenu,
  433.                       ptlMouse.x,
  434.                       ptlMouse.y,
  435.                       0,
  436.                       PU_HCONSTRAIN | PU_VCONSTRAIN | PU_NONE |
  437.                          PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2);
  438.       }
  439.       break;
  440.    case WM_CONTROL:
  441.       switch (SHORT1FROMMP(mpParm1)) {
  442.       case WND_CNR:
  443.          switch (SHORT2FROMMP(mpParm1)) {
  444.          case CN_CONTEXTMENU:
  445.             {
  446.                POINTL ptlMouse;
  447.  
  448.                //----------------------------------------------------------
  449.                // The user requested that the menu be displayed.  Note
  450.                // that there's a bug in the container such that if the
  451.                // user uses the keyboard to do this, we don't get notified.
  452.                //----------------------------------------------------------
  453.                WinQueryPointerPos(HWND_DESKTOP,&ptlMouse);
  454.  
  455.                WinPopupMenu(HWND_DESKTOP,
  456.                             hwndWnd,
  457.                             pcdData->hwndWndMenu,
  458.                             ptlMouse.x,
  459.                             ptlMouse.y,
  460.                             0,
  461.                             PU_HCONSTRAIN | PU_VCONSTRAIN | PU_NONE |
  462.                                PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2);
  463.             }
  464.             break;
  465.          default:
  466.             return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
  467.          } /* endswitch */
  468.          break;
  469.       default:
  470.          return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
  471.       } /* endswitch */
  472.       break;
  473.    case WM_COMMAND:
  474.       //-------------------------------------------------------------------
  475.       // Process the menu.  These are trivial things and are not commented.
  476.       //-------------------------------------------------------------------
  477.       switch (SHORT1FROMMP(mpParm1)) {
  478.       case MI_ICONVIEW:
  479.          {
  480.             CNRINFO ciInfo;
  481.  
  482.             ciInfo.flWindowAttr=CV_ICON;
  483.             WinSendMsg(pcdData->hwndCnr,
  484.                        CM_SETCNRINFO,
  485.                        MPFROMP(&ciInfo),
  486.                        MPFROMLONG(CMA_FLWINDOWATTR));
  487.  
  488.             SETMENUATTR(pcdData->hwndWndMenu,MI_ARRANGE,MIA_DISABLED,FALSE);
  489.             SETMENUATTR(pcdData->hwndWndMenu,MI_SELECTALL,MIA_DISABLED,FALSE);
  490.             SETMENUATTR(pcdData->hwndWndMenu,MI_DESELECTALL,MIA_DISABLED,FALSE);
  491.          }
  492.          break;
  493.       case MI_ICONTREE:
  494.          {
  495.             CNRINFO ciInfo;
  496.  
  497.             ciInfo.flWindowAttr=CV_TREE|CV_ICON;
  498.             WinSendMsg(pcdData->hwndCnr,
  499.                        CM_SETCNRINFO,
  500.                        MPFROMP(&ciInfo),
  501.                        MPFROMLONG(CMA_FLWINDOWATTR));
  502.  
  503.             SETMENUATTR(pcdData->hwndWndMenu,MI_ARRANGE,MIA_DISABLED,TRUE);
  504.             SETMENUATTR(pcdData->hwndWndMenu,MI_SELECTALL,MIA_DISABLED,TRUE);
  505.             SETMENUATTR(pcdData->hwndWndMenu,MI_DESELECTALL,MIA_DISABLED,TRUE);
  506.          }
  507.          break;
  508.       case MI_ARRANGE:
  509.          WinSendMsg(pcdData->hwndCnr,CM_ARRANGE,0,0);
  510.          break;
  511.       case MI_SELECTALL:
  512.          {
  513.             BOOL bSet;
  514.  
  515.             bSet=TRUE;                                // @8
  516.             searchCnr(pcdData->hwndCnr,(PFNSRCH)searchSelect,&bSet,NULL);
  517.          }
  518.          break;
  519.       case MI_DESELECTALL:
  520.          {
  521.             BOOL bSet;
  522.  
  523.             bSet=FALSE;
  524.             searchCnr(pcdData->hwndCnr,(PFNSRCH)searchSelect,&bSet,NULL);
  525.          }
  526.          break;
  527.       case MI_EXIT:
  528.          WinPostMsg(hwndWnd,WM_CLOSE,0,0);
  529.          break;
  530.       default:
  531.          return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
  532.       } /* endswitch */
  533.       break;
  534.    default:
  535.       return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
  536.    } /* endswitch */
  537.  
  538.    return MRFROMSHORT(FALSE);
  539. }
  540.  
  541. INT main(VOID)
  542. //-------------------------------------------------------------------------
  543. // Standard PM main(), blah, blah, blah...
  544. //-------------------------------------------------------------------------
  545. {
  546.    HAB habAnchor;
  547.    HMQ hmqQueue;
  548.    ULONG ulCreate;
  549.    HWND hwndFrame;
  550.    HWND hwndClient;
  551.    BOOL bLoop;
  552.    QMSG qmMsg;
  553.  
  554.    habAnchor=WinInitialize(0);
  555.    hmqQueue=WinCreateMsgQueue(habAnchor,0);
  556.  
  557.    WinRegisterClass(habAnchor,CLS_CLIENT,clientProc,0,sizeof(PVOID));
  558.  
  559.    ulCreate=FCF_SYSMENU | FCF_TITLEBAR | FCF_MINMAX | FCF_SIZEBORDER |
  560.                FCF_TASKLIST | FCF_SHELLPOSITION;
  561.  
  562.    hwndFrame=WinCreateStdWindow(HWND_DESKTOP,
  563.                                 WS_VISIBLE,
  564.                                 &ulCreate,
  565.                                 CLS_CLIENT,
  566.                                 "Container Sample",
  567.                                 0,
  568.                                 NULLHANDLE,
  569.                                 RES_CLIENT,
  570.                                 &hwndClient);
  571.    if (hwndFrame!=NULLHANDLE) {
  572.       bLoop=WinGetMsg(habAnchor,&qmMsg,NULLHANDLE,0,0);
  573.       while (bLoop) {
  574.          WinDispatchMsg(habAnchor,&qmMsg);
  575.          bLoop=WinGetMsg(habAnchor,&qmMsg,NULLHANDLE,0,0);
  576.       } /* endwhile */
  577.  
  578.       WinDestroyWindow(hwndFrame);
  579.    } /* endif */
  580.  
  581.    WinDestroyMsgQueue(hmqQueue);
  582.    WinTerminate(habAnchor);
  583. }
  584.