home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / graphic / showbmp / showbmp.c < prev    next >
Text File  |  1990-06-19  |  31KB  |  667 lines

  1. #define PROGRAM       "SHOWBMP"        // Program Name
  2. #define LEVEL         "Level 00"       // Program Level
  3. #define COPYRIGHT     "Copyright (c) 1990 George S. Brickner"
  4.  
  5. #pragma title (PROGRAM " " LEVEL " - Display Bitmap")
  6. #pragma linesize(120)
  7. #pragma pagesize(55)
  8.  
  9. /*****************************************************************************
  10. **                                                                          **
  11. **          SHOWBMP - Display an OS/2 bitmap in a PM window.                **
  12. **                      Level 00, June 19th, 1990                           **
  13. **                                                                          **
  14. *****************************************************************************/
  15. #define  INCL_DOS                      // Include OS/2 Doscalls
  16. #define  INCL_GPI                      // Include OS/2 PM GPI Calls
  17. #define  INCL_WIN                      // Include OS/2 PM Win Calls
  18. #define  INCL_BITMAPFILEFORMAT         // Include OS/2 PM Bitmap File Hdr
  19. #define  INCL_ERRORS                   // Include All OS/2 Errors
  20. #include <os2.h>                       // Standard OS/2 Definitions
  21.  
  22. #include <mt\process.h>                // C/2 Standard Process Defs
  23. #include <mt\string.h>                 // C/2 Standard String Defs
  24. #include <mt\stdlib.h>                 // C/2 Standard Library Defs
  25. #include <mt\stdio.h>                  // C/2 Standard I/O Defs
  26.  
  27. #include <SHOWBMP.h>                   // SHOWBMP Header File
  28. #include <UTILITY.h>                   // UTILITY Header File
  29. #include <BITMAP.h>                    // BITMAP Header File
  30. #include <FILEREQ.h>                   // FILEREQ Header File
  31.  
  32. #define  STACK_SIZE     (16384)        // Thread stack size
  33.  
  34. #pragma subtitle ("Define Global & Static Data Areas")
  35. #pragma page()
  36. /**********************************************************************
  37. **                        Define Global Data                         **
  38. **********************************************************************/
  39. CHAR   szClientClass[] = PROGRAM;      // Client window class & pgm name
  40. HWND   hwndFrame;                      // Frame Window Handle
  41.  
  42. /**********************************************************************
  43. **                        Define Static Data                         **
  44. **********************************************************************/
  45. static CHAR const eyepopper[] = PROGRAM "-" LEVEL "-" __TIMESTAMP__ "-" COPYRIGHT;
  46.  
  47. static HAB    habMain;                 // PM Anchor Block Handle
  48. static HWND   hwndClient;              // Client Window Handle
  49. static HWND   hwndVscroll;             // Vertical Scroll Bar Handle
  50. static HWND   hwndHscroll;             // Horizontal Scroll Bar Handle
  51.  
  52. static SHORT  cxClient;                // Client Window Width
  53. static SHORT  cyClient;                // Client Window Height
  54. static SHORT  cxScreen;                // Desktop screen Width
  55. static SHORT  cyScreen;                // Desktop screen Height
  56. static SHORT  cxBorder;                // Thin border Width
  57. static SHORT  cyBorder;                // Thin border Height
  58. static SHORT  cyTitleBar;              // Title Bar Height
  59. static SHORT  cyMenu;                  // Menu Bar Height
  60. static SHORT  cxVScroll;               // Vertical scroll bar width
  61. static SHORT  cyHScroll;               // Horizontal scroll bar height
  62.  
  63. static SHORT  sVscrollPos;             // Vertical Scroll Position
  64. static SHORT  sHscrollPos;             // Horizontal Scroll Position
  65. static SHORT  sVscrollMax;             // Vertical Scroll Limit
  66. static SHORT  sHscrollMax;             // Horizontal Scroll Limit
  67.  
  68. static BMPCTL BmpCtl;                  // Bitmap control area
  69. static CHAR   szFileName[256];         // File name area
  70.  
  71. #pragma subtitle ("About Dialog Box Procedure")
  72. #pragma page()
  73. /********************************************************************
  74. **                    About Dialog Box Procedure                   **
  75. ********************************************************************/
  76. MRESULT EXPENTRY AboutDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  77.   {
  78.     switch (msg)                       // Process Dialog Message
  79.       {
  80.         case WM_COMMAND:               // Command Message
  81.           {
  82.             switch (COMMANDMSG (&msg)->cmd)    // Process Command ID
  83.               {
  84.                 case DID_OK:                   // User Clicked "OK"
  85.                   {
  86.                     WinDismissDlg (hwnd, TRUE);    // Done With Dialog
  87.                     break;                         // Normal Exit
  88.                   }
  89.                 default:                       // Default Command Processing
  90.                   {
  91.                     return WinDefDlgProc (hwnd, msg, mp1, mp2);
  92.                   }
  93.               }
  94.             break;                         // Normal Exit
  95.           }
  96.         default:                       // Default Dialog Processing
  97.           {
  98.             return WinDefDlgProc (hwnd, msg, mp1, mp2);
  99.           }
  100.       }
  101.     return MPFROMSHORT (FALSE);        // Return To PM
  102.   }
  103.  
  104. #pragma subtitle ("Bitmap Fetch Thread")
  105. #pragma page()
  106. /********************************************************************
  107. **                      Bitmap Fetch Thread                        **
  108. ********************************************************************/
  109. static VOID _cdecl FAR BitmapThread (PBMPCTL pCtl)
  110.   {
  111.   USHORT    rc;                        // Return code
  112.  
  113.     pCtl->habThread = WinInitialize (0);   // Connect To PM
  114.  
  115.     while (DosSemWait (&pCtl->hTriggerSem, SEM_INDEFINITE_WAIT) == NO_ERROR)
  116.       {
  117.         DosSemSet (&pCtl->hTriggerSem);    // Set semaphore
  118.  
  119.         rc = CreateBitmap (pCtl);      // Load bitmap into memory
  120.  
  121.         if (rc == NO_ERROR)            // Bitmap load successful
  122.           {
  123.             WinPostMsg (pCtl->hwndClient, UWM_BITMAP_READY, 0, 0);
  124.           }
  125.         else                           // Bitmap load failed
  126.           {
  127.             WinPostMsg (pCtl->hwndClient, UWM_BITMAP_ERROR, MPFROM2SHORT (rc, 0), (MPARAM) pCtl->Err);
  128.           }
  129.       }
  130.     WinTerminate (pCtl->habThread);    // Disconnect From PM
  131.     _endthread ();                     // Terminate thread
  132.   }
  133.  
  134. #pragma subtitle ("Set Window Title Text")
  135. #pragma page()
  136. /********************************************************************
  137. **                       Set Window Title Text                     **
  138. ********************************************************************/
  139. static VOID SetTitleText (PCHAR pTitle)
  140.   {
  141.   USHORT Size;                         // Data size
  142.   CHAR   szTitleText[256];             // Window Title Text
  143.  
  144.     WinLoadString (habMain, (HMODULE) NULL, IDS_TITLE,
  145.         sizeof szTitleText - 1, szTitleText);
  146.     strcat (szTitleText, " - ");
  147.     if (pTitle)                        // Title string supplied
  148.       {
  149.         strcat (szTitleText, pTitle);
  150.       }
  151.     else                               // Title string omitted - substitute
  152.       {
  153.         Size = strlen (szTitleText);   // Get title length so far
  154.         WinLoadString (habMain, (HMODULE) NULL, IDS_UNTITLED,
  155.             sizeof (szTitleText - 1) - Size, &szTitleText[Size]);
  156.       }
  157.     WinSetWindowText (hwndFrame, szTitleText);
  158.   }
  159.  
  160. #pragma subtitle ("View Bitmap Information")
  161. #pragma page()
  162. /********************************************************************
  163. **                      View Bitmap Information                    **
  164. ********************************************************************/
  165. static VOID ViewInformation (PBMPCTL pCtl)
  166.   {
  167.   USHORT  size;                        // String Size
  168.   CHAR    szFormat[256];               // Format Area
  169.   CHAR    szMessage[256];              // Message Area
  170.   CHAR    szCaption[256];              // Caption Area
  171.  
  172.     WinLoadString (habMain, (HMODULE) NULL, IDS_FORMAT04, sizeof szFormat, szFormat);
  173.  
  174.     sprintf (szMessage, szFormat, pCtl->Hdr.bmp.cx, pCtl->Hdr.bmp.cy, pCtl->cColors);
  175.  
  176.     strcpy (szCaption, szClientClass);
  177.     size = strlen (szCaption);
  178.     WinLoadString (habMain, (HMODULE) NULL, IDS_VIEWINFO, sizeof szCaption - size, &szCaption[size]);
  179.     DisplayMsgBox (FALSE, szMessage, szCaption, MB_OK);
  180.   }
  181.  
  182.  
  183. #pragma subtitle ("Main Client Window Procedure")
  184. #pragma page()
  185. /********************************************************************
  186. **                    Main Client Window Procedure                 **
  187. ********************************************************************/
  188. MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  189.   {
  190.   static  BOOL   BitmapReady;          // Bitmap ready flag
  191.   HPS     hps;                         // Presentation Space Handle
  192.   RECTL   rcl;                         // Rectangle
  193.   POINTL  aptl[3];                     // GpiBitBlt point array
  194.   USHORT  rc;                          // Return code
  195.   SHORT   cxNew, cyNew, xNew, yNew;    // New window size, position
  196.   SHORT   sHscrollInc;                 // Horiz scroll Increment
  197.   SHORT   sVscrollInc;                 // Vert scroll Increment
  198.   PBMPCTL pCtl;                        // Bitmap Control Ptr
  199.   CHAR    szText[16];                  // Text
  200.  
  201.     pCtl = &BmpCtl;                    // Set Ptr
  202.     switch (msg)                       // Process Window Message
  203.       {
  204.         case WM_CREATE:                // Window being created
  205.           {
  206.             hwndVscroll = WinWindowFromID (
  207.                 WinQueryWindow (hwnd, QW_PARENT, FALSE),
  208.                 FID_VERTSCROLL);       // Get Vert Scroll Handle
  209.  
  210.             hwndHscroll = WinWindowFromID (
  211.                 WinQueryWindow (hwnd, QW_PARENT, FALSE),
  212.                 FID_HORZSCROLL);       // Get Horiz Scroll Handle
  213.  
  214.             SetOpenMask ("*.BMP");     // Set initial open search mask
  215.             BitmapReady = FALSE;       // Initialize switch
  216.  
  217.             pCtl->hTriggerSem = NULL;
  218.             DosSemSet (&pCtl->hTriggerSem);  // Set semaphore
  219.  
  220.             pCtl->tidThread = _beginthread (BitmapThread, malloc (STACK_SIZE), STACK_SIZE, pCtl);
  221.  
  222.             if (pCtl->tidThread != -1)     // Thread started
  223.               {
  224.                 if (pCtl->pFileName)       // Bitmap on cmd line - fetch
  225.                   {
  226.                     DosSemClear (&pCtl->hTriggerSem);
  227.                   }
  228.               }
  229.             else                   // Thread start failed
  230.               {
  231.                 rc = _doserrno;
  232.                 ShowDOSError (habMain, rc, IDS_ERROR05);
  233.                 return MPFROMSHORT (TRUE);     // Error return To PM
  234.               }
  235.             break;                     // Normal Exit
  236.           }
  237.         case WM_SIZE:                  // Window being sized
  238.           {
  239.             cxClient = SHORT1FROMMP (mp2); // New window width
  240.             cyClient = SHORT2FROMMP (mp2); // New window height
  241.  
  242.             sHscrollMax = max (0, (SHORT) pCtl->Hdr.bmp.cx - cxClient);
  243.             sHscrollPos = min (sHscrollPos, sHscrollMax);
  244.  
  245.             WinSendMsg (               // Set Scroll Bar Pos/Limits
  246.                 hwndHscroll, SBM_SETSCROLLBAR,
  247.                 MPFROM2SHORT (sHscrollPos, 0),     // Set Current Position
  248.                 MPFROM2SHORT (0, sHscrollMax));    // Set Min & Max Limits
  249.  
  250.             WinEnableWindow (          // Enable Scrollbar If Not Zero
  251.                 hwndHscroll,
  252.                 sHscrollMax ? TRUE : FALSE);
  253.  
  254.             sVscrollMax = max (0, (SHORT) pCtl->Hdr.bmp.cy - cyClient);
  255.             sVscrollPos = min (sVscrollPos, sVscrollMax);
  256.  
  257.             WinSendMsg (               // Set Scroll Bar Pos/Limits
  258.                 hwndVscroll, SBM_SETSCROLLBAR,
  259.                 MPFROM2SHORT (sVscrollPos, 0),     // Set Current Position
  260.                 MPFROM2SHORT (0, sVscrollMax));    // Set Min & Max Limits
  261.  
  262.             WinEnableWindow (          // Enable Scrollbar If Not Zero
  263.                 hwndVscroll,
  264.                 sVscrollMax ? TRUE : FALSE);
  265.             break;                     // Normal Exit
  266.           }
  267.         case WM_HSCROLL:               // Horizontal Scroll Bar Moved
  268.           {
  269.             switch (SHORT2FROMMP (mp2))        // Process Scroll Amount
  270.               {
  271.                 case SB_LINELEFT:              // Move Left 1/25 window
  272.                   {
  273.                     sHscrollInc = -(cxClient / 25);
  274.                     break;                     // Send Msg To Scroll Bar
  275.                   }
  276.                 case SB_LINERIGHT:             // Move Right 1/25 window
  277.                   {
  278.                     sHscrollInc = cxClient / 25;
  279.                     break;                     // Send Msg To Scroll Bar
  280.                   }
  281.                 case SB_PAGELEFT:              // Move Left 1/4 window
  282.                   {
  283.                     sHscrollInc = -(cxClient / 4);
  284.                     break;                     // Send Msg To Scroll Bar
  285.                   }
  286.                 case SB_PAGERIGHT:             // Move Right 1/4 window
  287.                   {
  288.                     sHscrollInc = cxClient / 4;
  289.                     break;                     // Send Msg To Scroll Bar
  290.                   }
  291.                 case SB_SLIDERPOSITION:        // Slider Movement
  292.                   {
  293.                     sHscrollInc = SHORT1FROMMP (mp2) - sHscrollPos;
  294.                     break;                     // Send Msg To Scroll Bar
  295.                   }
  296.                 default:                       // Ignore Other Scroll Msgs
  297.                   {
  298.                     sHscrollInc = 0;           // No Scroll
  299.                     break;
  300.                   }
  301.               }
  302.  
  303.             sHscrollInc = max (-sHscrollPos, min (sHscrollInc, sHscrollMax - sHscrollPos));
  304.  
  305.             if (sHscrollInc)                   // Perform Scroll
  306.               {
  307.                 sHscrollPos += sHscrollInc;    // Update Scroll Pos
  308.                 WinScrollWindow (hwndClient, -sHscrollInc, 0,    // Horz Scroll
  309.                     NULL, NULL, NULL, NULL, SW_INVALIDATERGN);
  310.                 WinSendMsg (hwndHscroll, SBM_SETPOS,       // Set Scroll Bar Pos
  311.                     MPFROM2SHORT (sHscrollPos, 0), NULL);
  312.                 WinUpdateWindow (hwnd);
  313.               }
  314.             break;                     // Normal exit
  315.           }
  316.         case WM_VSCROLL:               // Vertical Scroll Bar Moved
  317.           {
  318.             switch (SHORT2FROMMP (mp2))        // Process Scroll Amount
  319.               {
  320.                 case SB_LINEUP:                // Move up 1/25 window
  321.                   {
  322.                     sVscrollInc = -(cyClient / 25);
  323.                     break;                     // Send Msg To Scroll Bar
  324.                   }
  325.                 case SB_LINEDOWN:              // Move down 1/25 window
  326.                   {
  327.                     sVscrollInc = cyClient / 25;
  328.                     break;                     // Send Msg To Scroll Bar
  329.                   }
  330.                 case SB_PAGEUP:                // Move up 1/4 window
  331.                   {
  332.                     sVscrollInc = -(cyClient / 4);
  333.                     break;                     // Send Msg To Scroll Bar
  334.                   }
  335.                 case SB_PAGEDOWN:              // Move down 1/4 window
  336.                   {
  337.                     sVscrollInc = cyClient / 4;
  338.                     break;                     // Send Msg To Scroll Bar
  339.                   }
  340.                 case SB_SLIDERPOSITION:        // Slider Movement
  341.                   {
  342.                     sVscrollInc = SHORT1FROMMP (mp2) - sVscrollPos;
  343.                     break;                     // Send Msg To Scroll Bar
  344.                   }
  345.                 default:                       // Ignore Other Scroll Msgs
  346.                   {
  347.                     sVscrollInc = 0;           // No Scroll
  348.                     break;
  349.                   }
  350.               }
  351.  
  352.             sVscrollInc = max (-sVscrollPos, min (sVscrollInc, sVscrollMax - sVscrollPos));
  353.  
  354.             if (sVscrollInc)                   // Perform Scroll
  355.               {
  356.                 sVscrollPos += sVscrollInc;    // Update Scroll Pos
  357.                 WinScrollWindow (hwndClient, 0, sVscrollInc, // Vert Scroll
  358.                     NULL, NULL, NULL, NULL, SW_INVALIDATERGN);
  359.                 WinSendMsg (hwndVscroll, SBM_SETPOS,       // Set Scroll Bar Pos
  360.                     MPFROM2SHORT (sVscrollPos, 0), NULL);
  361.                 WinUpdateWindow (hwnd);
  362.               }
  363.             break;                     // Normal exit
  364.           }
  365.         case WM_PAINT:                 // Paint The Window
  366.           {
  367.             DisplayBusyPtr (TRUE);     // Display hourglass pointer
  368.             hps = WinBeginPaint (hwnd, NULL, &rcl);
  369.  
  370.             if (BitmapReady)           // Bitmap available - display
  371.               {
  372.                 GpiCreateLogColorTable (hps, LCOL_RESET, LCOLF_CONSECRGB,
  373.                     0L, (LONG) pCtl->cColors, pCtl->lLogColorTbl);
  374.                 // Target bottom left corner of client window
  375.                 aptl[0].x = rcl.xLeft;
  376.                 aptl[0].y = rcl.yBottom;
  377.                 // Target top right corner of client window
  378.                 aptl[1].x = rcl.xRight;
  379.                 aptl[1].y = rcl.yTop;
  380.                 // Source bottom left corner of bitmap
  381.                 aptl[2].x = rcl.xLeft + sHscrollPos;
  382.                 aptl[2].y = rcl.yBottom + sVscrollMax - sVscrollPos;
  383.                 GpiBitBlt (hps, pCtl->hpsBitmap, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  384.               }
  385.             else if (pCtl->pFileName)  // Display "Working..."
  386.               {
  387.                 WinLoadString (habMain, (HMODULE) NULL, IDS_WORKING,
  388.                     sizeof szText - 1, szText);
  389.                 WinQueryWindowRect (hwnd, &rcl);
  390.                 WinDrawText (hps, -1, szText, &rcl, 0L, 0L,
  391.                     DT_CENTER | DT_VCENTER | DT_TEXTATTRS | DT_ERASERECT);
  392.               }
  393.             else                       // Just erase client area
  394.               {
  395.                 GpiErase (hps);
  396.               }
  397.             WinEndPaint (hps);
  398.             DisplayBusyPtr (FALSE);    // Display normal pointer
  399.             break;                     // Normal Exit
  400.           }
  401.         case UWM_BITMAP_READY:         // Bitmap ready to display
  402.           {
  403.             cxNew = min ((SHORT) (pCtl->Hdr.bmp.cx + (2 * cxBorder) + cxVScroll - 1), cxScreen);
  404.             cyNew = min ((SHORT) (pCtl->Hdr.bmp.cy + (2 * cyBorder) + cyTitleBar + cyMenu + cyHScroll - 1), cyScreen);
  405.  
  406.             xNew = (cxScreen - cxNew) / 2; // New X co-ordinate
  407.             yNew = (cyScreen - cyNew) / 2; // New Y co-ordinate
  408.  
  409.             BitmapReady = TRUE;        // Bitmap is ready for display
  410.             sHscrollPos = sVscrollPos = 0; // Reset scroll bars
  411.             WinSetWindowPos (hwndFrame, 0, xNew, yNew, cxNew, cyNew, SWP_SIZE | SWP_MOVE);
  412.             WinInvalidateRect (hwnd, NULL, FALSE); // Force re-paint
  413.             break;                     // Normal edit
  414.           }
  415.         case UWM_BITMAP_ERROR:         // Bitmap processing failed
  416.           {
  417.             BitmapReady = FALSE;       // Bitmap is not ready for display
  418.             pCtl->pFileName = NULL;    // Nothing to display
  419.             WinSetErrorInfo ((ERRORID) mp2, SEI_DOSERROR, SHORT1FROMMP (mp1)); // Save Error info
  420.             ShowPMError (habMain, IDS_ERROR04);
  421.             WinInvalidateRect (hwnd, NULL, FALSE); // Force re-paint
  422.             break;                     // Normal edit
  423.           }
  424.         case WM_HELP:                  // Process help command
  425.           {
  426.             DisplayMsgBox (            // Display dummy help
  427.                 FALSE,                 // No beep
  428.                 "Sorry, there is no help for you.", // Message
  429.                 "Help",                // Title
  430.                 MB_OK                  // Use OK button
  431.               );
  432.             break;                     // Normal Exit
  433.           }
  434.         case WM_CHAR:                  // Process keystroke
  435.           {
  436.             switch (CHARMSG (&msg)->vkey)      // Process Keystroke
  437.               {
  438.                 case VK_LEFT:                  // Scroll Left
  439.                 case VK_RIGHT:                 // Scroll Right
  440.                   {
  441.                     return WinSendMsg (hwndHscroll, msg, mp1, mp2);
  442.                   }
  443.                 case VK_UP:                    // Scroll Up One Line
  444.                 case VK_DOWN:                  // Scroll Down One Line
  445.                 case VK_PAGEUP:                // Scroll Up One Page
  446.                 case VK_PAGEDOWN:              // Scroll Down One Page
  447.                   {
  448.                     return WinSendMsg (hwndVscroll, msg, mp1, mp2);
  449.                   }
  450.                 default:                       // Default Processing
  451.                   {
  452.                     return WinDefWindowProc (hwnd, msg, mp1, mp2);
  453.                   }
  454.               }
  455.             break;                     // Normal exit
  456.           }
  457.         case WM_COMMAND:               // Process Menu Command
  458.           {
  459.             switch (COMMANDMSG (&msg)->cmd) // Process menu selection
  460.               {
  461.                 case IDM_FILE_NEW:         // Process New Request
  462.                   {
  463.                     SetTitleText (NULL);   // Default title
  464.                     pCtl->pFileName = NULL;    // No bitmap file name
  465.                     BitmapReady = FALSE;   // Bitmap is not ready for display
  466.                     DestroyBitMap (pCtl);  // Clean up existing bitmap
  467.                     WinInvalidateRect (hwnd, NULL, FALSE); // Force repaint
  468.                     break;                 // Normal exit
  469.                   }
  470.                 case IDM_FILE_OPEN:        // Process Open Request
  471.                   {
  472.                     pCtl->pFileName = NULL;    // No bitmap file name
  473.                     BitmapReady = FALSE;   // Bitmap is not ready for display
  474.                     DestroyBitMap (pCtl);  // Clean up existing bitmap
  475.  
  476.                     if (WinDlgBox (        // Invoke Open Dialog Box
  477.                         HWND_DESKTOP,      // Desktop Handle
  478.                         hwnd,              // Window Handle
  479.                         OpenDlgProc,       // Dialog Processing
  480.                         (HMODULE) NULL,    // Resource Is In .EXE
  481.                         IDD_OPEN,          // Dialog ID
  482.                         szFileName))       // Dialog Data Ptr
  483.                       {
  484.                         pCtl->pFileName = szFileName;    // Set file name ptr
  485.                         SetTitleText (pCtl->pFileName);  // Set new title
  486.                         WinInvalidateRect (hwnd, NULL, FALSE); // Force repaint
  487.                         DosSemClear (&pCtl->hTriggerSem);     // Post thread
  488.                       }
  489.                     else                    // Open Failed
  490.                       {
  491.                         SetTitleText (NULL);   // Default title
  492.                         pCtl->pFileName = NULL;
  493.                       }
  494.                     break;                  // Normal Exit
  495.                   }
  496.                 case IDM_FILE_ABOUT:        // Display About Box
  497.                   {
  498.                     WinDlgBox (             // Invoke Dialog Box
  499.                         HWND_DESKTOP,       // Desktop Handle
  500.                         hwnd,               // Window Handle
  501.                         AboutDlgProc,       // Dialog Processing
  502.                         (HMODULE) NULL,     // Resource Is In .EXE
  503.                         IDD_ABOUT,          // Dialog ID
  504.                         NULL                // Dialog Data Ptr
  505.                       );
  506.                     break;                  // Normal Exit
  507.                   }
  508.                 case IDM_FILE_EXIT:         // Exit program
  509.                   {
  510.                     WinPostMsg (hwnd, WM_QUIT, NULL, NULL);
  511.                     break;                  // Normal exit
  512.                   }
  513.                 case IDM_FILE_INFO:         // View information
  514.                   {
  515.                     ViewInformation (pCtl);
  516.                     break;                  // Normal exit
  517.                   }
  518.                 default:                    // Default processing
  519.                   {
  520.                     return WinDefWindowProc (hwnd, msg, mp1, mp2);
  521.                   }
  522.               }
  523.             break;                     // Normal exit
  524.           }
  525.         case WM_INITMENU:              // Initialize Menu items
  526.           {
  527.             switch (SHORT1FROMMP (mp1))
  528.               {
  529.                 case IDM_FILE:         // File menu - Disable
  530.                   {
  531.                     EnableMenuItem (IDM_FILE_SAVE,   FALSE);
  532.                     EnableMenuItem (IDM_FILE_SAVEAS, FALSE);
  533.                     break;             // Normal Exit
  534.                   }
  535.               }
  536.             break;                     // Normal exit
  537.           }
  538.         case WM_DESTROY:               // Window being destroyed
  539.           {
  540.             DosSuspendThread (pCtl->tidThread);
  541.             DestroyBitMap (pCtl);      // Clean up
  542.             break;                     // Normal exit
  543.           }
  544.         default:                       // Default Window Processing
  545.           {
  546.             return WinDefWindowProc (hwnd, msg, mp1, mp2);
  547.           }
  548.       }
  549.     return MPFROMSHORT (FALSE);        // Normal return To PM
  550.   }
  551.  
  552. #pragma subtitle ("Initialize Client Window")
  553. #pragma page()
  554. /********************************************************************
  555. **                    Initialize Client Window                     **
  556. ********************************************************************/
  557. BOOL InitClientWindow (PBMPCTL pCtl)
  558.   {
  559.   BOOL Response = FALSE;               // Response to caller
  560.   ULONG flFrameFlags;                  // Frame flags
  561.  
  562.     flFrameFlags = FCF_TITLEBAR   |    // Title bar
  563.                    FCF_SYSMENU    |    // System menu
  564.                    FCF_MINBUTTON  |    // Minimumize button
  565.                    FCF_BORDER     |    // Thin border
  566.                    FCF_ICON       |    // Icon present
  567.                    FCF_MENU       |    // Menu bar
  568.                    FCF_ACCELTABLE |    // Keyboard accelerator table
  569.                    FCF_SHELLPOSITION | // Let shell position window
  570.                    FCF_TASKLIST   |    // Task list entry
  571.                    FCF_VERTSCROLL |    // Vertical scroll bar
  572.                    FCF_HORZSCROLL;     // Horizontal scroll bar
  573.  
  574.     if (WinRegisterClass (             // Register client window class
  575.         habMain,                       // Anchor block handle
  576.         szClientClass,                 // Name of class being registered
  577.         ClientWndProc,                 // Window procedure for class
  578.         0L,                            // Class style
  579.         0))                            // Extra bytes to reserve
  580.       {
  581.         hwndFrame = WinCreateStdWindow (   // Create Frame & Client Windows
  582.             HWND_DESKTOP,              // Parent window handle
  583.             WS_VISIBLE,                // Style of frame window
  584.             &flFrameFlags,             // Pointer to control data
  585.             szClientClass,             // Client window class name
  586.             NULL,                      // Title bar text
  587.             0L,                        // Style of client window
  588.             (HMODULE) NULL,            // Resources in EXE file
  589.             ID_MAINWIN,                // ID of resources
  590.             &hwndClient);              // Pointer to client window handle
  591.  
  592.         if (hwndFrame && hwndClient)   // Window Created - continue
  593.           {
  594.             pCtl->hwndClient = hwndClient;   // Client window to notify
  595.             SetTitleText (pCtl->pFileName);  // Initial title
  596.             cxScreen   = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN);
  597.             cyScreen   = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
  598.             cxBorder   = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CXBORDER);
  599.             cyBorder   = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYBORDER);
  600.             cyTitleBar = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYTITLEBAR);
  601.             cyMenu     = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYMENU);
  602.             cxVScroll  = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CXVSCROLL);
  603.             cyHScroll  = (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYHSCROLL);
  604.             Response = TRUE;           // Indicate success
  605.           }
  606.         else                           // Client WinCreateStdWindow Failed
  607.           {
  608.             ShowPMError (habMain, IDS_ERROR03);
  609.           }
  610.       }
  611.     else                               // Client WinRegisterClass Failed
  612.       {
  613.         ShowPMError (habMain, IDS_ERROR02);
  614.       }
  615.     return Response;                   // Return to caller
  616.   }
  617.  
  618. #pragma subtitle ("Main Program")
  619. #pragma page()
  620. /********************************************************************
  621. **                    Main Program Entry Point                     **
  622. ********************************************************************/
  623. USHORT main (USHORT argc, PCHAR argv[])
  624.   {
  625.   HMQ     hmq = NULL;                  // Message Queue Handle
  626.   QMSG    qmsg;                        // Message Queue Element
  627.   PBMPCTL pCtl;                        // Bitmap control area ptr
  628.  
  629.     pCtl = &BmpCtl;                    // Set bitmap control ptr
  630.     memset (pCtl, 0x00, sizeof (BMPCTL));
  631.  
  632.     if (argc > 1)                      // Filename supplied
  633.       {
  634.         pCtl->pFileName = argv[1];
  635.       }
  636.  
  637.     habMain = WinInitialize (0);       // Connect To PM
  638.  
  639.     if (habMain)                       // Successful - Continue
  640.       {
  641.         hmq = WinCreateMsgQueue (habMain, 0);  // Create Message Queue
  642.  
  643.         if (hmq)                       // Successful - Continue
  644.           {
  645.             if (InitClientWindow (pCtl))   // Client Window OK
  646.               {
  647.                 while (WinGetMsg (habMain, &qmsg, NULL, 0, 0)) // Msg loop
  648.                   {
  649.                     WinDispatchMsg (habMain, &qmsg);   // Dispatch message
  650.                   }
  651.                 WinDestroyWindow (hwndFrame);  // Destroy Window
  652.               }
  653.             WinDestroyMsgQueue (hmq);  // Destroy Message Queue
  654.           }
  655.         else  // WinCreateMsgQueue Failed
  656.           {
  657.             ShowPMError (habMain, IDS_ERROR01);
  658.           }
  659.         WinTerminate (habMain);        // Disconnect From PM
  660.       }
  661.     else  // WinInitialize Failed
  662.       {
  663.         WinAlarm (HWND_DESKTOP, WA_ERROR);
  664.       }
  665.     return 0;
  666.   }
  667.