home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / queues.zip / CLIQMAIN.C
C/C++ Source or Header  |  1992-07-15  |  22KB  |  704 lines

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