home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv8.zip / VACPP / IBMCPP / samples / COMPILER / PMLINES / PMLINES.C < prev    next >
Text File  |  1994-11-23  |  28KB  |  616 lines

  1. #pragma strings( readonly )
  2.  
  3. /*+--------------------------------------------------------------------------+*/
  4. /*|                                                                          |*/
  5. /*| PROGRAM NAME: PMLINES                                                    |*/
  6. /*| -------------                                                            |*/
  7. /*|  A Simple OS/2 Presentation Manager Graphics Demonstration Program       |*/
  8. /*|                                                                          |*/
  9. /*| COPYRIGHT:                                                               |*/
  10. /*| ----------                                                               |*/
  11. /*|  Copyright (C) International Business Machines Corp., 1991,1992.         |*/
  12. /*|                                                                          |*/
  13. /*| DISCLAIMER OF WARRANTIES:                                                |*/
  14. /*| -------------------------                                                |*/
  15. /*|  The following [enclosed] code is sample code created by IBM Corporation.|*/
  16. /*|  This sample code is not part of any standard IBM product and is provided|*/
  17. /*|  to you solely for the purpose of assisting you in the development of    |*/
  18. /*|  your applications.  The code is provided "AS IS", without warranty of   |*/
  19. /*|  any kind.  IBM shall not be liable for any damages arising out of your  |*/
  20. /*|  use of the sample code, even if they have been advised of the           |*/
  21. /*|  possibility of such damages.                                            |*/
  22. /*|                                                                          |*/
  23. /*| REVISION LEVEL: 1.0                                                      |*/
  24. /*| ---------------                                                          |*/
  25. /*|                                                                          |*/
  26. /*| WHAT THIS PROGRAM DOES:                                                  |*/
  27. /*| -----------------------                                                  |*/
  28. /*|  This program displays a standard window and then draws lines in the     |*/
  29. /*|  window.  Both the line and background colours change.                   |*/
  30. /*|                                                                          |*/
  31. /*| WHAT THIS PROGRAM DEMONSTRATES:                                          |*/
  32. /*| -------------------------------                                          |*/
  33. /*|  This program demonstrates how to create and display a standard window,  |*/
  34. /*|  use simple menus and dialog boxes, use a second thread for drawing,     |*/
  35. /*|  and displaying graphics using some basic GPI calls.                     |*/
  36. /*|                                                                          |*/
  37. /*| WHAT YOU NEED TO COMPILE THIS PROGRAM:                                   |*/
  38. /*| --------------------------------------                                   |*/
  39. /*|                                                                          |*/
  40. /*|  REQUIRED FILES:                                                         |*/
  41. /*|  ---------------                                                         |*/
  42. /*|                                                                          |*/
  43. /*|    PMLINES.C      - Source code                                          |*/
  44. /*|    PMLINES.DEF    - Module definition file                               |*/
  45. /*|    PMLINES.H      - Application header file                              |*/
  46. /*|    PMLINES.ICO    - Icon file                                            |*/
  47. /*|    SAMPLE1A.RC    - Resource file                                        |*/
  48. /*|    PMLINES.DLG    - Dialog file                                          |*/
  49. /*|                                                                          |*/
  50. /*|    OS2.H          - Presentation Manager include file                    |*/
  51. /*|    STDLIB.H       - Standard library function declarations               |*/
  52. /*|    STRING.H       - String handling function declarations                |*/
  53. /*|                                                                          |*/
  54. /*|  REQUIRED LIBRARIES:                                                     |*/
  55. /*|  -------------------                                                     |*/
  56. /*|                                                                          |*/
  57. /*|    OS2386.LIB     - Presentation Manager/OS2 library                     |*/
  58. /*|    DDE4NBS.LIB    - Subsystem Development Library                        |*/
  59. /*|                                                                          |*/
  60. /*|  REQUIRED PROGRAMS:                                                      |*/
  61. /*|  ------------------                                                      |*/
  62. /*|                                                                          |*/
  63. /*|    IBM C Set/2 Compiler                                                  |*/
  64. /*|    IBM Linker                                                            |*/
  65. /*|    Resource Compiler                                                     |*/
  66. /*|                                                                          |*/
  67. /*| EXPECTED INPUT:                                                          |*/
  68. /*| ---------------                                                          |*/
  69. /*|                                                                          |*/
  70. /*| EXPECTED OUTPUT:                                                         |*/
  71. /*| ----------------                                                         |*/
  72. /*|                                                                          |*/
  73. /*+--------------------------------------------------------------------------+*/
  74.  
  75. /*+--------------------------------------------------------------------------+*/
  76. /*| System and library header files.                                         |*/
  77. /*+--------------------------------------------------------------------------+*/
  78.  
  79. #define INCL_NOCOMMON
  80. #define INCL_DOSPROCESS
  81. #define INCL_DOSSEMAPHORES
  82. #define INCL_DOSERRORS
  83. #define INCL_WINWINDOWMGR
  84. #define INCL_WINMESSAGEMGR
  85. #define INCL_WINFRAMEMGR
  86. #define INCL_WINDIALOGS
  87. #define INCL_WININPUT
  88. #define INCL_WINSWITCHLIST
  89. #define INCL_WINPROGRAMLIST
  90. #define INCL_GPICONTROL
  91. #define INCL_GPIPRIMITIVES
  92. #include <os2.h>
  93. #include <stdlib.h>
  94. #include <string.h>
  95.  
  96. /*+--------------------------------------------------------------------------+*/
  97. /*| Application header files.                                                |*/
  98. /*+--------------------------------------------------------------------------+*/
  99.  
  100. #include "pmlines.h"
  101.  
  102. /*+--------------------------------------------------------------------------+*/
  103. /*| Internal function prototypes.                                            |*/
  104. /*+--------------------------------------------------------------------------+*/
  105.  
  106. static void InitTitle( HAB, HWND, char * );
  107. static MRESULT EXPENTRY ClientWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
  108. static MRESULT EXPENTRY HelpDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 );
  109. static FNTHREAD DrawingThread;
  110. static void DisplayMessage( HAB, ULONG );
  111.  
  112. /*+--------------------------------------------------------------------------+*/
  113. /*| Static global variables and local constants.                             |*/
  114. /*+--------------------------------------------------------------------------+*/
  115.  
  116. #define WINDOW_CLASS   "My_Window"          /* window class name              */
  117. #define COLOUR_TBL_LEN 16                   /* number of colour table entries */
  118. #define MSG_BOX_ID     256                  /* error message box id           */
  119. #define STRING_LENGTH  128                  /* size of buffer used for strings*/
  120. #define STACK_SIZE     8192UL               /* stack size for second thread   */
  121.  
  122. static HWND   hwndClient = NULLHANDLE;      /* client window handle           */
  123. static HMQ    hmqThread2 = NULLHANDLE;      /* message queue handle for thread*/
  124. static POINTL ptl1;                         /* line start point               */
  125. static POINTL ptl2;                         /* line end point                 */
  126. static LONG   lFcolour = CLR_BLUE;          /* foreground (line) colour       */
  127. static LONG   lBcolour = CLR_DARKGRAY;      /* background colour              */
  128. static LONG   cxClient, cyClient;           /* client window X and Y size     */
  129. static LONG   fcolourcounter = 1L;          /* wait time to change line colour*/
  130. static TID    tidDrawing = 0UL;             /* drawing thread identifier      */
  131. static char   szAppName[ MAXNAMEL + 1 ];    /* application name string        */
  132.  
  133. /*+--------------------------------------------------------------------------+*/
  134. /*| Main control procedure.                                                  |*/
  135. /*+--------------------------------------------------------------------------+*/
  136.  
  137. int main( void )
  138. {
  139.    HAB   hab = NULLHANDLE;                  /* PM anchor block handle         */
  140.    HMQ   hmq = NULLHANDLE;                  /* message queue handle           */
  141.    HWND  hwndFrame = NULLHANDLE;            /* frame window handle            */
  142.    ULONG flCreate = 0UL;                    /* window creation control flags  */
  143.    QMSG  qmsg;                              /* message from message queue     */
  144.    int   rc = 1;
  145.  
  146.    do
  147.    {
  148.       /* Initialize PM and create a message queue of default size.            */
  149.  
  150.       if ( ( hab = WinInitialize( 0UL ) ) == NULLHANDLE )
  151.          break;
  152.  
  153.       if ( ( hmq = WinCreateMsgQueue( hab, 0UL ) ) == NULLHANDLE )
  154.          break;
  155.  
  156.       /* Register client window class.                                        */
  157.  
  158.       if ( !WinRegisterClass( hab,          /* PM anchor block handle         */
  159.                               WINDOW_CLASS, /* window class name              */
  160.                           ClientWindowProc, /* address of window procedure    */
  161.                               CS_SIZEREDRAW,/* size changes cause redrawing   */
  162.                               0UL ) )       /* window data                    */
  163.       {
  164.          DisplayMessage( hab, IDS_NOREGISTER );
  165.          break;
  166.       }
  167.  
  168.       /* Create the standard windows but do not add the application to the    */
  169.       /* task manager list.                                                   */
  170.  
  171.       flCreate = FCF_STANDARD & ~FCF_TASKLIST;
  172.  
  173.       hwndFrame =
  174.          WinCreateStdWindow( HWND_DESKTOP,  /* make desktop window the parent */
  175.                              WS_VISIBLE,    /* frame window class style       */
  176.                              &flCreate,     /* frame control flags            */
  177.                              WINDOW_CLASS,  /* client window class name       */
  178.                              "",            /* title bar text                 */
  179.                              CS_SIZEREDRAW, /* client window class style      */
  180.                              0UL,           /* resource file handle - in EXE  */
  181.                              ID_WINDOW,     /* resources identifier           */
  182.                              &hwndClient ); /* client window handle           */
  183.       if ( hwndFrame == NULLHANDLE )
  184.       {
  185.          DisplayMessage( hab, IDS_NOSTDWINDOWS );
  186.          break;
  187.       }
  188.  
  189.       /* Initialize the window title and task switch list.                    */
  190.  
  191.       InitTitle( hab, hwndFrame, szAppName );
  192.  
  193.       /* Create the thread that will draw the lines.                          */
  194.       /* NOTE: _beginthread MUST be used if the thread contains CRT calls     */
  195.  
  196.       if ( DosCreateThread( &tidDrawing, DrawingThread, 0UL, 0UL, STACK_SIZE ) )
  197.       {
  198.          DisplayMessage( hab, IDS_NOTHREAD );
  199.          break;
  200.       }
  201.  
  202.       /* While the WM_QUIT message is not received, dispatch the message.     */
  203.       /* When the WM_QUIT message is received, WinGetMsg will return FALSE.   */
  204.  
  205.       while( WinGetMsg( hab, &qmsg, 0UL, 0UL, 0UL ) )
  206.          WinDispatchMsg( hab,               /* PM anchor block handle         */
  207.                          &qmsg );           /* pointer to message             */
  208.       rc = 0;
  209.  
  210.    }  while ( FALSE );
  211.  
  212.    /* Destroy the standard windows if they were created.                      */
  213.  
  214.    if ( hwndFrame != NULLHANDLE )
  215.       WinDestroyWindow( hwndFrame );        /* frame window handle            */
  216.  
  217.    /* Destroy the message queue and release the anchor block.                 */
  218.  
  219.    if ( hmq != NULLHANDLE )
  220.       WinDestroyMsgQueue( hmq );
  221.  
  222.    if ( hab != NULLHANDLE )
  223.       WinTerminate( hab );
  224.  
  225.    return rc;
  226. }
  227.  
  228. /*+--------------------------------------------------------------------------+*/
  229. /*| InitTitle - Initializes window title and task switch list.               |*/
  230. /*+--------------------------------------------------------------------------+*/
  231.  
  232. static void InitTitle( HAB hab, HWND hwnd, char *szTitle )
  233. {
  234.    SWCNTRL tSwcntrl;                        /* task switch structure          */
  235.  
  236.    /* Load the application name from the resources in the EXE.  Set the title */
  237.    /* bar text to this name.  Then add this application to the task manager   */
  238.    /* list with the loaded application name.                                  */
  239.  
  240.    WinLoadString( hab, 0UL, IDS_APPNAME, MAXNAMEL, szTitle );
  241.    WinSetWindowText( hwnd, szTitle );
  242.  
  243.    tSwcntrl.hwnd = hwnd;
  244.    tSwcntrl.hwndIcon = NULLHANDLE;
  245.    tSwcntrl.hprog = NULLHANDLE;
  246.    tSwcntrl.idProcess = 0;
  247.    tSwcntrl.idSession = 0;
  248.    tSwcntrl.uchVisibility = SWL_VISIBLE;
  249.    tSwcntrl.fbJump = SWL_JUMPABLE;
  250.    strcpy( tSwcntrl.szSwtitle, szTitle );
  251.    tSwcntrl.bProgType = PROG_PM;
  252.    WinAddSwitchEntry( &tSwcntrl );
  253.  
  254.    return;
  255. }
  256.  
  257. /*+--------------------------------------------------------------------------+*/
  258. /*| ClientWindowProc - Client window procedure.                              |*/
  259. /*+--------------------------------------------------------------------------+*/
  260.  
  261. static MRESULT EXPENTRY ClientWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  262. {
  263.    HPS   hps = NULLHANDLE;                  /* presentation space handle      */
  264.  
  265.    /* Process the message.                                                    */
  266.  
  267.    switch( msg )
  268.    {
  269.       case WM_CREATE:
  270.          /* The client window has been created but is not visible yet.        */
  271.          /* Initialize the window here.                                       */
  272.          break;
  273.  
  274.       case WM_CLOSE:
  275.          /* Tell the main procedure to terminate the message loop.            */
  276.  
  277.          WinPostMsg( hwnd, WM_QUIT, NULL, NULL );
  278.          break;
  279.  
  280.       case WM_PAINT:
  281.          /* Post a message to the second thread to make it repaint the        */
  282.          /* background.                                                       */
  283.  
  284.          hps = WinBeginPaint( hwnd, NULLHANDLE, NULL );
  285.  
  286.          WinPostQueueMsg( hmqThread2, WM_USER_REPAINT, 0UL, 0UL );
  287.  
  288.          WinEndPaint( hps );
  289.          break;
  290.  
  291.       case WM_COMMAND:
  292.          /* The user has chosen a menu item.  Process the selection           */
  293.          /* accordingly.                                                      */
  294.  
  295.          switch ( SHORT1FROMMP( mp1 ) )
  296.          {
  297.             case IDM_EXITPROG:
  298.                /* Post a close message.                                       */
  299.  
  300.                WinPostMsg( hwnd, WM_CLOSE, NULL, NULL );
  301.                break;
  302.  
  303.             case IDM_RESUME:
  304.                break;
  305.  
  306.             case IDM_HELPINSTRUCTIONS:
  307.                /* Display the help dialog box.                                */
  308.  
  309.                WinMessageBox( HWND_DESKTOP,      /* desktop is the parent     */
  310.                               hwnd,              /* owned by client window    */
  311.                               INSTRUCTIONS,      /* pointer to message text   */
  312.                               szAppName,         /* pointer to title text     */
  313.                               1UL,               /* message box identifier    */
  314.                               MB_OK | MB_INFORMATION | /* message box style   */
  315.                               MB_APPLMODAL | MB_MOVEABLE );
  316.  
  317.                /* Force a repaint.                                            */
  318.  
  319.                WinInvalidateRegion( hwnd, NULLHANDLE, FALSE );
  320.                break;
  321.  
  322.             case IDM_HELPABOUT:
  323.                /* Display the help dialog box.                                */
  324.  
  325.                WinDlgBox( HWND_DESKTOP,     /* make the desktop the parent    */
  326.                           hwnd,             /* owned by client window         */
  327.                           HelpDlgProc,      /* address of dialog procedure    */
  328.                           0UL,              /* module handle                  */
  329.                           IDD_HELP,         /* dialog identifier in resource  */
  330.                           NULL );           /* initialization data            */
  331.  
  332.                /* Force a repaint.                                            */
  333.  
  334.                WinInvalidateRegion( hwnd, NULLHANDLE, FALSE );
  335.                break;
  336.          }
  337.          break;
  338.  
  339.       case WM_SIZE:
  340.          /* Window is being resized so get new client window size and         */
  341.          /* recompute the end points for the lines.                           */
  342.  
  343.          cxClient = SHORT1FROMMP( mp2 );    /* Get new client window size     */
  344.          cyClient = SHORT2FROMMP( mp2 );
  345.          ptl1.x = cxClient / 2;             /* Set new points for lines based */
  346.          ptl1.y = cyClient / 2;             /* on the size of client window   */
  347.          ptl2.x = ptl1.x / 2;
  348.          ptl2.y = ptl1.y / 2;
  349.          break;
  350.  
  351.       case WM_BUTTON1DOWN:
  352.          /* The user has pushed mouse button 1 which means change the         */
  353.          /* foreground colour.                                                */
  354.  
  355.          /* Make sure that this window has the focus.                         */
  356.  
  357.          WinSetFocus( HWND_DESKTOP, hwnd );
  358.  
  359.          /* Reset foreground colour counter and increment foreground colour.  */
  360.  
  361.          fcolourcounter = 1;
  362.          lFcolour++;
  363.  
  364.          /* Make sure foreground and background colours are different.        */
  365.  
  366.          if ( lFcolour == lBcolour )
  367.             lFcolour++;
  368.  
  369.          /* Make sure the foregound colour does not exceed CLR_PALEGRAY.      */
  370.  
  371.          if ( lFcolour >= CLR_PALEGRAY )
  372.             lFcolour = CLR_BLUE;
  373.  
  374.          return ( MRESULT )TRUE;
  375.  
  376.       case WM_BUTTON1DBLCLK:
  377.          /* The user has double clicked mouse button 1 which means change     */
  378.          /* the background colour.                                            */
  379.  
  380.          /* Make sure that this window has the focus.                         */
  381.  
  382.          WinSetFocus( HWND_DESKTOP, hwnd );
  383.  
  384.          /* Increment the backgound colour but make sure the background       */
  385.          /* does not exceed CLR_PALEGRAY.                                     */
  386.  
  387.          if ( lBcolour == CLR_PALEGRAY )
  388.             lBcolour = CLR_BLUE;
  389.          else
  390.             ++lBcolour;
  391.  
  392.          /* Make sure foreground and background colours are different.        */
  393.  
  394.          if ( lFcolour == lBcolour )
  395.             lFcolour++;
  396.  
  397.          /* Make sure the foregound colour does not exceed CLR_PALEGRAY.      */
  398.  
  399.          if ( lFcolour >= CLR_PALEGRAY )
  400.             lFcolour = CLR_BLUE;
  401.  
  402.          /* Force the client window to repaint so that the background colour  */
  403.          /* is updated.                                                       */
  404.  
  405.          WinInvalidateRegion( hwnd, NULLHANDLE, FALSE );
  406.  
  407.          return ( MRESULT )TRUE;
  408.  
  409.       case WM_BUTTON2DOWN:
  410.          /* Make sure that this window has the focus.                         */
  411.  
  412.          WinSetFocus( HWND_DESKTOP, hwnd );
  413.  
  414.          /* Force the client window to repaint to clear the window.           */
  415.  
  416.          WinInvalidateRegion( hwnd, NULLHANDLE, FALSE );
  417.  
  418.          return ( MRESULT )TRUE;
  419.  
  420.       case WM_DESTROY:
  421.          /* The client window is being destroyed so tell the second thread to */
  422.          /* stop running.                                                     */
  423.  
  424.          WinPostQueueMsg( hmqThread2, WM_USER_END_THREAD, 0UL, 0UL );
  425.  
  426.          /* Wait for the drawing thread to terminate before returning.        */
  427.  
  428.          DosWaitThread( &tidDrawing, DCWW_WAIT );
  429.  
  430.          break;
  431.  
  432.       default:
  433.          /* For all other messages, let the default window procedure          */
  434.          /* process them.                                                     */
  435.  
  436.          return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
  437.    }
  438.    return NULL;
  439. }
  440.  
  441. /*+--------------------------------------------------------------------------+*/
  442. /*| HelpDlgProc - Help Dialog Procedure                                      |*/
  443. /*+--------------------------------------------------------------------------+*/
  444.  
  445. static MRESULT EXPENTRY HelpDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
  446. {
  447.    switch( msg )
  448.    {
  449.       case WM_COMMAND:
  450.          switch( SHORT1FROMMP( mp1 ) )      /* Extract the command value      */
  451.          {
  452.             case DID_OK:                    /* The Enter pushbutton or key    */
  453.                WinDismissDlg( hwndDlg, TRUE );
  454.                break;
  455.  
  456.             default:
  457.                break;
  458.          }
  459.          break;
  460.  
  461.       default:
  462.          return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  463.    }
  464.    return NULL;
  465. }
  466.  
  467. /*+--------------------------------------------------------------------------+*/
  468. /*| DrawingThread - Procedure that draws the lines in the client window.     |*/
  469. /*+--------------------------------------------------------------------------+*/
  470.  
  471. static void DrawingThread( ULONG ulThreadArg )
  472. {
  473.    /* Declare local variables.                                                */
  474.  
  475.    HAB   habThread2 = NULLHANDLE;           /* anchor block handle for thread */
  476.    HPS   hps = NULLHANDLE;                  /* presentation Space handle      */
  477.    LONG  delta1x = START_DELTA_X;           /* start point delta values       */
  478.    LONG  delta1y = START_DELTA_Y;
  479.    LONG  delta2x = END_DELTA_X;             /* end point delta values         */
  480.    LONG  delta2y = END_DELTA_Y;
  481.    RECTL rclClient;                         /* rectangle for client window    */
  482.    QMSG  qmsgThread2;                       /* message queue structure        */
  483.    BOOL  have_message;                      /* indicator that a message is    */
  484.                                             /* on the queue to be peeked at   */
  485.  
  486.    /* Change the priority class of this thread to idle class.                 */
  487.  
  488.    DosSetPriority( PRTYS_THREAD, PRTYC_IDLETIME, 0L, 0UL );
  489.  
  490.    /* Initialize thread to PM.                                                */
  491.  
  492.    habThread2 = WinInitialize( 0UL );
  493.    hmqThread2 = WinCreateMsgQueue( habThread2, 0UL );
  494.  
  495.    /* Get a presentation space.                                               */
  496.  
  497.    hps = WinGetPS( hwndClient );
  498.  
  499.    /* Run drawing thread.                                                     */
  500.  
  501.    qmsgThread2.msg = WM_USER_REPAINT;
  502.    have_message = TRUE;
  503.  
  504.    while ( !(have_message == TRUE && qmsgThread2.msg == WM_USER_END_THREAD) )
  505.    {
  506.       if ( have_message == TRUE && qmsgThread2.msg == WM_USER_REPAINT )
  507.       {
  508.          WinQueryWindowRect( hwndClient, &rclClient );
  509.          WinFillRect( hps, &rclClient, lBcolour );
  510.       }
  511.       else
  512.       {
  513.          /* Increment the foreground colour if necessary.                     */
  514.  
  515.          if ( ++fcolourcounter > ( ( cxClient + cyClient ) >> 1 ) )
  516.          {
  517.             fcolourcounter = 1;                /* Reset fcolourcounter and    */
  518.             lFcolour++;                        /* increment foreground colour.*/
  519.  
  520.             /* Make sure foreground and background colours are different.     */
  521.  
  522.             if ( lFcolour == lBcolour )
  523.                lFcolour++;
  524.  
  525.             /* Make sure the foregound colour does not exceed CLR_PALEGRAY.   */
  526.  
  527.             if ( lFcolour >= CLR_PALEGRAY )
  528.                lFcolour = CLR_BLUE;
  529.          }
  530.  
  531.          /* Add deltas to the start and end points for a line.                */
  532.  
  533.          /* If the start point would be invalid then negate the delta.        */
  534.  
  535.          if ( ( ptl1.x + delta1x ) > cxClient )
  536.             delta1x = -delta1x;
  537.  
  538.          if ( ( ptl1.x + delta1x ) < 1 )
  539.             delta1x = -delta1x;
  540.  
  541.          if ( ( ptl1.y + delta1y ) > cyClient )
  542.             delta1y = -delta1y;
  543.  
  544.          if ( ( ptl1.y + delta1y ) < 1 )
  545.             delta1y = -delta1y;
  546.  
  547.          /* Add delta to start point.                                         */
  548.  
  549.          ptl1.x += delta1x;
  550.          ptl1.y += delta1y;
  551.  
  552.          /* If the end point would be invalid then negate the delta.          */
  553.  
  554.          if ( ( ptl2.x + delta2x ) > cxClient )
  555.             delta2x = -delta2x;
  556.          if ( ( ptl2.x + delta2x ) < 1 )
  557.             delta2x = -delta2x;
  558.          if ( ( ptl2.y + delta2y ) > cyClient )
  559.             delta2y = -delta2y;
  560.          if ( ( ptl2.y + delta2y ) < 1 )
  561.             delta2y = -delta2y;
  562.  
  563.          /* Add delta to end point.                                           */
  564.  
  565.          ptl2.x += delta2x;
  566.          ptl2.y += delta2y;
  567.  
  568.          /* Now draw the line.                                                */
  569.  
  570.          GpiSetColor( hps, lFcolour );
  571.          GpiMove( hps, &ptl1 );                /* Move to start point         */
  572.          GpiLine( hps, &ptl2 );                /* Draw new line               */
  573.       }
  574.  
  575.       /* Peek in the message queue to see if the main thread has posted a msg.*/
  576.  
  577.       have_message = WinPeekMsg( habThread2,
  578.                                  &qmsgThread2,
  579.                                  NULLHANDLE,
  580.                                  0UL,
  581.                                  0UL,
  582.                                  PM_REMOVE );
  583.    }
  584.  
  585.    /* Clean up and terminate drawing thread.                                  */
  586.  
  587.    WinReleasePS( hps );
  588.    WinDestroyMsgQueue( hmqThread2 );
  589.    WinTerminate( habThread2 );
  590.    DosExit( EXIT_THREAD, 0UL );
  591. }
  592.  
  593. /*+--------------------------------------------------------------------------+*/
  594. /*| DisplayMessage - display an error message in a message box.              |*/
  595. /*+--------------------------------------------------------------------------+*/
  596.  
  597. static void DisplayMessage( HAB hab, ULONG ulStringNum )
  598. {
  599.    char szTemp[ STRING_LENGTH ];
  600.  
  601.    WinLoadString( hab, 0UL, ulStringNum, STRING_LENGTH, szTemp );
  602.  
  603.    WinAlarm( HWND_DESKTOP,                  /* desktop window handle          */
  604.              WA_ERROR );                    /* type of alarm                  */
  605.  
  606.    WinMessageBox( HWND_DESKTOP,             /* parent window handle           */
  607.                   HWND_DESKTOP,             /* owner window handle            */
  608.                   szTemp,                   /* pointer to message text        */
  609.                   szAppName,                /* pointer to title text          */
  610.                   MSG_BOX_ID,               /* message box identifier         */
  611.                   MB_OK | MB_ERROR |        /* message box style              */
  612.                   MB_SYSTEMMODAL );
  613.  
  614.    return;
  615. }
  616.