home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / os2 / queues / cliqmain.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  22KB  |  699 lines

  1. /*==============================================================*\
  2.  *
  3.  *  cliqmain.c - sample queue application main source file
  4.  *      Copyright 1996, IBM Corp.
  5.  *
  6.  *--------------------------------------------------------------
  7.  *
  8.  *  DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  9.  *  sample code created by IBM Corporation. This sample code is not
  10.  *  part of any standard or IBM product and is provided to you solely
  11.  *  for  the purpose of assisting you in the development of your
  12.  *  applications.  The code is provided "AS IS", without
  13.  *  warranty of any kind.  IBM shall not be liable for any damages
  14.  *  arising out of your use of the sample code, even if they have been
  15.  *  advised of the possibility of such damages.
  16.  *
  17.  *--------------------------------------------------------------
  18.  *
  19.  *  This file contains the source for the main thread
  20.  *  which services the PM message queue.
  21.  *
  22. \*==============================================================*/
  23.  
  24. /*--------------------------------------------------------------*\
  25.  *  Include files, macros, defined constants, and externs
  26. \*--------------------------------------------------------------*/
  27.  
  28. #define INCL_WINHELP
  29. #define INCL_DOSPROCESS
  30. #define INCL_DOSSEMAPHORES
  31. #define INCL_DOSQUEUES
  32. #define INCL_GPILCIDS
  33. #define INCL_WIN
  34.  
  35. #include <os2.h>
  36. #include <string.h>
  37. #include <stdlib.h>
  38. #include <stdio.h>
  39.  
  40. #include "cliqmain.h"
  41. #include "queue.h"
  42. #include "cliqxtrn.h"
  43. #include "cliqhelp.h"
  44.  
  45. #define  ENTRY_STRING     "Queue Message"
  46. #define  PRIORITY_STRING  "Message Priority"
  47. #define  DAY_STRING       "Day"
  48. #define  MONTH_STRING     "Month"
  49. #define  YEAR_STRING      "Year"
  50.  
  51. #define  ENTRY_LEN        14
  52. #define  PRIORITY_LEN     17
  53. #define  DAY_LEN           4
  54. #define  MONTH_LEN         6
  55. #define  YEAR_LEN          5
  56.  
  57.  
  58. /*--------------------------------------------------------------*\
  59.  *  Global variables
  60. \*--------------------------------------------------------------*/
  61.  
  62. HWND   hwndMainFrame = NULLHANDLE;    /* handle to the main frame window */
  63. HWND   hwndMain;                      /* handle to the main client window */
  64. HAB    hab;                           /* anchor block for the process */
  65. HMQ    hmq;                           /* handle to the process' message queue */
  66. CHAR   szAppName[MAXNAMEL];           /* buffer for application name string */
  67. BOOL   fHelpEnabled;                  /* flag to determine if help is enabled */
  68. HQUEUE hqQ;
  69. LONG   cxChar, cyChar;
  70. RECTL  rcl;
  71. int    index;
  72.  
  73. BOOL         fThrdsDead = FALSE;
  74. HEV          hevSend;
  75. CHAR         pszMessage[MESSAGE_LEN];
  76. ULONG        ulMsgSize, ulMsgType;
  77. USHORT       usPriority;
  78. Q_DATE       qdDate;
  79. PVOID        pvdQMsg;
  80. THREADPARAM  tpThrdParm;
  81.  
  82.  
  83. /****************************************************************\
  84.  *  Main routine
  85.  *--------------------------------------------------------------
  86.  *
  87.  *  Name:   main()
  88.  *
  89.  *  Purpose: Initializes the PM environment, calls the
  90.  *              initialization routine, creates the main
  91.  *              window,  and polls the message queue
  92.  *
  93.  *  Usage:
  94.  *
  95.  *  Method:
  96.  *          - obtains anchor block handle and creates message
  97.  *              queue
  98.  *          - calls the initialization routine
  99.  *          - creates the main frame window which creates the
  100.  *              main client window
  101.  *          - polls the message queue via Get/Dispatch Msg loop
  102.  *          - upon exiting the loop, exits
  103.  *
  104.  *  Returns:
  105.  *          0 - if successful execution completed
  106.  *          1 - if error
  107. \****************************************************************/
  108. INT main()
  109. {
  110.    QMSG qmsg;              /* message structure */
  111.    int  iTimeout = 1000;   /* thread exit timeout */
  112.  
  113.    hab = WinInitialize(0);
  114.  
  115.    if(!hab)
  116.    {
  117.       DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
  118.       return RETURN_ERROR;
  119.    }
  120.  
  121.    hmq = WinCreateMsgQueue(hab, 0);
  122.  
  123.    if(!hmq)
  124.    {
  125.       DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
  126.       WinTerminate(hab);
  127.       return RETURN_ERROR;
  128.    }
  129.  
  130.    if(!Init())
  131.    {
  132.       if(hwndMainFrame == NULLHANDLE)
  133.       {
  134.           MessageBox(HWND_DESKTOP,
  135.                      IDMSG_MAINWINCREATEFAILED,
  136.                      0,
  137.                      MB_OK | MB_ERROR,
  138.                      TRUE);
  139.           return RETURN_ERROR;
  140.       }
  141.  
  142.       else
  143.       {
  144.          MessageBox(HWND_DESKTOP,
  145.                  IDMSG_INITFAILED,
  146.                  0,
  147.                  MB_OK | MB_ERROR,
  148.                  TRUE);
  149.          if (WinIsWindow(hab, hwndMainFrame))
  150.          {
  151.             WinDestroyWindow(hwndMainFrame);
  152.          }
  153.       }
  154.  
  155.       DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
  156.       WinDestroyMsgQueue(hmq);
  157.       WinTerminate(hab);
  158.       return RETURN_ERROR;
  159.    }
  160.  
  161.    /* Get-Dispatch Message loop */
  162.    while(WinGetMsg(hab, (PQMSG)&qmsg, NULLHANDLE, 0UL, 0UL))
  163.        WinDispatchMsg(hab, (PQMSG)&qmsg);
  164.  
  165.    /* destroy the help instance */
  166.    DestroyHelpInstance();
  167.  
  168.    if (WinIsWindow(hab, hwndMainFrame))
  169.    {
  170.       WinDestroyWindow(hwndMainFrame);
  171.    }
  172.  
  173.    WinDestroyMsgQueue(hmq);
  174.  
  175.    /* give the other thread a chance to exit */
  176.    while (!fThrdsDead && iTimeout--)
  177.    {
  178.       DosSleep(0UL);
  179.    }
  180.  
  181.    DosCloseEventSem(hevSend);
  182.    WinTerminate(hab);
  183.    return RETURN_SUCCESS;
  184. }   /* main() */
  185.  
  186.  
  187. /****************************************************************\
  188.  *  Main client window procedure
  189.  *--------------------------------------------------------------
  190.  *
  191.  *  Name:   MainWndProc(hwnd, msg, mp1, mp2)
  192.  *
  193.  *  Purpose: Processes the messages sent to the main client
  194.  *              window.  This routine processes the basic
  195.  *              messages all client windows should process
  196.  *              and passes all others onto WinDefWindowProc.
  197.  *
  198.  *  Usage:  Called for each message placed in the main
  199.  *          window's message queue
  200.  *
  201.  *  Method: a switch statement branches to the routines to be
  202.  *          performed for each message processed.
  203.  *
  204.  *  Returns:  Return values are determined by each message
  205.  *
  206. \****************************************************************/
  207. MRESULT EXPENTRY MainWndProc(HWND   hwnd,    /* handle of window */
  208.                              ULONG  msg,     /* id of message */
  209.                              MPARAM mp1,     /* first message parameter */
  210.                              MPARAM mp2)     /* second message parameter */
  211. {
  212.    HPS    hps;
  213.    FONTMETRICS   fm;
  214.    static POINTL ptl;
  215.  
  216.    switch(msg)
  217.    {
  218.       case WM_CREATE:
  219.          hps = WinGetPS(hwnd);
  220.          GpiQueryFontMetrics(hps, (LONG)sizeof fm, &fm);
  221.          WinReleasePS(hps);
  222.          cyChar = fm.lMaxBaselineExt;
  223.          cxChar = fm.lAveCharWidth;
  224.          rcl.yTop = 0;
  225.          break;
  226.  
  227.       case WM_PAINT:
  228.          if (0 == rcl.yTop)
  229.          {
  230.             WinQueryWindowRect(hwndMain, &rcl);
  231.          }
  232.          ptl.y = (4.0 / 5.0 * rcl.yTop + 1.0 / 2.0 * cxChar);
  233.          ptl.x = 4 * cxChar;
  234.          hps = WinBeginPaint(hwnd, NULLHANDLE, NULL);
  235.          GpiErase(hps);
  236.          GpiCharStringAt(hps, &ptl, ENTRY_LEN, ENTRY_STRING);
  237.  
  238.          ptl.y = ((2.0 / 5.0) * rcl.yTop + cxChar);
  239.          GpiCharStringAt(hps, &ptl, PRIORITY_LEN, PRIORITY_STRING);
  240.  
  241.          ptl.y = (3.0 / 5.0 * rcl.yTop + 1.0 / 2.0 * cxChar);
  242.          ptl.x = 1.0 / 4.0 * rcl.xRight - (DAY_LEN+1) * cxChar;
  243.          GpiCharStringAt(hps, &ptl, DAY_LEN, DAY_STRING);
  244.  
  245.          ptl.y = (3.0 / 5.0 * rcl.yTop + 1.0 / 2.0 * cxChar);
  246.          ptl.x = 2.0 / 4.0 * rcl.xRight - (MONTH_LEN + 1) * cxChar;
  247.          GpiCharStringAt(hps, &ptl, MONTH_LEN, MONTH_STRING);
  248.  
  249.          ptl.y = (3.0 / 5.0 * rcl.yTop + 1.0 / 2.0 * cxChar);
  250.          ptl.x = 3.0 / 4.0 * rcl.xRight - (YEAR_LEN + 1) * cxChar;
  251.          GpiCharStringAt(hps, &ptl, YEAR_LEN, YEAR_STRING);
  252.          WinEndPaint(hps);
  253.          break;
  254.  
  255.       case WM_COMMAND:
  256.           MainCommand(mp1, mp2);
  257.           break;
  258.  
  259.       case WM_MSG:
  260.          MessageBox(hwndMain,
  261.                     (ULONG)SHORT1FROMMP(mp1),
  262.                     LONGFROMMP(mp2),
  263.                     MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL,
  264.                     TRUE);
  265.          break;
  266.  
  267.       case HM_QUERY_KEYS_HELP:
  268.           return (MRESULT)PANEL_HELPKEYS;
  269.           break ;
  270.  
  271.       case WM_CLOSE:
  272.          /* send thread a closure message */
  273.          usPriority = 99;
  274.          DosPostEventSem(hevSend);
  275.  
  276.       default:
  277.          return WinDefWindowProc(hwnd, msg, mp1, mp2);
  278.          break;
  279.    }
  280.  
  281.    return MRFROMLONG(0);      /* all window procedures should return 0 as a default */
  282.  
  283. }   /* MainWndProc() */
  284.  
  285.  
  286. /****************************************************************\
  287.  *  Message Box procedure
  288.  *--------------------------------------------------------------
  289.  *
  290.  *  Name:   MessageBox(hwndOwner, nIdMsg, fsStyle, fBeep)
  291.  *
  292.  *  Purpose: Displays the message box with the message
  293.  *              given in idMsg retrieved from the message table
  294.  *              and using the style flags in fsStyle
  295.  *
  296.  *  Usage:  Called whenever a MessageBox is to be displayed
  297.  *
  298.  *  Method: - Message string is loaded from the process's message table
  299.  *          - Alarm beep is sounded if desired
  300.  *          - Message box with the message is displayed
  301.  *          - WinMessageBox return value is returned
  302.  *
  303.  *  Returns: return value from WinMessageBox()
  304.  *
  305. \****************************************************************/
  306. ULONG MessageBox(HWND  hwndOwner,  /* handle of the message box's owner */
  307.                  ULONG idMsg,      /* id of the message in the message table */
  308.                  LONG  lRC,        /* return code of failing function */
  309.                  ULONG fsStyle,    /* style of the message box */
  310.                  BOOL  fBeep)      /* if TRUE, beep before message box is displayed */
  311. {
  312.    CHAR szText[TITLE_LEN + 18];    /* allow space for chars in sprintf below  */
  313.  
  314.    if(!WinLoadMessage(hab,
  315.                     NULLHANDLE,
  316.                     idMsg,
  317.                     TITLE_LEN,
  318.                     (PSZ)szText))
  319.    {
  320.       WinAlarm(HWND_DESKTOP, WA_ERROR);
  321.       return MBID_ERROR;
  322.    }
  323.  
  324.    if (lRC)
  325.    {
  326.       sprintf(szText, "%s\n rc = %lu", szText, lRC);
  327.    }
  328.  
  329.    if(fBeep)
  330.    {
  331.       WinAlarm(HWND_DESKTOP, WA_ERROR);
  332.    }
  333.  
  334.    return WinMessageBox(HWND_DESKTOP,
  335.                         hwndOwner,
  336.                         szText,
  337.                         (PSZ)NULL,
  338.                         MSGBOXID,
  339.                         fsStyle);
  340.  
  341. }   /* MessageBox() */
  342.  
  343.  
  344. /****************************************************************\
  345.  *  Main window WM_COMMAND processing procedure
  346.  *--------------------------------------------------------------
  347.  *
  348.  *  Name:   MainCommand(mp1, mp2)
  349.  *
  350.  *  Purpose: Calls the appropriate procedures that deal with
  351.  *              the selected menu item.
  352.  *
  353.  *  Usage:  Routine is called whenever a WM_COMMAND message
  354.  *          is posted to the main window.
  355.  *
  356.  *  Method: a switch statement branches on the id of the
  357.  *          menu item that posted the message and the
  358.  *          appropriate action for that item is taken.
  359.  *
  360.  *  Returns:
  361.  *
  362. \****************************************************************/
  363. VOID MainCommand(MPARAM mp1, MPARAM mp2)
  364. {
  365.    ULONG  ulPosts;
  366.  
  367.    switch(SHORT1FROMMP(mp1))
  368.    {
  369.       case IDM_FILEEXIT:
  370.          usPriority = 99;
  371.          DosPostEventSem(hevSend);
  372.          FileExit();
  373.          break;
  374.  
  375.       case WID_SEND_DATE:
  376.          /* still waiting to send last message? */
  377.          DosQueryEventSem(hevSend, &ulPosts);
  378.  
  379.          if (0UL == ulPosts)
  380.          {
  381.             /* message type */
  382.             ulMsgType = Q_MSG_DATE;
  383.             pvdQMsg = (VOID *)&qdDate;
  384.  
  385.             /* get date */
  386.             WinSendMsg(WinWindowFromID(hwndMain, WID_DAY),
  387.                        SPBM_QUERYVALUE,
  388.                        (MPARAM)&(qdDate.usDay),
  389.                        MPFROM2SHORT(NULL, SPBQ_ALWAYSUPDATE));
  390.  
  391.             WinSendMsg(WinWindowFromID(hwndMain, WID_MONTH),
  392.                        SPBM_QUERYVALUE,
  393.                        (MPARAM)&(qdDate.usMonth),
  394.                        MPFROM2SHORT(NULL, SPBQ_ALWAYSUPDATE));
  395.  
  396.             WinSendMsg(WinWindowFromID(hwndMain, WID_YEAR),
  397.                        SPBM_QUERYVALUE,
  398.                        (MPARAM)&(qdDate.usYear),
  399.                        MPFROM2SHORT(NULL, SPBQ_ALWAYSUPDATE));
  400.  
  401.             /* message size */
  402.             ulMsgSize = sizeof(Q_DATE);
  403.  
  404.             /* get priority from spinbutton */
  405.             WinSendMsg(WinWindowFromID(hwndMain, WID_Q_PRIORITY),
  406.                        SPBM_QUERYVALUE,
  407.                        (MPARAM)&usPriority,
  408.                        MPFROM2SHORT(NULL, SPBQ_ALWAYSUPDATE));
  409.  
  410.             /* post message */
  411.             DosPostEventSem(hevSend);
  412.          }
  413.  
  414.          else
  415.          {
  416.             /* didn't post message */
  417.             DosBeep(100,100);
  418.          }
  419.          break;
  420.  
  421.       case WID_SEND_MSG:
  422.          /* still waiting to send last message? */
  423.          DosQueryEventSem(hevSend, &ulPosts);
  424.  
  425.          if (0UL == ulPosts)
  426.          {
  427.             /* message type */
  428.             ulMsgType = Q_MSG_TEXT;
  429.             pvdQMsg = (VOID *)pszMessage;
  430.  
  431.             /* get text */
  432.             WinQueryWindowText(WinWindowFromID(hwndMain, WID_Q_MSG), MESSAGE_LEN, pszMessage);
  433.  
  434.             /* message size */
  435.             ulMsgSize = strlen(pszMessage) + 1UL;
  436.  
  437.             /* get priority from spinbutton */
  438.             WinSendMsg(WinWindowFromID(hwndMain, WID_Q_PRIORITY),
  439.                        SPBM_QUERYVALUE,
  440.                        (MPARAM)&usPriority,
  441.                        MPFROM2SHORT(NULL, SPBQ_ALWAYSUPDATE));
  442.  
  443.             /* post message */
  444.             DosPostEventSem(hevSend);
  445.          }
  446.  
  447.          else
  448.          {
  449.             /* didn't post message */
  450.             DosBeep(100UL, 100UL);
  451.          }
  452.          break;
  453.  
  454.       case IDM_HELPHELPFORHELP:
  455.          HelpHelpForHelp(mp2);
  456.          break;
  457.  
  458.       case IDM_HELPEXTENDED:
  459.          HelpExtended(mp2);
  460.          break;
  461.  
  462.       case IDM_HELPKEYS:
  463.          HelpKeys(mp2);
  464.          break;
  465.  
  466.       case IDM_HELPINDEX:
  467.          HelpIndex(mp2);
  468.          break;
  469.  
  470.       case IDM_HELPTUTORIAL:
  471.          HelpTutorial(mp2);
  472.          break;
  473.  
  474.       case IDM_HELPABOUT:
  475.          HelpAbout(mp2);
  476.          break;
  477.  
  478.       default:
  479.          break;
  480.    }
  481. }   /* MainCommand() */
  482.  
  483.  
  484. /****************************************************************\
  485.  *  Initialization routine
  486.  *--------------------------------------------------------------
  487.  *
  488.  *  Name:   Init()
  489.  *
  490.  *  Purpose: Performs initialization functions required
  491.  *              before the application can be executed.
  492.  *
  493.  *  Usage:  Called once before the message queue is serviced.
  494.  *
  495.  *  Method:
  496.  *          - registers all window classes.
  497.  *          - initializes processing thread.
  498.  *
  499.  *  Returns:
  500.  *          TRUE - initialization is successful
  501.  *          FALSE - initialization failed
  502. \****************************************************************/
  503. BOOL Init()
  504. {
  505.    ULONG  flCtlData;    /* frame control data */
  506.    LONG   xLeft;
  507.    HWND   hwndSpin;
  508.    static USHORT  ausPriority[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  509.  
  510.    /* load application name from resource file */
  511.    if(!WinLoadString(hab, NULLHANDLE, IDS_APPNAME, MAXNAMEL, (PSZ)szAppName))
  512.    {
  513.       return FALSE;
  514.    }
  515.  
  516.    /* register the main client window class */
  517.    if(!WinRegisterClass(hab,
  518.                        (PSZ)szAppName,
  519.                        MainWndProc,
  520.                        CS_SIZEREDRAW | CS_CLIPCHILDREN,
  521.                        0UL))
  522.    {
  523.       return FALSE;
  524.    }
  525.  
  526.    /* create the main window */
  527.    flCtlData = FCF_TITLEBAR | FCF_SYSMENU | FCF_MENU |
  528.                FCF_MINMAX | FCF_ICON | FCF_BORDER | FCF_ACCELTABLE |
  529.                FCF_ICON | FCF_SHELLPOSITION | FCF_TASKLIST;
  530.  
  531.    hwndMainFrame = WinCreateStdWindow(HWND_DESKTOP,
  532.                                       WS_VISIBLE,
  533.                                       &flCtlData,
  534.                                       (PSZ)szAppName,
  535.                                       NULL,
  536.                                       WS_VISIBLE,
  537.                                       NULLHANDLE,
  538.                                       IDR_MAIN,
  539.                                       &hwndMain);
  540.    if (NULLHANDLE == hwndMainFrame)
  541.    {
  542.       return FALSE;
  543.    }
  544.  
  545.    WinSetWindowText(hwndMainFrame, szAppName);
  546.  
  547.    if (DosCreateEventSem(NULL, &hevSend, DC_SEM_SHARED, FALSE))
  548.    {
  549.       return FALSE;
  550.    }
  551.  
  552.    if (0 == rcl.yTop)
  553.    {
  554.       WinQueryWindowRect(hwndMain, &rcl);
  555.    }
  556.    xLeft = rcl.xRight / 5;
  557.    xLeft = max(xLeft, (cxChar * (ENTRY_LEN + 7)));
  558.    xLeft = max(xLeft, (cxChar * (PRIORITY_LEN + 7)));
  559.  
  560.    if (!InitQThrd(hevSend, &pvdQMsg, &usPriority, &ulMsgSize, &ulMsgType))
  561.    {
  562.       DosCloseEventSem(hevSend);
  563.       return FALSE;
  564.    }
  565.  
  566.    WinCreateWindow(hwndMain,
  567.                    WC_ENTRYFIELD,
  568.                    "Queue Message",
  569.                    (WS_VISIBLE | ES_MARGIN | WS_TABSTOP),
  570.                    xLeft,
  571.                    ((4.0 / 5.0) * rcl.yTop),
  572.                    ((rcl.xRight) - xLeft - 4 * cxChar),
  573.                    (cyChar + 2),
  574.                    hwndMain,
  575.                    HWND_BOTTOM,
  576.                    WID_Q_MSG,
  577.                    NULL,
  578.                    NULL);
  579.  
  580.    hwndSpin = WinCreateWindow(hwndMain,
  581.                               WC_SPINBUTTON,
  582.                               "Priority",
  583.                               (ULONG)(WS_VISIBLE | SPBS_MASTER | SPBS_NUMERICONLY | SPBS_JUSTRIGHT | WS_TABSTOP),
  584.                               xLeft,
  585.                               ((2.0 / 5.0) * rcl.yTop),
  586.                               (cxChar * 10),
  587.                               (cyChar + 2),
  588.                               hwndMain,
  589.                               HWND_BOTTOM,
  590.                               WID_Q_PRIORITY,
  591.                               NULL,
  592.                               NULL);
  593.  
  594.    WinSendMsg(hwndSpin, SPBM_SETLIMITS, MPFROMLONG(15), MPVOID);
  595.  
  596.    hwndSpin = WinCreateWindow(hwndMain,
  597.                               WC_SPINBUTTON,
  598.                               "Day",
  599.                               (WS_VISIBLE | SPBS_MASTER | SPBS_NUMERICONLY | SPBS_JUSTRIGHT | WS_TABSTOP),
  600.                               (1.0 / 4.0 * rcl.xRight),
  601.                               ((3.0 / 5.0) * rcl.yTop),
  602.                               (cxChar * 10),
  603.                               (cyChar + 2),
  604.                               hwndMain ,
  605.                               HWND_BOTTOM,
  606.                               WID_DAY,
  607.                               NULL,
  608.                               NULL);
  609.  
  610.    WinSendMsg(hwndSpin, SPBM_SETLIMITS, MPFROMLONG(31), MPFROMLONG(1));
  611.  
  612.    hwndSpin = WinCreateWindow(hwndMain,
  613.                               WC_SPINBUTTON,
  614.                               "Month",
  615.                               (ULONG)(WS_VISIBLE | SPBS_MASTER | SPBS_NUMERICONLY | SPBS_JUSTRIGHT | WS_TABSTOP),
  616.                               (2.0 / 4.0 * rcl.xRight),
  617.                               ((3.0 / 5.0) * rcl.yTop),
  618.                               (cxChar*10),
  619.                               (cyChar + 2),
  620.                               hwndMain,
  621.                               HWND_BOTTOM,
  622.                               WID_MONTH,
  623.                               NULL,
  624.                               NULL);
  625.  
  626.    WinSendMsg(hwndSpin, SPBM_SETLIMITS, MPFROMLONG(12), MPFROMLONG(1));
  627.  
  628.    hwndSpin = WinCreateWindow(hwndMain,
  629.                               WC_SPINBUTTON,
  630.                               "Year",
  631.                               (WS_VISIBLE | SPBS_MASTER | SPBS_NUMERICONLY | SPBS_JUSTRIGHT | WS_TABSTOP),
  632.                               (3.0 / 4.0 * rcl.xRight),
  633.                               ((3.0 / 5.0) * rcl.yTop),
  634.                               (cxChar * 10),
  635.                               (cyChar + 2),
  636.                               hwndMain,
  637.                               HWND_BOTTOM,
  638.                               WID_YEAR,
  639.                               NULL,
  640.                               NULL);
  641.  
  642.    WinSendMsg(hwndSpin, SPBM_SETLIMITS, MPFROMLONG(2000), MPFROMLONG(1900));
  643.  
  644.    WinCreateWindow(hwndMain,
  645.                    WC_BUTTON,
  646.                    "Send Msg",
  647.                    (WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP),
  648.                    ((SHORT)(rcl.xRight/(LONG)3) - cxChar*(SHORT)8),
  649.                    (rcl.yTop / 6),
  650.                    (cxChar * 16),
  651.                    (2 * cyChar),
  652.                    hwndMain,
  653.                    HWND_BOTTOM,
  654.                    WID_SEND_MSG,
  655.                    NULL, NULL);
  656.  
  657.    WinCreateWindow(hwndMain,
  658.                    WC_BUTTON,
  659.                    "Send Date",
  660.                    (WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP),
  661.                    ((2 * rcl.xRight/3) - cxChar * 9),
  662.                    (rcl.yTop / 6),
  663.                    (cxChar * 18),
  664.                    (2 * cyChar),
  665.                    hwndMain,
  666.                    HWND_BOTTOM,
  667.                    WID_SEND_DATE,
  668.                    NULL, NULL);
  669.  
  670.    InitHelp();
  671.  
  672.    return TRUE;
  673.  
  674. }  /* Init() */
  675.  
  676.  
  677. /****************************************************************\
  678.  *  Exit routine
  679.  *--------------------------------------------------------------
  680.  *
  681.  *  Name:   FileExit(mp2)
  682.  *
  683.  *  Purpose: Processes the File menu's Exit item.
  684.  *
  685.  *  Usage:  called whenever Exit from the file menu is
  686.  *          selected
  687.  *
  688.  *  Method:  Routine posts a WM_CLOSE message to the main
  689.  *           application window.
  690.  *
  691.  *  Returns:
  692.  *
  693. \****************************************************************/
  694. VOID FileExit()
  695. {
  696.    WinPostMsg(hwndMain, WM_CLOSE, MPVOID, MPVOID);
  697. }   /* FileExit() */
  698.  
  699.