home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_08 / qcdemow.cpp < prev    next >
C/C++ Source or Header  |  1992-07-21  |  22KB  |  631 lines

  1. ///////////////////////////////////////////////////////
  2. //  QCDEMOW.CPP: Quadcode demo program for Windows
  3. //  Written by:
  4. //    Kenneth Van Camp
  5. //    RR #1 Box 1255
  6. //    East Stroudsburg, PA  18301
  7. //    (717)223-8620
  8. //
  9. //  Functions -
  10. //    main                      main pgm entry point
  11. //    init_graphics             initialize graphics
  12. //    Cursor::Cursor            default constructor
  13. //    Cursor::Move              move cursor
  14. //    RegionDisplay::Display    display region
  15. //    RegionDisplay::Interact   user interaction
  16. //    win_yieldfunc             yield function for build
  17. //
  18. ///////////////////////////////////////////////////////
  19. #include <windows.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <ctype.h>
  23. #include <string.h>
  24. #include <time.h>
  25. #include <iostream.h>
  26. #include "qc.h"
  27. #include "qcdemow.h"
  28.  
  29. // Global variables:
  30. HCURSOR ArrowCursor,        //  standard arrow cursor
  31.         WaitCursor;         //  hourglass cursor
  32. HDC     Hdc;                //  device context for the window
  33. HWND    BuildHdlg,          //  handle for the Building dialog box
  34.         MainHwnd;           //  handle for application's main window
  35. HANDLE  Haccel;             //  handle for application acclerators
  36. int     Shrink = TRUE,      //  shrink all qc's for plotting?
  37.         XShrinkage = 0,     //  amount to shrink in X direction
  38.         YShrinkage = 0,     //  amount to shrink in Y direction
  39.         Xmax = 0,           //  # pixels in viewport in X direction
  40.         Ymax = 0,           //  # pixels in viewport in Y direction
  41.         QCsize,             //  size of a single-division quadcode
  42.         Nquits,             //  number of quits used to represent region
  43.         RegionNumQC = 0,    //  number of qc's in region
  44.         BuildCancelled = FALSE; //  was the region building cancelled?
  45. time_t  RegionBuildTime = 0;//  time to build region
  46.  
  47. const int   SCRRES = 1024;  //  screen resolution used (logical coords)
  48.  
  49. // class RegionDisplay: A Region class with graphical
  50. // display and interaction capabilities.
  51. class RegionDisplay: public Region
  52. {
  53.   public:
  54.     RegionDisplay         // constructor from outline
  55.         (PointListHeader &vertex_list):
  56.         Region (vertex_list) { }  // calls base constr.
  57.     void Display (void);  // display on graphics screen
  58.     void Interact (void); // graphic interact function
  59. };  // class RegionDisplay
  60.  
  61. RegionDisplay *TheRegion = NULL;
  62.  
  63. // The following is the perimeter list for the demo region:
  64. const int Npts = 37;
  65. const int Ndiv = 128;
  66. const int Reduce = 1;
  67. Point Plist[Npts] =
  68. {
  69.     {  5, 68}, { 28, 68}, { 32, 88}, { 33, 94},
  70.     { 31,110}, { 30,113}, { 35,124}, { 51,125},
  71.     { 63,127}, { 63,119}, { 67,116}, { 59,109},
  72.     { 63,119}, { 63,127}, { 74,126}, { 80,125},
  73.     { 88,112}, { 99,101}, {107, 98}, {113, 96},
  74.     {124, 98}, {122, 94}, {123, 91}, {121, 85},
  75.     {118, 78}, {108, 73}, { 96, 64}, { 85, 58},
  76.     { 81, 50}, { 82, 46}, { 90, 38}, { 83, 25},
  77.     { 72, 21}, { 58,  8}, { 55,  8}, { 54, 40},
  78.     {  5, 40}, 
  79. };
  80. PointListHeader Phdr =
  81. {
  82.     Npts, Ndiv, Plist
  83. };
  84.  
  85.  
  86. // Prototypes for exported functions:
  87.  
  88. #if defined( __cplusplus )
  89. extern "C" {
  90. #endif  // __cplusplus
  91.  
  92. long FAR PASCAL WndProc (HWND, UINT, WPARAM, LPARAM);
  93. BOOL FAR PASCAL AboutDlgProc (HWND, UINT, WPARAM, LPARAM);
  94. BOOL FAR PASCAL BuildDlgProc (HWND, UINT, WPARAM, LPARAM);
  95.  
  96. #if defined( __cplusplus )
  97. }
  98. #endif  // __cplusplus
  99.  
  100. // Prototypes for other local functions:
  101. void redraw_win (int first_time);
  102. void update_status (int xcursor, int ycursor);
  103. void set_draw_area (void);
  104. int win_yieldfunc (int pct_complete);
  105.  
  106. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  107.                     LPSTR lpszCmdParam, int nCmdShow)
  108. {
  109.     static char szAppName[] = "QCDemoW";
  110.     MSG         msg;
  111.     WNDCLASS    wndclass;
  112.  
  113.     // Initialize the cursor we will use.
  114.     ArrowCursor = LoadCursor (NULL, IDC_ARROW);
  115.     WaitCursor  = LoadCursor (NULL, IDC_WAIT);
  116.  
  117.     if (!hPrevInstance)
  118.     {
  119.         wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  120.         wndclass.lpfnWndProc   = WndProc;
  121.         wndclass.cbClsExtra    = 0;
  122.         wndclass.cbWndExtra    = 0;
  123.         wndclass.hInstance     = hInstance;
  124.         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
  125.         wndclass.hCursor       = ArrowCursor;
  126.         wndclass.hbrBackground = GetStockObject (WHITE_BRUSH);
  127.         wndclass.lpszMenuName  = "QCDEMOW";
  128.         wndclass.lpszClassName = szAppName;
  129.  
  130.         RegisterClass (&wndclass);
  131.     }
  132.  
  133.     MainHwnd = CreateWindow (szAppName, // window class name
  134.             "Quadcode Demo (Windows Version)",  // window caption
  135.             WS_OVERLAPPEDWINDOW,    // window style
  136.             CW_USEDEFAULT,          // initial x position
  137.             CW_USEDEFAULT,          // initial y position
  138.             CW_USEDEFAULT,          // initial x size
  139.             CW_USEDEFAULT,          // initial y size
  140.             NULL,                   // parent window handle
  141.             NULL,                   // window menu handle
  142.             hInstance,              // program instance handle
  143.             NULL);                  // creation parameters
  144.  
  145.     ShowWindow (MainHwnd, nCmdShow);
  146.     UpdateWindow (MainHwnd);
  147.  
  148.     Haccel = LoadAccelerators (hInstance, "ACCELERATORS_1");
  149.     if (Haccel == NULL)
  150.         MessageBox (MainHwnd, "Can't Load Acelerators", "NOTICE",
  151.                             MB_ICONEXCLAMATION | MB_OK);
  152.  
  153.     while (GetMessage (&msg, NULL, 0, 0))
  154.     {
  155.         // Translate accelerator keystrokes, too.
  156.         if (! TranslateAccelerator (MainHwnd, Haccel, &msg))
  157.         {
  158.             TranslateMessage (&msg);
  159.             DispatchMessage (&msg);
  160.         }
  161.     }
  162.     return msg.wParam;
  163.  
  164. }   // WinMain
  165.  
  166. long FAR PASCAL WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  167. {
  168.     PAINTSTRUCT ps;
  169.     int         ret;
  170.     WORD        menu_state;         // Current menu state (checked or not)
  171.     char        tmpstr[80];
  172.  
  173.     static int      first_paint = TRUE, // Is this the first screen paint?
  174.                     resized = FALSE;    // Was the window just resized?
  175.     static HMENU    menu;           // Popup menu
  176.     static HANDLE   hinstance;      // Instance of this program
  177.     static FARPROC  about_dlg_proc, // Point to About dialog box procedure
  178.                     build_dlg_proc; // Point to Build dialog box procedure
  179.  
  180.     switch (message)
  181.     {
  182.         case WM_CREATE:
  183.             // This occurs when the window is first created.
  184.             // First get the instance of the main program.
  185.             hinstance = ((LPCREATESTRUCT)lParam)->hInstance;
  186.             // Register the dialog procedures:
  187.             about_dlg_proc = MakeProcInstance ((FARPROC)AboutDlgProc,
  188.                         hinstance);
  189.             build_dlg_proc = MakeProcInstance ((FARPROC)BuildDlgProc,
  190.                         hinstance);
  191.             // Then get the handle for the menu
  192.             menu = GetMenu (hwnd);
  193.             return 0;
  194.  
  195.         case WM_COMMAND:
  196.             // This is a menu selection or accelerator.
  197.             // Ignore any menu commands if the region is not built yet.
  198.             if (RegionNumQC == 0)
  199.                 return 0;
  200.             switch ( wParam )
  201.             {
  202.                 case QCMNU_EXIT:   // File Menu, Exit QCDemoW selection
  203.                 case QCACC_EXIT:   // Alt-X accelerator
  204.                     ret = MessageBox (hwnd, "Are You Sure You Want To Exit?",
  205.                             "QCDemoW", MB_OKCANCEL);
  206.                     if ( ret == IDOK )
  207.                         PostQuitMessage (0);
  208.                     return 0;
  209.  
  210.                 case QCMNU_ABOUT:   // File Menu, About selection
  211.                     DialogBox (hinstance, "ABOUT_BOX", hwnd, about_dlg_proc);
  212.                     return 0;
  213.  
  214.                 case QCMNU_SHRINKAGE:   // Options Menu, Shrinkage selection
  215.                 case QCACC_SHRINKAGE:   // Alt-S accelerator
  216.                     // This is a boolean checked item: Reverse previous state.
  217.                     if (Shrink)
  218.                     {
  219.                         Shrink = FALSE;
  220.                         menu_state = MF_UNCHECKED;
  221.                     }
  222.                     else
  223.                     {
  224.                         Shrink = TRUE;
  225.                         menu_state = MF_CHECKED;
  226.                     }
  227.                     menu_state |= MF_BYCOMMAND;
  228.                     CheckMenuItem (menu, wParam, menu_state);
  229.  
  230.                     // Invalidate the entire window so a repaint is forced.
  231.                     InvalidateRect (hwnd, NULL, TRUE);
  232.                     return 0;
  233.  
  234.                 default:
  235.                     // Unknown menu selection
  236.                     sprintf (tmpstr, "Unknown Selection #%d", wParam);
  237.                     MessageBox (hwnd, tmpstr, "WARNING",
  238.                             MB_ICONEXCLAMATION | MB_OK);
  239.                     return 0;
  240.  
  241.             }   // switch ( wParam )
  242.             break;
  243.  
  244.         case WM_MOVE:
  245.             // Make sure the window is repainted after a move, so we get
  246.             // a new Hdc for the status box update.
  247.             if (RegionNumQC > 0)
  248.                 InvalidateRect (hwnd, NULL, TRUE);
  249.             return 0;
  250.  
  251.         case WM_SIZE:
  252.             // Flag that the window was resized so extents will be
  253.             // recalculated on the next WM_PAINT (which comes automatically
  254.             // following a resize).
  255.             if (RegionNumQC > 0)
  256.                 resized = TRUE;
  257.             return 0;
  258.  
  259.         case WM_PAINT:
  260.             if (! first_paint)
  261.             {
  262.                 // Ignore any paint commands after the first one, until
  263.                 // the region is fully built.
  264.                 if (RegionNumQC == 0)
  265.                     return 0;
  266.                 // Change to the hourglass cursor during standard redraw.
  267.                 // (Don't have to put up hourglass on first paint, since
  268.                 // the modeless dialog box is displayed.)
  269.                 SetCursor (WaitCursor);
  270.             }
  271.  
  272.             // Get the device context to repaint the area.
  273.             Hdc = BeginPaint (hwnd, &ps);
  274.  
  275.             if (first_paint || resized)
  276.             {
  277.                 // The first time we paint, and each time the window is resized,
  278.                 // save the viewport extent.  (These are device coordinates.)
  279.                 RECT rect;
  280.                 GetClientRect (hwnd, &rect) ;
  281.                 Xmax = rect.right;
  282.                 Ymax = rect.bottom;
  283.                 resized = FALSE;
  284.             }
  285.  
  286.             // Setup the viewport and drawing mode.
  287.             set_draw_area ();
  288.  
  289.             if (Shrink)
  290.             {
  291.                 // Make sure the shrinkage is at least one pixel.
  292.                 XShrinkage = SCRRES / Xmax + 1;
  293.                 YShrinkage = SCRRES / Ymax + 1;
  294.             }
  295.             else
  296.                 XShrinkage = YShrinkage = 0;
  297.  
  298.             // On the first paint, have to build the region.  Put up a
  299.             // dialog box to inform the user, and build the region.
  300.             if (first_paint)
  301.             {
  302.                 first_paint = FALSE;
  303.                 BuildHdlg = CreateDialog (hinstance, "BUILD_BOX", hwnd,
  304.                         build_dlg_proc);
  305.                 redraw_win (TRUE);
  306.                 // Close the dialog box.  Not an error if it can't be
  307.                 // closed, since the user can close it.
  308.                 PostMessage (BuildHdlg, WM_CLOSE, 0, 0);
  309.             }
  310.             else
  311.             {
  312.                 // After the first paint, just redraw the entire region.
  313.                 redraw_win (FALSE);
  314.             }
  315.  
  316.             EndPaint (hwnd, &ps);
  317.  
  318.             // Put the cursor back as the arrow pointer.
  319.             SetCursor (ArrowCursor);
  320.  
  321.             return 0;
  322.  
  323.         case WM_MOUSEMOVE:
  324.             // Don't interpret mouse movements unless region already built.
  325.             if (RegionNumQC > 0)
  326.             {
  327.                 // When the mouse moves, we wait until there are no more mouse
  328.                 // movement messages in the queue before processing it.
  329.                 // That prevents the application from falling too far behind
  330.                 // the user.
  331.                 MSG nextmsg;
  332.                 nextmsg.lParam = lParam;    // In case no more in queue.
  333.                 while ((ret = PeekMessage (&nextmsg, hwnd, WM_MOUSEMOVE,
  334.                         WM_MOUSEMOVE, PM_REMOVE)) != FALSE)
  335.                     ;
  336.                 // Find the current mouse position.
  337.                 POINT pt = MAKEPOINT (nextmsg.lParam);
  338.             
  339.                 // Setup the viewport and drawing mode.
  340.                 Hdc = GetDC (hwnd);
  341.                 if (Hdc == NULL)
  342.                     MessageBox (hwnd, "NULL DC", "ERROR",
  343.                                 MB_OK | MB_ICONEXCLAMATION);
  344.                 set_draw_area ();
  345.  
  346.                 // Convert device coordinates to logical (window) coordinates.
  347.                 DPtoLP (Hdc, &pt, 1);    // This doesn't work!
  348.                 // pt.x = (float)pt.x * SCRRES / Xmax;
  349.                 // pt.y = (float)pt.y * SCRRES / Ymax;
  350.  
  351.                 // Update the status box.
  352.                 // This should be a message to the status box window,
  353.                 // but it isn't implemented as a window yet.
  354.                 update_status (pt.x, pt.y);
  355.             }
  356.             return 0;
  357.  
  358.         case WM_DESTROY:
  359.             PostQuitMessage (0);
  360.             return 0;
  361.  
  362.     }   // switch
  363.  
  364.     return (DefWindowProc (hwnd, message, wParam, lParam));
  365.  
  366. }   // WndProc
  367.  
  368. // AboutDlgProc: Dialog box procedure for the "About QCDemoW" selection.
  369. extern "C"
  370. BOOL FAR PASCAL AboutDlgProc (HWND hdlg, UINT message, WPARAM wParam,
  371.         LPARAM lParam)
  372. {
  373.     switch (message)
  374.     {
  375.         case WM_INITDIALOG:
  376.             // Initialize the message with our performance message.
  377.             char tmpstr[80];
  378.             wsprintf (tmpstr, "%d Quadcodes Built in %d Seconds",
  379.                     RegionNumQC, RegionBuildTime);
  380.             SetDlgItemText (hdlg, QCTXT_ABOUT, tmpstr);
  381.             return TRUE;
  382.  
  383.         case WM_COMMAND:
  384.             switch (wParam)
  385.             {
  386.                 case QCBUT_OKABOUT:
  387.                     EndDialog (hdlg, TRUE);
  388.                     return TRUE;
  389.             }
  390.             break;
  391.     }
  392.     return FALSE;
  393. }   // AboutDlgProc
  394.  
  395. // BuildDlgProc: Dialog box procedure for the "Building Region" message.
  396. // This is a modeless dialog box.
  397. extern "C"
  398. BOOL FAR PASCAL BuildDlgProc (HWND hdlg, UINT message, WPARAM wParam,
  399.         LPARAM lParam)
  400. {
  401.     switch (message)
  402.     {
  403.         case WM_INITDIALOG:
  404.             return TRUE;
  405.  
  406.         case WM_COMMAND:
  407.             switch (wParam)
  408.             {
  409.                 case QCBUT_CANCEL:
  410.                     // The user decided to cancel the building of the region.
  411.                     // This has to kill the whole application.
  412. #ifdef NEVER
  413.                     PostMessage (MainHwnd, WM_DESTROY, 0, 0);
  414.                     EndDialog (hdlg, TRUE);
  415. #endif
  416.                     BuildCancelled = TRUE;
  417.                     return TRUE;
  418.             }
  419.             break;
  420.  
  421.         case WM_CLOSE:
  422.             DestroyWindow (hdlg);
  423.             return TRUE;
  424.  
  425.     }   // switch (message)
  426.     return FALSE;
  427.  
  428. }   // BuildDlgProc
  429.  
  430. // redraw_win: Redraw the entire region in the graphics window.
  431. void redraw_win (int first_time)
  432. {
  433.  
  434.     if (first_time)
  435.     {
  436.         // First draw, so build the quadcode region.
  437.         // Reduce to proper size
  438.         Phdr.ndiv /= Reduce;
  439.         int i;
  440.         for (i = 0; i < Npts; i++)
  441.         {
  442.             Phdr.pointptr[i].i /= Reduce;
  443.             Phdr.pointptr[i].j /= Reduce;
  444.         }
  445.  
  446.         // Set the yield function so user can interrupt.
  447.         SetRegionYieldFunc (win_yieldfunc);
  448.  
  449.         time_t tstart;
  450.         time (&tstart);
  451.  
  452.         // Build the region from a perimeter list
  453.         TheRegion = new RegionDisplay (Phdr);
  454.  
  455.         // Save the time it took to build the region.
  456.         time_t tend;
  457.         time (&tend);
  458.         RegionBuildTime = difftime (tend, tstart);
  459.         RegionNumQC = TheRegion->NumQC();
  460.  
  461.         if (RegionNumQC == 0)
  462.         {
  463.             // Region build was aborted by user.
  464.             PostMessage (MainHwnd, WM_DESTROY, 0, 0);
  465.             return;
  466.         }
  467.     }
  468.  
  469.     // Now redisplay the region.
  470.     TheRegion->Display();
  471.  
  472. }   // redraw_win
  473.  
  474. // update_status: Update the status box in the upper left corner of the screen.
  475. void update_status (int xcursor, int ycursor)
  476. {
  477.     // These are the coordinates of the status box (logical coords):
  478.     const int   StatUL = 10,    // upper-left corner
  479.                 StatLR = 85;    // lower-right corner
  480.  
  481.     // Find current mouse position
  482.     int i = ycursor / QCsize;
  483.     int j = xcursor / QCsize;
  484.  
  485.     // Only check if within region limits.
  486.     if (i >= 0 && i < Ndiv && j >= 0 && j < Ndiv)
  487.     {
  488.         QuadCode qc (i, j, Nquits);
  489.         if (TheRegion->InRegion (qc))
  490.         {
  491.             // In region - draw a solid status box.
  492.             HBRUSH blk_brush = GetStockObject (BLACK_BRUSH);
  493.             SelectObject (Hdc, blk_brush);
  494.             Rectangle (Hdc, StatUL, StatUL, StatLR, StatLR);
  495.         }
  496.         else
  497.         {
  498.             // Out of region - draw empty status box.
  499.             HBRUSH wht_brush = GetStockObject (WHITE_BRUSH);
  500.             SelectObject (Hdc, wht_brush);
  501.             Rectangle (Hdc, StatUL, StatUL, StatLR, StatLR);
  502.         }
  503.     }   // if i >= 0 ...
  504.  
  505. }   // update_status
  506.  
  507. // set_draw_area: Setup the viewport and client drawing area for a repaint.
  508. void set_draw_area (void)
  509. {
  510.     // Use a viewport sized to the client rectangle, and
  511.     // the window (virtual) size is SCRRES x SCRRES.  This makes
  512.     // (0,0) at the upper left of the window and (SCRRES,SCRRES)
  513.     // at the lower right of the window.  This is only
  514.     // approximate however, since when drawing in isotropic
  515.     // mode (to preserver the aspect ratio) we do not have
  516.     // the entire window to draw in.
  517.     SetMapMode (Hdc, MM_ISOTROPIC);
  518.     SetViewportExt (Hdc, Xmax, Ymax);
  519.  
  520.     SetWindowExt (Hdc, SCRRES, SCRRES);
  521.     SetWindowOrg (Hdc, 0, 0);
  522. }   // set_draw_area
  523.  
  524. // RegionDisplay::Display: Display the region on the graphics screen.
  525. void RegionDisplay::Display (void)
  526. {
  527.     if (NumQC() == 0)
  528.         return;
  529.  
  530.     // Get a brush so the quadcodes are filled black:
  531.     HBRUSH blk_brush = GetStockObject (BLACK_BRUSH);
  532.     SelectObject (Hdc, blk_brush);
  533.  
  534.     // Calculate the size of a single-division quadcode
  535.     QCsize = SCRRES / Ndiv;
  536.  
  537.     // Do for each quadcode in the region.
  538.     QCNode *qcn;
  539.     for ( qcn = first_qcnode; qcn; qcn = qcn->next)
  540.     {
  541.         COORD   i, j;
  542.         int     nq;
  543.         qcn->ToIJ (i, j, nq);
  544.         COORD nqc_div = 1L << nq;
  545.         float qcfact = Ndiv / nqc_div;
  546.         int qcxlen = QCsize * qcfact;
  547.         int qcylen = QCsize * qcfact;
  548.         int x = j * qcxlen;
  549.         int y = i * qcylen;
  550.  
  551.         x += XShrinkage;
  552.         y += YShrinkage;
  553.         qcxlen -= 2 * XShrinkage;
  554.         qcylen -= 2 * YShrinkage;
  555.  
  556.         // Minimum quadcode size is 2 screen units.
  557.         qcxlen = max (qcxlen, 2);
  558.         qcylen = max (qcylen, 2);
  559.  
  560.         // Draw the quadcode:
  561.         Rectangle (Hdc, x, y, x + qcxlen, y + qcylen);
  562.     }   // for qcn
  563.  
  564.     // Save the maximum number of quits in a quadcode in this region.
  565.     Nquits = MaxQuits();
  566.  
  567. }   // RegionDisplay::Display
  568.  
  569. ///////////////////////////////////////////////////////
  570. // win_yieldfunc: A function that is called periodically
  571. // during region building to yield control to the user
  572. // or another application.  Under Windows, it checks the
  573. // message queue for a Cancel by the user.  This also
  574. // allows Windows to pass messages to other applications.
  575. // It returns TRUE if the user aborts, or FALSE otherwise.
  576.  
  577. int win_yieldfunc (int pct_complete)
  578. // pct_complete     is the percent of region built
  579. {
  580.     // Before checking for messages, update the status bar.
  581.     // First get the handle of the frame window.
  582.     HWND frame_hwnd = GetDlgItem (BuildHdlg, QCFRAME);
  583.     HDC  frame_hdc  = GetDC (frame_hwnd);
  584.     RECT rect;
  585.     GetClientRect (frame_hwnd, &rect);
  586.  
  587.     // Get a brush so the frame is filled black:
  588.     HBRUSH blk_brush = GetStockObject (BLACK_BRUSH);
  589.     SelectObject (frame_hdc, blk_brush);
  590.  
  591.     // Calculate the length of the rectangle, proportional to amount done.
  592.     int xmax = ((float)pct_complete * (rect.right - 1) / 100.0);
  593.     Rectangle (frame_hdc, 1, 1, xmax, rect.bottom - 1);
  594.  
  595.     // Now check to see if the user pressed Cancel button.
  596.     MSG nextmsg;
  597. #ifdef NEVER
  598.     // Don't know why this doesn't work.  Should only have to check for
  599.     // commands to dialog box, but this doesn't yield control to Windows
  600.     // and it doesn't catch the mouse click.
  601.     if (PeekMessage (&nextmsg, BuildHdlg, WM_COMMAND, WM_COMMAND, PM_REMOVE))
  602.     {
  603.         if (nextmsg.wParam == QCBUT_CANCEL)
  604.         {
  605.             // User pressed Cancel button
  606.             return TRUE;
  607.         }
  608.     }
  609.  
  610.     return FALSE;
  611. #endif
  612.  
  613.     if (PeekMessage (&nextmsg, NULL, 0, 0, PM_REMOVE))
  614.     {
  615.         if (! IsDialogMessage (BuildHdlg, &nextmsg))
  616.         {
  617.             if (! TranslateAccelerator (MainHwnd, Haccel, &nextmsg))
  618.             {
  619.                 TranslateMessage (&nextmsg);
  620.                 DispatchMessage (&nextmsg);
  621.             }
  622.         }
  623.     }
  624.  
  625.     if (BuildCancelled)
  626.         return TRUE;
  627.     else
  628.         return FALSE;
  629.  
  630. } // win_yieldfunc
  631.