home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 5 / ctrom5b.zip / ctrom5b / PROGRAM / DIVERSEN / IMGLIB12 / TSTAPP.C < prev    next >
C/C++ Source or Header  |  1995-03-25  |  74KB  |  2,466 lines

  1. /****************************************************************************
  2.     Copyright (c) 1994, 1995 by SimSoft
  3.     PROGRAM: testapp.c
  4.     PURPOSE: Test program to exercise the functionality of ImgLib
  5.  
  6.     Revision History:
  7.     Nov  6, 94  Beta release
  8.     Dec 18, 94  Release 1.0
  9.     Feb 19, 95  Release 1.1:  Added support for file saving, scrolling, sizing
  10.                               printing
  11.     Mar 25, 95  Release 1.2:  Removed references to unsupported image types.
  12.                               Added clipdoard operations by utilizing ClipDIB
  13.                               Added the "Zoom x5" feature.
  14.                               Simplified palette handling.
  15. ****************************************************************************/
  16.  
  17. #include <windows.h>
  18. #include <commdlg.h>
  19. #ifndef WIN32
  20. #include <print.h>
  21. #endif
  22. #include <malloc.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "tstapp.h"
  26. #include "imglib.h"
  27. #ifdef USE_WING
  28. #include <wing.h>
  29. typedef HDC (WINGAPI *WINGCREATEDC) (void);
  30. typedef HBITMAP (WINGAPI *WINGCREATEBITMAP) (HDC, BITMAPINFO const FAR *, void FAR *FAR *);
  31. typedef BOOL (WINGAPI *WINGSTRETCHBLT) (HDC, int, int, int, int, HDC, int, int, int, int);
  32.  
  33. WINGSTRETCHBLT fpWinGStretchBlt;
  34. WINGCREATEBITMAP fpWinGCreateBitmap;
  35. WINGCREATEDC fpWinGCreateDC;
  36. #endif
  37.  
  38. #ifdef WIN32
  39. #define huge
  40. #define CONTROL_ID(w) (LOWORD (w))
  41. #define allocmem(s) (malloc (s))
  42. #define freemem(p) (free (p))
  43. #define copymem(d, s, c) (memcpy (d, s, c))
  44. #else
  45. #define CONTROL_ID(w) (w)
  46. #define allocmem(s) (GlobalLock (GlobalAlloc (GHND, (DWORD)s)))
  47. #define freemem(p) (GlobalFree (LOWORD (GlobalHandle (HIWORD (p)))))
  48. #define copymem(d, s, c) (hmemcpy (d, s, c))
  49. #endif
  50.  
  51. typedef char huge * HPSTR;
  52.  
  53. #define WINDOW_NAME "ImgLib Test App"
  54. #define MENU_POSITION_ROTATE      5
  55. #define MENU_POSITION_MIRROR      6
  56. #define MENU_POSITION_TC_OPT      0
  57.  
  58. static HWND       hwndMain;
  59. static HINSTANCE  hInst;
  60. static char       szBuffer[256];
  61. static HINSTANCE  hWinGInst;
  62. static HACCEL     hAccel;
  63. static LPVOID     lpDIB1, lpDIB2, lpDIBDisplay;
  64. static HPALETTE   hPalette;
  65. static LPPRINTDLG pPrintDlgStruct;
  66. static BOOL       bHalftoneImgLib, bFillPage;
  67. static unsigned int uPrintCopies = 1;
  68. static RECT       rcSelection;
  69. static POINT      ptAnchor;
  70. static BOOL       bDrawSelection, bPasting;
  71. static HDC        hdcWinG;
  72. static HBITMAP    hbmpWinG, hbmpWinGOld;
  73.  
  74. static BOOL       InitApplication (HANDLE);
  75. static BOOL       InitInstance (HANDLE, int);
  76. LRESULT CALLBACK  MainWndProc (HWND, UINT, WPARAM, LPARAM);
  77. BOOL CALLBACK     AboutProc (HWND, UINT, WPARAM, LPARAM);
  78. BOOL CALLBACK     FileTypeProc (HWND, UINT, WPARAM, LPARAM);
  79. BOOL CALLBACK     BrightnessProc (HWND, UINT, WPARAM, LPARAM);
  80. BOOL CALLBACK     PrintProc (HWND, UINT, WPARAM, LPARAM);
  81. static BOOL       GetOpenFile (LPSTR);
  82. static BOOL       GetSaveFile (LPSTR);
  83. LPVOID            CreateDisplayDIB (HWND, LPVOID*, HPALETTE *);
  84. static void       UpdateWindowTitle (LPSTR, BOOL);
  85. static void       ResizeWindowToDIB (HWND, LPVOID);
  86. static void       HandleVerticalScroll (WPARAM, LPARAM);
  87. static void       HandleHorizontalScroll (WPARAM, LPARAM);
  88. static void       HandleWindowSizing (LPVOID, WPARAM, LPARAM);
  89. static void       HandlePrinting (LPVOID);
  90. static void       HandleMenuPopup (WPARAM, LPARAM);
  91. static void       InitializePrintStruct (void);
  92. static void       HandleLButtonDown (WPARAM, LPARAM);
  93. static void       HandleLButtonUp (WPARAM, LPARAM);
  94. static void       HandleMouseMove (WPARAM, LPARAM);
  95. static void       HandleRButtonDown (WPARAM, LPARAM);
  96. static void       HandleCharacter (WPARAM, LPARAM);
  97. static void       HandlePasting (WPARAM, LPARAM);
  98. static void       HandleCopying (WPARAM, LPARAM);
  99. static void       HandleZoomin (WPARAM, LPARAM);
  100. static void       DrawSelectionBox (void);
  101. static void       EraseSelectionBox (void);
  102. static void       ProcessNewDIB (LPVOID);
  103. static LRESULT    HandlePaintingAndUpdates (UINT, WPARAM, LPARAM);
  104. #ifdef USE_WING
  105. static void       InitializeWinG (void);
  106. static void       UpdateWinGBitmap (LPVOID);
  107. #endif
  108.  
  109. /****************************************************************************
  110.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  111.     PURPOSE: calls initialization function, processes message loop
  112. ****************************************************************************/
  113.  
  114. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  115. MSG               msg;
  116.  
  117.   hInst = hInstance;
  118.  
  119.   if (!hPrevInstance)
  120.   {
  121.     if (!InitApplication (hInstance))
  122.       return (FALSE);
  123.   }
  124.   if (!InitInstance (hInstance, nCmdShow))
  125.     return (FALSE);
  126.   
  127.   while (GetMessage (&msg, NULL, 0, 0xffff))
  128.   {
  129.     if (!TranslateAccelerator (hwndMain, hAccel, &msg))
  130.     {
  131.       TranslateMessage (&msg);
  132.       DispatchMessage (&msg);
  133.     }
  134.   }
  135.   return (0);
  136. }
  137.  
  138.  
  139. /****************************************************************************
  140.     FUNCTION: InitApplication(HANDLE)
  141.     PURPOSE: Initializes window data and registers window class
  142. ****************************************************************************/
  143.  
  144. BOOL InitApplication (HANDLE hInstance)
  145. {
  146. WNDCLASS          wc;
  147.  
  148.   wc.style = 0;
  149.   wc.lpfnWndProc = MainWndProc;
  150.   wc.cbClsExtra = 0;
  151.   wc.cbWndExtra = 0;
  152.   wc.hInstance = hInstance;
  153.   wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  154.   wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  155.   wc.hbrBackground = GetStockObject (WHITE_BRUSH);
  156.   wc.lpszMenuName = "tstappmenu";
  157.   wc.lpszClassName = "Test App";
  158.   
  159.   return (RegisterClass (&wc));
  160. }
  161.  
  162.  
  163. /****************************************************************************
  164.     FUNCTION:  InitInstance(HANDLE, int)
  165.     PURPOSE:  Saves instance handle and creates main window
  166. ****************************************************************************/
  167.  
  168. BOOL InitInstance (HANDLE hInstance, int nCmdShow)
  169. {
  170. UINT              uErrMode;
  171. HMENU             hMenu;
  172. HDC               hDC;
  173.  
  174.   hAccel = LoadAccelerators (hInstance, "tstappaccel");
  175.  
  176.   if (!hAccel)
  177.     return (FALSE);
  178.  
  179.   /*
  180.    * Just use default size and location.  It's easier to size an already
  181.    * created window for the specific client area size.
  182.    */
  183.    
  184.   hwndMain = CreateWindow ("Test App", WINDOW_NAME,
  185.         WS_OVERLAPPEDWINDOW,
  186.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  187.         NULL, NULL, hInstance, NULL);
  188.  
  189.   if (!hwndMain)
  190.     return (FALSE);
  191.  
  192.   ShowWindow (hwndMain, nCmdShow);
  193.   UpdateWindow (hwndMain);
  194.   hDC = GetDC (hwndMain);
  195.  
  196.   if (GetDeviceCaps (hDC, RASTERCAPS) & RC_PALETTE)
  197.   {
  198.     uErrMode = SetErrorMode (SEM_NOOPENFILEERRORBOX);
  199. #ifdef WIN32
  200.     hWinGInst = LoadLibrary ("wing32.dll");
  201. #else
  202.     hWinGInst = LoadLibrary ("wing.dll");
  203.   
  204.     if (hWinGInst < HINSTANCE_ERROR)
  205.       hWinGInst = 0;
  206. #endif
  207.     SetErrorMode (uErrMode);
  208.   }
  209.   else
  210.     hWinGInst = NULL;
  211.   
  212.   ReleaseDC (hwndMain, hDC);
  213.   hMenu = GetMenu (hwndMain);
  214.  
  215. #ifdef USE_WING
  216.   if (hWinGInst)
  217.   {
  218.     InitializeWinG ();
  219.     CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_CHECKED);
  220.     CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_IMGLIB, MF_BYCOMMAND | MF_UNCHECKED);
  221.   }
  222.   else
  223. #endif
  224.     EnableMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_GRAYED);
  225.   
  226.   return (TRUE);
  227. }
  228.  
  229. /****************************************************************************
  230.     FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
  231.     PURPOSE:  Processes messages
  232. ****************************************************************************/
  233.  
  234. LRESULT CALLBACK MainWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  235. {
  236. int               iCount, iBrightness;
  237. static char       szFileName[260], szOldTitle[256];
  238. LPVOID            lpDIBNew;
  239. HMENU             hMenu;
  240. DWORD             dwStartTime;
  241. static short      nFileType;
  242. PRINTDLG          PrintDlgStruct;
  243.  
  244.   switch (message)
  245.   {
  246.     case WM_QUERYNEWPALETTE:
  247.     case WM_PALETTECHANGED:
  248.     case WM_PAINT:
  249.       
  250.       return (HandlePaintingAndUpdates (message, wParam, lParam));
  251.       break;
  252.  
  253.     case WM_CHAR:
  254.       
  255.       HandleCharacter (wParam, lParam);
  256.       break;
  257.  
  258.     case WM_LBUTTONDOWN:
  259.       
  260.       HandleLButtonDown (wParam, lParam);
  261.       break;
  262.  
  263.     case WM_RBUTTONDOWN:
  264.       
  265.       HandleRButtonDown (wParam, lParam);
  266.       break;
  267.  
  268.     case WM_LBUTTONUP:
  269.       
  270.       HandleLButtonUp (wParam, lParam);
  271.       break;
  272.  
  273.     case WM_MOUSEMOVE:
  274.       
  275.       HandleMouseMove (wParam, lParam);
  276.       break;
  277.  
  278.     case WM_INITMENUPOPUP:
  279.  
  280.       HandleMenuPopup (wParam, lParam);
  281.       break;
  282.  
  283.     case WM_VSCROLL:
  284.  
  285.       HandleVerticalScroll (wParam, lParam);
  286.       break;
  287.  
  288.     case WM_HSCROLL:
  289.  
  290.       HandleHorizontalScroll (wParam, lParam);
  291.       break;
  292.  
  293.     case WM_SIZE:
  294.  
  295.       HandleWindowSizing (lpDIBDisplay, wParam, lParam);
  296.       break;
  297.  
  298.     case WM_COMMAND:
  299.  
  300.       switch (CONTROL_ID (wParam))
  301.       {
  302.         case ID_FILE_PRINT:
  303.  
  304.           if (lpDIB1)
  305.             HandlePrinting (lpDIB1);
  306.           break;
  307.  
  308.         case ID_FILE_PRINT_SETUP:
  309.  
  310.           if (!pPrintDlgStruct)
  311.             InitializePrintStruct ();
  312.  
  313.           if (!pPrintDlgStruct)
  314.             break;
  315.  
  316.           PrintDlgStruct = *pPrintDlgStruct;
  317.           PrintDlgStruct.hwndOwner = hWnd;
  318.           PrintDlgStruct.Flags = PD_PRINTSETUP;
  319.           
  320.           if (PrintDlg (&PrintDlgStruct) == TRUE)
  321.             *pPrintDlgStruct = PrintDlgStruct;
  322.           break;
  323.  
  324.         case ID_FILE_SAVE:
  325.  
  326.           if (lpDIB1)
  327.           {
  328.             if (GetSaveFile (szFileName) == FALSE)
  329.               break;
  330.  
  331.             if (DialogBoxParam (hInst, "IDD_FILETYPE", hWnd, FileTypeProc, (LPARAM)(LPINT)&nFileType) != TRUE)
  332.               break;
  333.  
  334.             UpdateWindowTitle (szFileName, TRUE);
  335.  
  336.             if (WriteDIBToFile (lpDIB1, szFileName, nFileType) == FALSE)
  337.             {
  338.               switch (GetLastImgLibError ())
  339.               {
  340.                 case ERROR_WRITE_ACCESS_DENIED:
  341.                   wsprintf ((LPSTR)szBuffer, (LPSTR)"Error writing to file \"%s\"", (LPSTR)szFileName);
  342.                   break;
  343.                 case ERROR_INVALID_POINTER:
  344.                   wsprintf ((LPSTR)szBuffer, (LPSTR)"Error accessing one of the pointer parameters", (LPSTR)szFileName);
  345.                   break;
  346.                 case ERROR_INCOMPATIBLE_IMAGE:
  347.                   wsprintf ((LPSTR)szBuffer, (LPSTR)"Image format incompatible with the selected file type", (LPSTR)szFileName);
  348.                   break;
  349.               }
  350.               MessageBox (NULL, szBuffer, "Save Error", MB_TASKMODAL | MB_ICONSTOP | MB_OK);
  351.             }
  352.           }
  353.           break;
  354.  
  355.         case ID_FILE_OPEN:
  356.         
  357.           if (GetOpenFile (szFileName) == FALSE)
  358.             break;
  359.  
  360.           SetCursor (LoadCursor (NULL, IDC_WAIT));
  361.           lpDIBNew = ReadFileIntoDIB (szFileName);
  362.           
  363.           if (lpDIBNew)
  364.           {
  365.             bDrawSelection = FALSE;
  366.             UpdateWindowTitle (szFileName, TRUE);
  367.             ProcessNewDIB (lpDIBNew);;
  368.           }
  369.           SetCursor (LoadCursor (NULL, IDC_ARROW));
  370.  
  371.           if (!lpDIBNew)
  372.           {
  373.             switch (GetLastImgLibError ())
  374.             {
  375.               case ERROR_UNSUPPORTED_IMAGE:
  376.                 MessageBox (hWnd, "Unsupported image type", WINDOW_NAME, MB_OK | MB_ICONSTOP);
  377.                 break;
  378.               case ERROR_NO_MEMORY:
  379.                 MessageBox (hWnd, "Out of memory reading image", WINDOW_NAME, MB_OK | MB_ICONSTOP);
  380.                 break;
  381.               case ERROR_INVALID_POINTER:
  382.                 MessageBox (hWnd, "Access violation", WINDOW_NAME, MB_OK | MB_ICONSTOP);
  383.                 break;
  384.             }
  385.           }
  386.           break;
  387.  
  388.         case ID_OPTIONS_TIME:
  389.         
  390.           if (GetOpenFile (szFileName) == FALSE)
  391.             break;
  392.  
  393.           SetCursor (LoadCursor (NULL, IDC_WAIT));
  394.           GetWindowText (hWnd, szOldTitle, sizeof (szOldTitle));
  395.           dwStartTime = GetTickCount ();
  396.  
  397.           for (iCount = 0;iCount < 10;iCount++)
  398.           {
  399.             wsprintf ((LPSTR)szBuffer, (LPSTR)"Testing image loading speed \"%s\" -- %d", (LPSTR)szFileName, iCount);
  400.             UpdateWindowTitle (szBuffer, FALSE);
  401.             lpDIBNew = ReadFileIntoDIB (szFileName);
  402.  
  403.             if (lpDIBNew)
  404.             {
  405.               DIBFree (lpDIBNew);
  406.             }
  407.             else
  408.             {
  409.               break;
  410.             }
  411.           }
  412.           SetWindowText (hWnd, szOldTitle);
  413.           SetCursor (LoadCursor (NULL, IDC_ARROW));
  414.           
  415.           if (iCount == 10)
  416.             wsprintf ((LPSTR)szBuffer, (LPSTR)"File \"%s\" loaded 10 times in %ld milliseconds", (LPSTR)szFileName, GetTickCount () - dwStartTime);
  417.           else
  418.             wsprintf ((LPSTR)szBuffer, (LPSTR)"File \"%s\" failed to load 10 times", (LPSTR)szFileName);
  419.  
  420.           MessageBox (hWnd, szBuffer, "ImgLib Timing Results", MB_OK);
  421.           break;
  422.  
  423.         case ID_FILE_EXIT:
  424.  
  425.           DestroyWindow (hWnd);
  426.           break;
  427.  
  428.         case ID_EDIT_UNDO:
  429.  
  430.           if (lpDIB1 && lpDIB2)
  431.           {
  432.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  433.  
  434.             if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
  435.               DIBFree (lpDIBDisplay);
  436.  
  437.             lpDIBNew = lpDIB2;
  438.             lpDIB2 = lpDIB1;
  439.             lpDIB1 = lpDIBNew;
  440.  
  441.             if (hPalette)
  442.             {
  443.               DeleteObject (hPalette);
  444.               hPalette = NULL;
  445.             }
  446.             
  447.             lpDIBDisplay = CreateDisplayDIB (hWnd, &lpDIB1, &hPalette);
  448.             bDrawSelection = FALSE;
  449.             ResizeWindowToDIB (hWnd, lpDIBDisplay);
  450.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  451.           }
  452.           break;
  453.  
  454.         case ID_EDIT_PASTE:
  455.  
  456.           HandlePasting (wParam, lParam);
  457.           break;
  458.  
  459.         case ID_EDIT_COPY:
  460.  
  461.           HandleCopying (wParam, lParam);
  462.           break;
  463.  
  464.         case ID_EDIT_ZOOM:
  465.  
  466.           HandleZoomin (wParam, lParam);
  467.           break;
  468.  
  469.         case ID_EDIT_EMPTY:
  470.  
  471.           if (OpenClipboard (hWnd))
  472.           {
  473.             EmptyClipboard ();
  474.             CloseClipboard ();
  475.           }
  476.           break;
  477.  
  478.         case ID_PROCESS_BRIGHTNESS:
  479.  
  480.           if (lpDIB1)
  481.           {
  482.             iBrightness = DialogBox (hInst, "IDD_BRIGHTNESS", hWnd, BrightnessProc);
  483.  
  484.             if (iBrightness)
  485.             {
  486.               SetCursor (LoadCursor (NULL, IDC_WAIT));
  487.               lpDIBNew = BrightenDIB (lpDIB1, (short)iBrightness);
  488.               ProcessNewDIB (lpDIBNew);
  489.               SetCursor (LoadCursor (NULL, IDC_ARROW));
  490.             }
  491.           }
  492.           break;
  493.  
  494.         case ID_PROCESS_SMOOTH:
  495.  
  496.           if (lpDIB1)
  497.           {
  498.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  499.             lpDIBNew = SmoothDIB (lpDIB1, 1);
  500.             ProcessNewDIB (lpDIBNew);
  501.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  502.           }
  503.           break;
  504.  
  505.         case ID_PROCESS_HALFTONE:
  506.  
  507.           if (lpDIB1)
  508.           {
  509.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  510.             lpDIBNew = HalftoneDIB (lpDIB1);
  511.             ProcessNewDIB (lpDIBNew);
  512.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  513.           }
  514.           break;
  515.  
  516.         case ID_PROCESS_GRAY:
  517.  
  518.           if (lpDIB1)
  519.           {
  520.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  521.             lpDIBNew = GrayDIB (lpDIB1);
  522.             ProcessNewDIB (lpDIBNew);
  523.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  524.           }
  525.           break;
  526.  
  527.         case ID_PROCESS_EXPAND:
  528.  
  529.           if (lpDIB1)
  530.           {
  531.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  532.             lpDIBNew = ExpandToTrueDIB (lpDIB1);
  533.             ProcessNewDIB (lpDIBNew);
  534.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  535.           }
  536.           break;
  537.  
  538.         case ID_PROCESS_ROT90:
  539.         case ID_PROCESS_ROT180:
  540.         case ID_PROCESS_ROT270:
  541.  
  542.           if (lpDIB1)
  543.           {
  544.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  545.  
  546.             switch (CONTROL_ID (wParam))
  547.             {
  548.               case ID_PROCESS_ROT90:
  549.  
  550.                 lpDIBNew = RotateDIB (lpDIB1, 90);
  551.                 break;
  552.               case ID_PROCESS_ROT180:
  553.  
  554.                 lpDIBNew = RotateDIB (lpDIB1, 180);
  555.                 break;
  556.               case ID_PROCESS_ROT270:
  557.  
  558.                 lpDIBNew = RotateDIB (lpDIB1, 270);
  559.                 break;
  560.             }
  561.             ProcessNewDIB (lpDIBNew);
  562.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  563.           }
  564.           break;
  565.  
  566.         case ID_PROCESS_MIRRORH:
  567.         case ID_PROCESS_MIRRORV:
  568.  
  569.           if (lpDIB1)
  570.           {
  571.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  572.  
  573.             switch (CONTROL_ID (wParam))
  574.             {
  575.               case ID_PROCESS_MIRRORH:
  576.  
  577.                 lpDIBNew = MirrorDIB (lpDIB1, FALSE);
  578.                 break;
  579.               case ID_PROCESS_MIRRORV:
  580.  
  581.                 lpDIBNew = MirrorDIB (lpDIB1, TRUE);
  582.                 break;
  583.             }
  584.             ProcessNewDIB (lpDIBNew);
  585.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  586.           }
  587.           break;
  588.  
  589.         case ID_OPTIONS_TC_DISPLAY_GDI:
  590.  
  591.           hMenu = GetMenu (hWnd);
  592.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_GDI, MF_BYCOMMAND | MF_CHECKED);
  593.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_UNCHECKED);
  594.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_IMGLIB, MF_BYCOMMAND | MF_UNCHECKED);
  595.  
  596.           if (lpDIB1)
  597.           {
  598.             if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
  599.               DIBFree (lpDIBDisplay);
  600.  
  601.             lpDIBDisplay = CreateDisplayDIB (hWnd, &lpDIB1, &hPalette);
  602.             InvalidateRect (hWnd, (LPRECT) (NULL), FALSE);
  603.           }
  604.           break;
  605.  
  606.         case ID_OPTIONS_TC_DISPLAY_WING:
  607.  
  608.           hMenu = GetMenu (hWnd);
  609.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_GDI, MF_BYCOMMAND | MF_UNCHECKED);
  610.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_CHECKED);
  611.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_IMGLIB, MF_BYCOMMAND | MF_UNCHECKED);
  612.  
  613.           if (lpDIB1)
  614.           {
  615.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  616.  
  617.             if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
  618.               DIBFree (lpDIBDisplay);
  619.  
  620.             lpDIBDisplay = CreateDisplayDIB (hWnd, &lpDIB1, &hPalette);
  621.             InvalidateRect (hWnd, (LPRECT) (NULL), FALSE);
  622.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  623.           }
  624.           break;
  625.  
  626.         case ID_OPTIONS_TC_DISPLAY_IMGLIB:
  627.  
  628.           hMenu = GetMenu (hWnd);
  629.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_GDI, MF_BYCOMMAND | MF_UNCHECKED);
  630.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND | MF_UNCHECKED);
  631.           CheckMenuItem (hMenu, ID_OPTIONS_TC_DISPLAY_IMGLIB, MF_BYCOMMAND | MF_CHECKED);
  632.  
  633.           if (lpDIB1)
  634.           {
  635.             SetCursor (LoadCursor (NULL, IDC_WAIT));
  636.  
  637.             if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
  638.               DIBFree (lpDIBDisplay);
  639.  
  640.             lpDIBDisplay = CreateDisplayDIB (hWnd, &lpDIB1, &hPalette);
  641.             InvalidateRect (hWnd, (LPRECT) (NULL), FALSE);
  642.             SetCursor (LoadCursor (NULL, IDC_ARROW));
  643.           }
  644.           break;
  645.  
  646.         case ID_OPTIONS_RETAIN_TC:
  647.  
  648.           hMenu = GetMenu (hWnd);
  649.           if (GetMenuState (hMenu, ID_OPTIONS_RETAIN_TC, MF_BYCOMMAND) & MF_CHECKED)
  650.           {
  651.             CheckMenuItem (hMenu, ID_OPTIONS_RETAIN_TC, MF_BYCOMMAND | MF_UNCHECKED);
  652.  
  653.             if (lpDIBDisplay && lpDIB1 != lpDIBDisplay)
  654.             {
  655.               DIBFree (lpDIB1);
  656.               lpDIB1 = lpDIBDisplay;
  657.             }
  658.           }
  659.           else
  660.           {
  661.             CheckMenuItem (hMenu, ID_OPTIONS_RETAIN_TC, MF_BYCOMMAND | MF_CHECKED);
  662.           }
  663.  
  664.           break;
  665.  
  666.         case ID_HELP_ABOUT:
  667.  
  668.           DialogBox (hInst, "IDD_ABOUT_DIALOG", hWnd, AboutProc);
  669.           break;
  670.  
  671.         default:
  672.           return (DefWindowProc (hWnd, message, wParam, lParam));
  673.       }
  674.       break;
  675.  
  676.     case WM_DESTROY:
  677.  
  678.       if (lpDIB1)
  679.         DIBFree (lpDIB1);
  680.  
  681.       if (lpDIB2)
  682.         DIBFree (lpDIB2);
  683.  
  684.       if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
  685.         DIBFree (lpDIBDisplay);
  686.  
  687.       if (hPalette)
  688.       {
  689.         DeleteObject (hPalette);
  690.         hPalette = NULL;
  691.       }
  692.  
  693.       if (hWinGInst)
  694.       {
  695.         if (hbmpWinG)
  696.         {
  697.           SelectObject (hdcWinG, hbmpWinGOld);
  698.           DeleteObject (hbmpWinG);
  699.         }
  700.         DeleteDC (hdcWinG);
  701.         FreeLibrary (hWinGInst);
  702.       }
  703.       PostQuitMessage(0);
  704.       break;
  705.  
  706.     default:
  707.       return (DefWindowProc (hWnd, message, wParam, lParam));
  708.   }
  709.   return (0);
  710. }
  711.  
  712. /****************************************************************************
  713.     FUNCTION: AboutProc(HWND, UINT, WPARAM, LPARAM)
  714.     PURPOSE:  Processes messages for the About dialog
  715. ****************************************************************************/
  716.  
  717. BOOL CALLBACK AboutProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  718. {
  719. HWND              hwndStatic;
  720. char              szImgLibVer[512];
  721.  
  722.   switch (message)
  723.   {
  724.     case WM_INITDIALOG:
  725.  
  726.       hwndStatic = GetDlgItem (hDlg, IDC_ABOUT_STRING);
  727.       GetImgLibVersion (szImgLibVer, sizeof (szImgLibVer));
  728.       SetWindowText (hwndStatic, szImgLibVer);
  729.       return (TRUE);
  730.  
  731.     case WM_COMMAND:
  732.       if (CONTROL_ID (wParam) == IDOK)
  733.       {
  734.         EndDialog(hDlg, TRUE);
  735.         return (TRUE);
  736.       }
  737.       break;
  738.   }
  739.   return (FALSE);
  740. }
  741.  
  742. /****************************************************************************
  743.     FUNCTION: BrightnessProc(HWND, UINT, WPARAM, LPARAM)
  744.     PURPOSE:  Processes messages for the Brightness Control dialog
  745. ****************************************************************************/
  746.  
  747. BOOL CALLBACK BrightnessProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  748. {
  749. HWND              hwndStatic, hwndScroll;
  750. char              szMessage[32];
  751. int               iScrollCode, iNewPos;
  752. static LPVOID     lpDIBSave;
  753. LPVOID            lpDIBNew;
  754.  
  755.   switch (message)
  756.   {
  757.     case WM_INITDIALOG:
  758.  
  759.       lpDIBSave = lpDIBDisplay;
  760.       hwndScroll = GetDlgItem (hDlg, IDC_BRIGHTNESS_SCROLLBAR);
  761.       SetScrollRange (hwndScroll, SB_CTL, 50, 150, TRUE);
  762.       SetScrollPos (hwndScroll, SB_CTL, 100, TRUE);
  763.       return (TRUE);
  764.  
  765.     case WM_HSCROLL:
  766.  
  767. #ifdef WIN32
  768.       iScrollCode = (int) LOWORD (wParam);
  769.       iNewPos = (int) HIWORD (wParam);
  770. #else
  771.       iScrollCode = (int) wParam;
  772.       iNewPos = (int) LOWORD (lParam);
  773. #endif
  774.       
  775.       hwndScroll = GetDlgItem (hDlg, IDC_BRIGHTNESS_SCROLLBAR);
  776.  
  777.       switch (iScrollCode)
  778.       {
  779.         case SB_ENDSCROLL:
  780.           iNewPos = GetScrollPos (hwndScroll, SB_CTL);
  781.           lpDIBNew = BrightenDIB (lpDIBSave, (short) iNewPos);
  782.  
  783.           if (lpDIBNew)
  784.           {
  785.             if (lpDIBDisplay != lpDIBSave)
  786.               DIBFree (lpDIBDisplay);
  787.  
  788.             lpDIBDisplay = lpDIBNew;
  789.             InvalidateRect (hwndMain, NULL, FALSE);
  790.           }
  791.           break;
  792.     
  793.         case SB_LINEDOWN:
  794.           iNewPos = GetScrollPos (hwndScroll, SB_CTL) + 1;
  795.           break;
  796.  
  797.         case SB_LINEUP:
  798.           iNewPos = GetScrollPos (hwndScroll, SB_CTL) - 1;
  799.           break;
  800.         case SB_PAGEDOWN:
  801.           iNewPos = GetScrollPos (hwndScroll, SB_CTL) + 10;
  802.           break;
  803.  
  804.         case SB_PAGEUP:
  805.           iNewPos = GetScrollPos (hwndScroll, SB_CTL) - 10;
  806.           break;
  807.       }
  808.  
  809.       if (iNewPos < 50)
  810.         iNewPos = 50;
  811.  
  812.       if (iNewPos > 150)
  813.         iNewPos = 150;
  814.  
  815.       wsprintf ((LPSTR)szMessage, (LPSTR)"%d %%", iNewPos);
  816.       hwndStatic = GetDlgItem (hDlg, IDC_BRIGHTNESS_PERCENTAGE);
  817.       SetWindowText (hwndStatic, szMessage);
  818.       SetScrollPos (hwndScroll, SB_CTL, iNewPos, TRUE);
  819.       return (TRUE);
  820.  
  821.     case WM_COMMAND:
  822.  
  823.       switch (CONTROL_ID (wParam))
  824.       {
  825.         case IDOK:
  826.           hwndScroll = GetDlgItem (hDlg, IDC_BRIGHTNESS_SCROLLBAR);
  827.           iNewPos = GetScrollPos (hwndScroll, SB_CTL);
  828.           
  829.           if (lpDIBDisplay != lpDIBSave)
  830.           {
  831.             DIBFree (lpDIBDisplay);
  832.             lpDIBDisplay = lpDIBSave;
  833.           }
  834.           EndDialog(hDlg, iNewPos);
  835.           return (TRUE);
  836.         case IDCANCEL:
  837.           
  838.           if (lpDIBDisplay != lpDIBSave)
  839.           {
  840.             DIBFree (lpDIBDisplay);
  841.             lpDIBDisplay = lpDIBSave;
  842.             InvalidateRect (hwndMain, NULL, FALSE);
  843.           }
  844.           EndDialog(hDlg, FALSE);
  845.           return (TRUE);
  846.       }
  847.       break;
  848.   }
  849.   return (FALSE);
  850. }
  851.  
  852. /****************************************************************************
  853.     FUNCTION: FileTypeProc(HWND, UINT, WPARAM, LPARAM)
  854.     PURPOSE:  Processes messages for the FileType dialog
  855. ****************************************************************************/
  856.  
  857. BOOL CALLBACK FileTypeProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  858. {
  859. static short      *pnFileType;
  860. int               iCtrl;
  861.  
  862.   switch (message)
  863.   {
  864.     case WM_INITDIALOG:
  865.  
  866.       pnFileType = (short *)lParam;
  867.  
  868.       switch (*pnFileType)
  869.       {
  870.         case FILETYPE_BMP:
  871.           iCtrl = IDC_IT_BMP;
  872.           break;
  873.         case FILETYPE_TIFF_DEFAULT:
  874.           iCtrl = IDC_IT_TIFF;
  875.           break;
  876.         case FILETYPE_TIFF_NO_COMPRESSION:
  877.           iCtrl = IDC_IT_TIFF_NOCOMP;
  878.           break;
  879.         case FILETYPE_TIFF_HUFFMAN:
  880.           iCtrl = IDC_IT_TIFF_HUFFMAN;
  881.           break;
  882.         case FILETYPE_TIFF_PACKBITS:
  883.           iCtrl = IDC_IT_TIFF_PACKBITS;
  884.           break;
  885.         case FILETYPE_TIFF_G3:
  886.           iCtrl = IDC_IT_TIFF_G3;
  887.           break;
  888.         case FILETYPE_TIFF_G4:
  889.           iCtrl = IDC_IT_TIFF_G4;
  890.           break;
  891.         default:
  892.           iCtrl = IDC_IT_BMP;
  893.           break;
  894.       }
  895.       CheckRadioButton (hDlg, IDC_IT_BMP, IDC_IT_TIFF_G4, iCtrl);
  896.       return (TRUE);
  897.  
  898.     case WM_COMMAND:
  899.  
  900.       if (CONTROL_ID (wParam) == IDOK)
  901.       {
  902.         if (IsDlgButtonChecked (hDlg, IDC_IT_BMP))
  903.           *pnFileType = FILETYPE_BMP;
  904.         else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF))
  905.           *pnFileType = FILETYPE_TIFF_DEFAULT;
  906.         else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_NOCOMP))
  907.           *pnFileType = FILETYPE_TIFF_NO_COMPRESSION;
  908.         else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_HUFFMAN))
  909.           *pnFileType = FILETYPE_TIFF_HUFFMAN;
  910.         else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_PACKBITS))
  911.           *pnFileType = FILETYPE_TIFF_PACKBITS;
  912.         else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_G3))
  913.           *pnFileType = FILETYPE_TIFF_G3;
  914.         else if (IsDlgButtonChecked (hDlg, IDC_IT_TIFF_G4))
  915.           *pnFileType = FILETYPE_TIFF_G4;
  916.         EndDialog(hDlg, TRUE);
  917.         return (TRUE);
  918.       }
  919.       else if (CONTROL_ID (wParam) == IDCANCEL)
  920.       {
  921.         EndDialog(hDlg, FALSE);
  922.         return (TRUE);
  923.       }
  924.       break;
  925.   }
  926.   return (FALSE);
  927. }
  928.  
  929. /****************************************************************************
  930.     FUNCTION: PrintProc(HWND, UINT, WPARAM, LPARAM)
  931.     PURPOSE:  Processes messages for the Print dialog
  932. ****************************************************************************/
  933.  
  934. BOOL CALLBACK PrintProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  935. {
  936. static LPBITMAPINFOHEADER pBmi;
  937. HWND              hwndCtl;
  938. LPDEVNAMES        pDevNames, pDevNamesNew;
  939. LPDEVMODE         pDevMode, pDevModeNew;
  940. char              szBuffer[256];
  941. static PRINTDLG   PrintDlgStruct;
  942. unsigned int      uCopyCount;
  943. BOOL              bConvertOK;
  944. HANDLE            hDevModeNew, hDevNamesNew;
  945.  
  946.   switch (message)
  947.   {
  948.     case WM_INITDIALOG:
  949.  
  950.       PrintDlgStruct = *pPrintDlgStruct;
  951.       SetDlgItemInt (hDlg, IDC_COPY_COUNT, uPrintCopies, FALSE);
  952.       pBmi = (LPBITMAPINFOHEADER) lParam;
  953.       pDevNames = (LPDEVNAMES)GlobalLock (pPrintDlgStruct->hDevNames);
  954.       pDevMode = (LPDEVMODE)GlobalLock (pPrintDlgStruct->hDevMode);
  955.  
  956.       /*
  957.        * Make copies of the DEVNAMES and DEVMODE structures
  958.        */
  959.       hDevNamesNew = GlobalAlloc (GMEM_MOVEABLE, GlobalSize (pPrintDlgStruct->hDevNames));
  960.       pDevNamesNew = (LPDEVNAMES) GlobalLock (hDevNamesNew);
  961.       hDevModeNew = GlobalAlloc (GMEM_MOVEABLE, GlobalSize (pPrintDlgStruct->hDevMode));
  962.       pDevModeNew = (LPDEVMODE) GlobalLock (hDevModeNew);
  963.       copymem (pDevModeNew, pDevMode, GlobalSize (hDevModeNew));
  964.       copymem (pDevNamesNew, pDevNames, GlobalSize (hDevNamesNew));
  965.       GlobalUnlock (pPrintDlgStruct->hDevNames);
  966.       GlobalUnlock (pPrintDlgStruct->hDevMode);
  967.       PrintDlgStruct.hDevMode = hDevModeNew;
  968.       PrintDlgStruct.hDevNames = hDevNamesNew;
  969.  
  970.       if (pBmi->biPlanes * pBmi->biBitCount == 1 || pDevModeNew->dmColor == DMCOLOR_COLOR)   // monochrome bitmap or color printer
  971.       {
  972.         hwndCtl = GetDlgItem (hDlg, IDC_HALFTONE_GROUP);
  973.         EnableWindow (hwndCtl, FALSE);
  974.         hwndCtl = GetDlgItem (hDlg, IDC_METHOD_GDI);
  975.         EnableWindow (hwndCtl, FALSE);
  976.         hwndCtl = GetDlgItem (hDlg, IDC_METHOD_IMGLIB);
  977.         EnableWindow (hwndCtl, FALSE);
  978.       }
  979.       else
  980.       {
  981.         if (bHalftoneImgLib)
  982.           CheckRadioButton (hDlg, IDC_METHOD_GDI, IDC_METHOD_IMGLIB, IDC_METHOD_IMGLIB);
  983.         else
  984.           CheckRadioButton (hDlg, IDC_METHOD_GDI, IDC_METHOD_IMGLIB, IDC_METHOD_GDI);
  985.       }
  986.       if (bFillPage)
  987.         CheckDlgButton (hDlg, IDC_FILL_PAGE, TRUE);
  988.  
  989.       wsprintf ((LPSTR)szBuffer, (LPSTR)"%s on %s", (LPSTR)pDevNamesNew + pDevNamesNew->wDeviceOffset, (LPSTR)pDevNamesNew + pDevNamesNew->wOutputOffset);
  990.       SetDlgItemText (hDlg, IDC_PRINTERNAME, szBuffer);
  991.       GlobalUnlock (hDevNamesNew);
  992.       GlobalUnlock (hDevModeNew);
  993.       return (TRUE);
  994.  
  995.     case WM_COMMAND:
  996.  
  997.       switch (CONTROL_ID (wParam))
  998.       {
  999.         case IDC_SETUP_PRINTER:
  1000.  
  1001.           PrintDlgStruct.hwndOwner = hDlg;
  1002.           PrintDlgStruct.Flags = PD_PRINTSETUP;
  1003.           if (PrintDlg (&PrintDlgStruct))
  1004.           {
  1005.             pDevModeNew = (LPDEVMODE) GlobalLock (PrintDlgStruct.hDevMode);
  1006.             if (pBmi->biPlanes * pBmi->biBitCount == 1 || pDevModeNew->dmColor == DMCOLOR_COLOR)   // monochrome bitmap or color printer
  1007.             {
  1008.               hwndCtl = GetDlgItem (hDlg, IDC_HALFTONE_GROUP);
  1009.               EnableWindow (hwndCtl, FALSE);
  1010.               hwndCtl = GetDlgItem (hDlg, IDC_METHOD_GDI);
  1011.               EnableWindow (hwndCtl, FALSE);
  1012.               hwndCtl = GetDlgItem (hDlg, IDC_METHOD_IMGLIB);
  1013.               EnableWindow (hwndCtl, FALSE);
  1014.             }
  1015.             else
  1016.             {
  1017.               hwndCtl = GetDlgItem (hDlg, IDC_HALFTONE_GROUP);
  1018.               EnableWindow (hwndCtl, TRUE);
  1019.               hwndCtl = GetDlgItem (hDlg, IDC_METHOD_GDI);
  1020.               EnableWindow (hwndCtl, TRUE);
  1021.               hwndCtl = GetDlgItem (hDlg, IDC_METHOD_IMGLIB);
  1022.               EnableWindow (hwndCtl, TRUE);
  1023.             }
  1024.             GlobalUnlock (PrintDlgStruct.hDevMode);
  1025.           }
  1026.           return (TRUE);
  1027.  
  1028.         case IDOK:
  1029.  
  1030.           uCopyCount = GetDlgItemInt (hDlg, IDC_COPY_COUNT, &bConvertOK, FALSE);
  1031.  
  1032.           if (!bConvertOK || uCopyCount < 1 || uCopyCount > 100)
  1033.           {
  1034.             MessageBox (hDlg, "Invalid value.  Please enter a number between 1 and 100", "Print", MB_ICONSTOP | MB_OK);
  1035.             SetFocus (GetDlgItem (hDlg, IDC_COPY_COUNT));
  1036.             return (TRUE);
  1037.           }
  1038.           uPrintCopies = uCopyCount;
  1039.           bFillPage = IsDlgButtonChecked (hDlg, IDC_FILL_PAGE);
  1040.           bHalftoneImgLib = IsDlgButtonChecked (hDlg, IDC_METHOD_IMGLIB);
  1041.           GlobalFree (pPrintDlgStruct->hDevNames);
  1042.           GlobalFree (pPrintDlgStruct->hDevMode);
  1043.           *pPrintDlgStruct = PrintDlgStruct;
  1044.           EndDialog (hDlg, TRUE);
  1045.           return (TRUE);
  1046.  
  1047.         case IDCANCEL:
  1048.  
  1049.           GlobalFree (PrintDlgStruct.hDevNames);
  1050.           GlobalFree (PrintDlgStruct.hDevMode);
  1051.           EndDialog (hDlg, FALSE);
  1052.           return (TRUE);
  1053.       }
  1054.       break;
  1055.   }
  1056.   return (FALSE);
  1057. }
  1058.  
  1059. /*************************************************************************
  1060.   Function:  GetOpenFile (LPSTR. WORD)
  1061.    Purpose:  Prompts user for a filename through the use of a Windows
  1062.              FileOpen common dialog box.
  1063.    Returns:  TRUE if a filename is selected.
  1064.              FALSE if no filename is selected.
  1065.   Comments:  Filename is put into the string passed to the routine.
  1066.              If a filename is not selected, NULL is returned.
  1067. *************************************************************************/
  1068.  
  1069. BOOL GetOpenFile (LPSTR szFileName)
  1070. {
  1071. OPENFILENAME   of;
  1072. DWORD          flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
  1073. static char    szTitle[30];         // Dialog Box title
  1074. static char    szTemplate[20];      // Dialog Box template
  1075. static char    szFile[256];         // File name
  1076. static char    szFileTitle[256];    // Title
  1077. static char    szDrive[5];          // Drive
  1078. static char    szDir[256];          // Directory
  1079. char szFilter[] =                   // Filter
  1080.   "Pictures\0*.bmp;*.jpg;*.tga;*.pcd;*.pcx;*.tif\0All Files\0*.*\0";
  1081. LPSTR          pFile;
  1082.  
  1083.    szFile[0] = '\0';
  1084.    of.lStructSize       = sizeof (OPENFILENAME);
  1085.    of.hwndOwner         = hwndMain;
  1086.    of.hInstance         = hInst;
  1087.    of.lpstrFilter       = szFilter;
  1088.    of.lpstrCustomFilter = NULL;
  1089.    of.nMaxCustFilter    = 0L;
  1090.    of.nFilterIndex      = 1L;
  1091.    of.lpstrFile         = szFile;
  1092.    of.nMaxFile          = sizeof (szFile);
  1093.    of.lpstrFileTitle    = szFileTitle;
  1094.    of.nMaxFileTitle     = sizeof (szFileTitle);
  1095.    of.lpstrInitialDir   = szDir;
  1096.    of.lpstrTitle        = "Open a new test bitmap file";
  1097.    of.Flags             = flags;
  1098.    of.nFileOffset       = 0;
  1099.    of.nFileExtension    = 0;
  1100.    of.lpstrDefExt       = NULL;
  1101.    of.lCustData         = 0;
  1102.    of.lpfnHook          = NULL;
  1103.    of.lpTemplateName    = NULL;
  1104.  
  1105.   if (GetOpenFileName (&of))
  1106.   {
  1107.     lstrcpy (szFileName, of.lpstrFile);
  1108.     lstrcpy (szDir, of.lpstrFile);
  1109.     pFile = strrchr (szDir, '\\');
  1110.  
  1111.     if (pFile)
  1112.       *pFile = 0;
  1113.  
  1114.     return TRUE;
  1115.   }
  1116.   else
  1117.     return FALSE;
  1118. }
  1119.  
  1120. /*************************************************************************
  1121.   Function:  GetSaveFile (LPSTR. WORD)
  1122.    Purpose:  Prompts user for a filename through the use of a Windows
  1123.              FileOpen common dialog box.
  1124.    Returns:  TRUE if a filename is selected.
  1125.              FALSE if no filename is selected.
  1126.   Comments:  Filename is put into the string passed to the routine.
  1127.              If a filename is not selected, NULL is returned.
  1128. *************************************************************************/
  1129.  
  1130. BOOL GetSaveFile (LPSTR szFileName)
  1131. {
  1132. OPENFILENAME   of;
  1133. DWORD          flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
  1134. static char    szTitle[30];         // Dialog Box title
  1135. static char    szTemplate[20];      // Dialog Box template
  1136. static char    szFile[256];         // File name
  1137. static char    szFileTitle[256];    // Title
  1138. static char    szDrive[5];          // Drive
  1139. static char    szDir[256];          // Directory
  1140. char szFilter[] =                   // Filter
  1141.   "Windows Pictures\0*.bmp;*.tif\0All Files\0*.*\0";
  1142. LPSTR          pFile;
  1143.  
  1144.    szFile[0] = '\0';
  1145.    of.lStructSize       = sizeof (OPENFILENAME);
  1146.    of.hwndOwner         = GetFocus ();
  1147.    of.hInstance         = hInst;
  1148.    of.lpstrFilter       = szFilter;
  1149.    of.lpstrCustomFilter = NULL;
  1150.    of.nMaxCustFilter    = 0L;
  1151.    of.nFilterIndex      = 1L;
  1152.    of.lpstrFile         = szFile;
  1153.    of.nMaxFile          = sizeof (szFile);
  1154.    of.lpstrFileTitle    = szFileTitle;
  1155.    of.nMaxFileTitle     = sizeof (szFileTitle);
  1156.    of.lpstrInitialDir   = szDir;
  1157.    of.lpstrTitle        = "Save the image in a bitmap file";
  1158.    of.Flags             = flags;
  1159.    of.nFileOffset       = 0;
  1160.    of.nFileExtension    = 0;
  1161.    of.lpstrDefExt       = "*.bmp";
  1162.    of.lCustData         = 0;
  1163.    of.lpfnHook          = NULL;
  1164.    of.lpTemplateName    = NULL;
  1165.  
  1166.   if (GetSaveFileName (&of))
  1167.   {
  1168.     lstrcpy (szFileName, of.lpstrFile);
  1169.     lstrcpy (szDir, of.lpstrFile);
  1170.     pFile = strrchr (szDir, '\\');
  1171.  
  1172.     if (pFile)
  1173.       *pFile = 0;
  1174.  
  1175.     return TRUE;
  1176.   }
  1177.   else
  1178.     return FALSE;
  1179. }
  1180.  
  1181. /*************************************************************************
  1182.   Function:  CreateDisplayDIB()
  1183.    Purpose:  Creates a DIB suitable for the display based on user-selected options.
  1184.    Returns:  a new DIB pointer
  1185. *************************************************************************/
  1186.  
  1187. LPVOID CreateDisplayDIB (HWND hwnd, LPVOID *lpDIB, HPALETTE *phPal)
  1188. {
  1189. HMENU             hMenu;
  1190. LPBITMAPINFO      pBitmapInfo;
  1191. UINT              uState;
  1192. LPVOID            lpDIBDisplay;
  1193. long              lColors;
  1194. int               iPixelBits, iPlanes;
  1195. HDC               hDC;
  1196.  
  1197.   hDC = GetDC (hwnd);
  1198.   iPixelBits = GetDeviceCaps (hDC, BITSPIXEL);
  1199.   iPlanes = GetDeviceCaps (hDC, PLANES);
  1200.   ReleaseDC (hwnd, hDC);
  1201.  
  1202.   if (iPixelBits * iPlanes > 8)
  1203.   {
  1204.     /*
  1205.      * No color reduction on true color (or high color) displays
  1206.      */
  1207.     *phPal = NULL;
  1208.     return (*lpDIB);
  1209.   }
  1210.   pBitmapInfo = (LPBITMAPINFO) *lpDIB;
  1211.   hMenu = GetMenu (hwnd);
  1212.   uState = GetMenuState (hMenu, ID_OPTIONS_TC_DISPLAY_GDI, MF_BYCOMMAND);
  1213.  
  1214.   if (uState & MF_CHECKED || pBitmapInfo->bmiHeader.biClrUsed)
  1215.   {
  1216.     lpDIBDisplay = *lpDIB;
  1217.     
  1218.     if (pBitmapInfo->bmiHeader.biClrUsed > 2)
  1219.       *phPal = CreateDIBPalette (lpDIBDisplay);
  1220.     else
  1221.       *phPal = NULL;
  1222.   }
  1223.   else
  1224.   {
  1225.     uState = GetMenuState (hMenu, ID_OPTIONS_TC_DISPLAY_WING, MF_BYCOMMAND);
  1226.  
  1227.     if (uState & MF_CHECKED && hWinGInst)
  1228.     {
  1229.       lpDIBDisplay = WinGHalftoneDIB (*lpDIB, phPal);
  1230.     }
  1231.     else
  1232.     {
  1233.       lColors = 1 << iPixelBits * iPlanes;
  1234.       lpDIBDisplay = ReduceDIB (*lpDIB, lColors, TRUE);
  1235.       *phPal = CreateDIBPalette (lpDIBDisplay);
  1236.     }
  1237.  
  1238.     if (lpDIBDisplay && lpDIBDisplay != *lpDIB)
  1239.     {
  1240.       if (!(GetMenuState (hMenu, ID_OPTIONS_RETAIN_TC, MF_BYCOMMAND) & MF_CHECKED))
  1241.       {
  1242.         DIBFree (*lpDIB);
  1243.         *lpDIB = lpDIBDisplay;
  1244.       }
  1245.     }
  1246.   }
  1247. #ifdef USE_WING
  1248.   /*
  1249.    * Use WinG for displaying if available
  1250.    */
  1251.  
  1252.   if (hWinGInst)
  1253.     UpdateWinGBitmap (lpDIBDisplay);
  1254. #endif
  1255.   return (lpDIBDisplay);
  1256. }
  1257.  
  1258. /*************************************************************************
  1259.   Function:  UpdateWindowTitle ()
  1260.    Purpose:  Updates the window title with the name of the file displayed.
  1261.    Returns:  none
  1262. *************************************************************************/
  1263.  
  1264. static void UpdateWindowTitle (LPSTR pszFilePath, BOOL bStripPath)
  1265. {
  1266. static char       szWindowName[260];
  1267. char              szFileName[260];
  1268. char              *pszFileName = NULL;
  1269.  
  1270.   if (pszFilePath && *pszFilePath)
  1271.   {
  1272.     /*
  1273.      * Make local copy because in 16-bit world strrchr can only operate on
  1274.      * near pointers.
  1275.      */
  1276.     lstrcpy (szFileName, pszFilePath);
  1277.  
  1278.     if (bStripPath)
  1279.       pszFileName = strrchr (szFileName, '\\');
  1280.  
  1281.     /*
  1282.      * If found the last path delimiter, skip over it.
  1283.      */
  1284.     if (pszFileName)
  1285.       pszFileName++;
  1286.     else
  1287.       pszFileName = szFileName;
  1288.  
  1289.     wsprintf ((LPSTR)szWindowName, (LPSTR)"%s -- %s", (LPSTR)WINDOW_NAME, (LPSTR)pszFileName);
  1290.   }
  1291.   else
  1292.     wsprintf ((LPSTR)szWindowName, (LPSTR)"%s", (LPSTR)WINDOW_NAME);
  1293.  
  1294.   SetWindowText (hwndMain, szWindowName);
  1295. }
  1296.  
  1297. /*************************************************************************
  1298.   Function:  ResizeWindowToDIB ()
  1299.    Purpose:  Updates the window size to fit the given device-independent DIB
  1300.    Returns:  none
  1301. *************************************************************************/
  1302.  
  1303. static void ResizeWindowToDIB (HWND hwnd, LPVOID pDIB)
  1304. {
  1305. int               iWidth, iHeight, iXOverhead, iYOverhead;
  1306. int               iScreenWidth, iScreenHeight, iXPos, iYPos;
  1307. int               iHScrollRange, iVScrollRange;
  1308. LPBITMAPINFOHEADER pBmi = (LPBITMAPINFOHEADER)pDIB;
  1309. HDC               hDC;
  1310. RECT              rect;
  1311. BOOL              bHScroll, bVScroll;
  1312. DWORD             dwStyle;
  1313.  
  1314.   bHScroll = bVScroll = FALSE;
  1315.   GetWindowRect (hwnd, &rect);
  1316.   iXPos = rect.left;
  1317.  
  1318.   if (iXPos < 0)
  1319.     iXPos = 0;
  1320.  
  1321.   iYPos = rect.top;
  1322.  
  1323.   if (iYPos < 0)
  1324.     iYPos = 0;
  1325.  
  1326.   hDC = GetDC (hwnd);
  1327.   iScreenWidth = GetDeviceCaps (hDC, HORZRES);
  1328.   iScreenHeight = GetDeviceCaps (hDC, VERTRES);
  1329.   ReleaseDC (hwnd, hDC);
  1330.   iWidth = (int)pBmi->biWidth;
  1331.   iHeight = (int)pBmi->biHeight;
  1332.   iXOverhead = GetSystemMetrics (SM_CXFRAME) * 2;
  1333.   iYOverhead = GetSystemMetrics (SM_CYFRAME) * 2 + GetSystemMetrics (SM_CYCAPTION) + GetSystemMetrics (SM_CYMENU);
  1334.  
  1335.   if (iWidth + iXOverhead + iXPos > iScreenWidth)
  1336.   {
  1337.     iXPos = iScreenWidth - iWidth - iXOverhead;
  1338.  
  1339.     if (iXPos < 0)
  1340.     {
  1341.       iHScrollRange = -iXPos;
  1342.       iXPos = 0;
  1343.       bHScroll = TRUE;
  1344.     }
  1345.   }
  1346.   if (iHeight + iYOverhead + iYPos > iScreenHeight)
  1347.   {
  1348.     iYPos = iScreenHeight - iHeight - iYOverhead;
  1349.  
  1350.     if (iYPos < 0)
  1351.     {
  1352.       iVScrollRange = -iYPos;
  1353.       iYPos = 0;
  1354.       bVScroll = TRUE;
  1355.     }
  1356.   }
  1357.   dwStyle = GetWindowLong (hwnd, GWL_STYLE);
  1358.  
  1359.   if (bHScroll)
  1360.   {
  1361.     ShowScrollBar (hwndMain, SB_HORZ, TRUE);
  1362.     /*
  1363.      * Having the vertical scrollbar will "steal" some more pixels
  1364.      * from the client area.  Check and adjust for it here.
  1365.      */
  1366.     if (bVScroll)
  1367.       iHScrollRange += GetSystemMetrics (SM_CXVSCROLL);
  1368.   }
  1369.   else
  1370.   {
  1371.     /*
  1372.      * Remove the scrollbar
  1373.      */
  1374.     if (dwStyle & WS_HSCROLL)
  1375.     {
  1376.       SetScrollPos (hwnd, SB_HORZ, 0, TRUE);
  1377.       ShowScrollBar (hwndMain, SB_HORZ, FALSE);
  1378.     }
  1379.   }
  1380.   if (bVScroll)
  1381.   {
  1382.     ShowScrollBar (hwndMain, SB_VERT, TRUE);
  1383.     /*
  1384.      * Having the horizontal scrollbar will "steal" some more pixels
  1385.      * from the client area.  Check and adjust for it here.
  1386.      */
  1387.     if (bHScroll)
  1388.       iVScrollRange += GetSystemMetrics (SM_CYHSCROLL);
  1389.   }
  1390.   else
  1391.   {
  1392.     /*
  1393.      * Remove the scrollbar
  1394.      */
  1395.     if (dwStyle & WS_VSCROLL)
  1396.     {
  1397.       SetScrollPos (hwnd, SB_VERT, 0, TRUE);
  1398.       ShowScrollBar (hwndMain, SB_VERT, FALSE);
  1399.     }
  1400.   }
  1401.   
  1402.   /*
  1403.    * Having done all this checking, the following call may still cause the
  1404.    * addition of scrollbars in rare circumstances like the menu bar becoming
  1405.    * 2-line.
  1406.    */
  1407.   SetWindowPos (hwnd, HWND_TOP, iXPos, iYPos, min (iXOverhead + iWidth, iScreenWidth),
  1408.                 min (iYOverhead + iHeight, iScreenHeight),
  1409.                 SWP_NOACTIVATE | SWP_NOZORDER);
  1410.   if (bHScroll)
  1411.     SetScrollRange (hwnd, SB_HORZ, 0, iHScrollRange, TRUE);
  1412.   if (bVScroll)
  1413.     SetScrollRange (hwnd, SB_VERT, 0, iVScrollRange, TRUE);
  1414.  
  1415.   InvalidateRect (hwnd, (LPRECT) (NULL), FALSE);
  1416. }
  1417.  
  1418. /*************************************************************************
  1419.   Function:  HandleVerticalScroll ()
  1420.    Purpose:  Process the vertical scrollbar operations.
  1421.    Returns:  none
  1422. *************************************************************************/
  1423.  
  1424. static void HandleVerticalScroll (WPARAM wParam, LPARAM lParam)
  1425. {
  1426. int               nScrollCode, iNewPos, iVScroll, iHScroll;
  1427. int               iCurrPos, iMinScroll, iMaxScroll, iClientHeight;
  1428. RECT              rect;
  1429.  
  1430.   UpdateWindow (hwndMain);
  1431.  
  1432. #ifdef WIN32
  1433.   nScrollCode = (int) LOWORD (wParam);
  1434.   iNewPos = (int) HIWORD (wParam);
  1435. #else
  1436.   nScrollCode = (int) wParam;
  1437.   iNewPos = (int) LOWORD (lParam);
  1438. #endif
  1439.  
  1440.   GetClientRect (hwndMain, &rect);
  1441.   iClientHeight = rect.bottom;
  1442.   iHScroll = iVScroll = 0;
  1443.   GetScrollRange (hwndMain, SB_VERT, &iMinScroll, &iMaxScroll);
  1444.   iCurrPos = GetScrollPos (hwndMain, SB_VERT);
  1445.  
  1446.   switch (nScrollCode)
  1447.   {
  1448.     case SB_BOTTOM:
  1449.       
  1450.       iVScroll = iMaxScroll - iCurrPos;
  1451.       break;
  1452.  
  1453.     case SB_PAGEDOWN:
  1454.  
  1455.       if (iCurrPos + iClientHeight <= iMaxScroll)
  1456.         iVScroll = -iClientHeight;
  1457.       else
  1458.         iVScroll = - (iMaxScroll - iCurrPos);
  1459.  
  1460.       break;
  1461.  
  1462.     case SB_PAGEUP:
  1463.  
  1464.       if (iCurrPos - iClientHeight >= 0)
  1465.         iVScroll = iClientHeight;
  1466.       else
  1467.         iVScroll = iCurrPos;
  1468.  
  1469.       break;
  1470.  
  1471.     case SB_THUMBTRACK:
  1472.     case SB_THUMBPOSITION:
  1473.       iVScroll = GetScrollPos (hwndMain, SB_VERT) - iNewPos;
  1474.       break;
  1475.   
  1476.     case SB_LINEDOWN:
  1477.  
  1478.       iVScroll = -1;
  1479.       break;
  1480.  
  1481.     case SB_LINEUP:
  1482.  
  1483.       iVScroll = 1;
  1484.       break;
  1485.  
  1486.     case SB_ENDSCROLL:
  1487.  
  1488.       return;
  1489.   }
  1490.   if (iCurrPos - iVScroll > iMaxScroll)
  1491.     iVScroll = iCurrPos - iMaxScroll;
  1492.  
  1493.   if (iCurrPos - iVScroll < iMinScroll)
  1494.     iVScroll = iCurrPos - iMinScroll;
  1495.  
  1496.   if (!iVScroll)
  1497.     return;
  1498.  
  1499.   ScrollWindow (hwndMain, iHScroll, iVScroll, NULL, &rect);
  1500.   SetScrollPos (hwndMain, SB_VERT, iCurrPos - iVScroll, TRUE);
  1501. }
  1502.  
  1503. /*************************************************************************
  1504.   Function:  HandleHorizontalScroll ()
  1505.    Purpose:  Process the horozontal scrollbar operations.
  1506.    Returns:  none
  1507. *************************************************************************/
  1508.  
  1509. static void HandleHorizontalScroll (WPARAM wParam, LPARAM lParam)
  1510. {
  1511. int               nScrollCode, iNewPos, iVScroll, iHScroll;
  1512. int               iCurrPos, iMinScroll, iMaxScroll, iClientWidth;
  1513. RECT              rect;
  1514.  
  1515.   UpdateWindow (hwndMain);
  1516.  
  1517. #ifdef WIN32
  1518.   nScrollCode = (int) LOWORD (wParam);
  1519.   iNewPos = (int) HIWORD (wParam);
  1520. #else
  1521.   nScrollCode = (int) wParam;
  1522.   iNewPos = (int) LOWORD (lParam);
  1523. #endif
  1524.  
  1525.   GetClientRect (hwndMain, &rect);
  1526.   iClientWidth = rect.right;
  1527.   iHScroll = iVScroll = 0;
  1528.   GetScrollRange (hwndMain, SB_HORZ, &iMinScroll, &iMaxScroll);
  1529.   iCurrPos = GetScrollPos (hwndMain, SB_HORZ);
  1530.  
  1531.   switch (nScrollCode)
  1532.   {
  1533.     case SB_BOTTOM:
  1534.       
  1535.       iHScroll = iMaxScroll - iCurrPos;
  1536.       break;
  1537.  
  1538.     case SB_PAGEDOWN:
  1539.  
  1540.       if (iCurrPos + iClientWidth <= iMaxScroll)
  1541.         iHScroll = -iClientWidth;
  1542.       else
  1543.         iHScroll = - (iMaxScroll - iCurrPos);
  1544.  
  1545.       break;
  1546.  
  1547.     case SB_PAGEUP:
  1548.  
  1549.       if (iCurrPos - iClientWidth >= 0)
  1550.         iHScroll = iClientWidth;
  1551.       else
  1552.         iHScroll = iCurrPos;
  1553.  
  1554.       break;
  1555.  
  1556.     case SB_THUMBTRACK:
  1557.     case SB_THUMBPOSITION:
  1558.       iHScroll = GetScrollPos (hwndMain, SB_HORZ) - iNewPos;
  1559.       break;
  1560.   
  1561.     case SB_LINEDOWN:
  1562.  
  1563.       iHScroll = -1;
  1564.       break;
  1565.  
  1566.     case SB_LINEUP:
  1567.  
  1568.       iHScroll = 1;
  1569.       break;
  1570.  
  1571.     case SB_ENDSCROLL:
  1572.  
  1573.       return;
  1574.   }
  1575.   if (iCurrPos - iHScroll > iMaxScroll)
  1576.     iHScroll = iCurrPos - iMaxScroll;
  1577.  
  1578.   if (iCurrPos - iHScroll < iMinScroll)
  1579.     iHScroll = iCurrPos - iMinScroll;
  1580.  
  1581.   if (!iHScroll)
  1582.     return;
  1583.  
  1584.   ScrollWindow (hwndMain, iHScroll, iVScroll, NULL, &rect);
  1585.   SetScrollPos (hwndMain, SB_HORZ, iCurrPos - iHScroll, TRUE);
  1586. }
  1587.  
  1588. /*************************************************************************
  1589.   Function:  HandleWindowSizing ()
  1590.    Purpose:  Process the WM_SIZE messages.
  1591.    Returns:  none
  1592. *************************************************************************/
  1593.  
  1594. static void HandleWindowSizing (LPVOID pDIB, WPARAM wParam, LPARAM lParam)
  1595. {
  1596. LPBITMAPINFOHEADER pBmi = (LPBITMAPINFOHEADER)pDIB;
  1597. BOOL              bHScroll, bVScroll;
  1598. DWORD             dwStyle;
  1599. int               iNewWidth, iNewHeight;
  1600. int               iHScrollRange, iVScrollRange;
  1601. int               iPos;
  1602. static BOOL       bSizing;
  1603.  
  1604.   /*
  1605.    * Prevent resizing from infinitely recursing.  This may be caused by having
  1606.    * to add or take away a scrollbar which in turn causes another WM_SIZE
  1607.    * message to be generated as the client area is affected by the scrollbars.
  1608.    */
  1609.   if (bSizing)
  1610.     return;
  1611.   if (!pBmi)
  1612.     return;
  1613.   if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE || wParam == SIZE_MAXSHOW)
  1614.     return;
  1615.  
  1616.   bSizing = TRUE;
  1617.   bHScroll = bVScroll = FALSE;
  1618.   iHScrollRange = iVScrollRange = 0;
  1619.   dwStyle = GetWindowLong (hwndMain, GWL_STYLE);
  1620.   iNewWidth = (int) LOWORD (lParam);
  1621.   iNewHeight = (int) HIWORD (lParam);
  1622.  
  1623.   if (dwStyle & WS_HSCROLL)
  1624.     iNewHeight += GetSystemMetrics (SM_CYHSCROLL);
  1625.  
  1626.   if (dwStyle & WS_VSCROLL)
  1627.     iNewWidth += GetSystemMetrics (SM_CXVSCROLL);
  1628.  
  1629.   /*
  1630.    * The following code determines if the scrollbars are required.
  1631.    * Adding a scrollbar "steals" pixels from client area, so the affected
  1632.    * dimension must be rechecked for a need of scrollbar.
  1633.    */
  1634.   if (pBmi->biWidth > iNewWidth)
  1635.   {
  1636.     bHScroll = TRUE;
  1637.     iHScrollRange = (int)pBmi->biWidth - iNewWidth;
  1638.     iNewHeight -= GetSystemMetrics (SM_CYHSCROLL);
  1639.   }
  1640.  
  1641.   if (pBmi->biHeight > iNewHeight)
  1642.   {
  1643.     bVScroll = TRUE;
  1644.     iVScrollRange = (int)pBmi->biHeight - iNewHeight;
  1645.     iNewWidth -= GetSystemMetrics (SM_CXVSCROLL);
  1646.  
  1647.     /*
  1648.      * Recheck the width to see if a horizontal scrollbar may be ncecessary.
  1649.      */
  1650.     if (pBmi->biWidth > iNewWidth && !bHScroll)
  1651.     {
  1652.       bHScroll = TRUE;
  1653.       iHScrollRange = (int)pBmi->biWidth - iNewWidth;
  1654.       iNewHeight -= GetSystemMetrics (SM_CYHSCROLL);
  1655.       iVScrollRange += GetSystemMetrics (SM_CYHSCROLL);
  1656.     }
  1657.   }
  1658.  
  1659.   if (!bHScroll && (dwStyle & WS_HSCROLL))
  1660.   {
  1661.     /*
  1662.      * Remove the scrollbar
  1663.      */
  1664.     SetScrollPos (hwndMain, SB_HORZ, 0, TRUE);
  1665.     ShowScrollBar (hwndMain, SB_HORZ, FALSE);
  1666.   }
  1667.   if (!bVScroll && (dwStyle & WS_VSCROLL))
  1668.   {
  1669.     /*
  1670.      * Remove the scrollbar
  1671.      */
  1672.     SetScrollPos (hwndMain, SB_VERT, 0, TRUE);
  1673.     ShowScrollBar (hwndMain, SB_VERT, FALSE);
  1674.   }
  1675.   /*
  1676.    * Update the scrollbar positions and ranges
  1677.    */
  1678.   if (bHScroll)
  1679.   {
  1680.     ShowScrollBar (hwndMain, SB_HORZ, TRUE);
  1681.     iPos = GetScrollPos (hwndMain, SB_HORZ);
  1682.  
  1683.     if (iPos > iHScrollRange)
  1684.     {
  1685.       InvalidateRect (hwndMain, NULL, FALSE);
  1686.       SetScrollPos (hwndMain, SB_HORZ, iHScrollRange, TRUE);
  1687.     }
  1688.     SetScrollRange (hwndMain, SB_HORZ, 0, iHScrollRange, TRUE);
  1689.   }
  1690.   if (bVScroll)
  1691.   {
  1692.     ShowScrollBar (hwndMain, SB_VERT, TRUE);
  1693.     iPos = GetScrollPos (hwndMain, SB_VERT);
  1694.  
  1695.     if (iPos > iVScrollRange)
  1696.     {
  1697.       InvalidateRect (hwndMain, NULL, FALSE);
  1698.       SetScrollPos (hwndMain, SB_VERT, iVScrollRange, TRUE);
  1699.     }
  1700.     SetScrollRange (hwndMain, SB_VERT, 0, iVScrollRange, TRUE);
  1701.   }
  1702.   bSizing = FALSE;
  1703. }
  1704.  
  1705. /*************************************************************************
  1706.   Function:  HandlePrinting ()
  1707.    Purpose:  Process the File/Print request.
  1708.    Returns:  none
  1709. *************************************************************************/
  1710.  
  1711. static void HandlePrinting (LPVOID lpDIB)
  1712. {
  1713. HDC               hDC;
  1714. LPDEVNAMES        pDevNames;
  1715. LPDEVMODE         pDevMode;
  1716. LPVOID            lpDIBPrint = NULL;
  1717. LPBITMAPINFOHEADER pBih;
  1718. LPBITMAPINFO      pBmi;
  1719. char              szTitle[128];
  1720. DOCINFO           DocInfo;
  1721. int               iXMargin, iYMargin, iWidth, iHeight;
  1722.  
  1723.   if (!pPrintDlgStruct)
  1724.   {
  1725.     InitializePrintStruct ();
  1726.  
  1727.     if (!pPrintDlgStruct)
  1728.       return;
  1729.   }
  1730.   if (!DialogBoxParam (hInst, "IDD_PRINT", hwndMain, PrintProc, (LPARAM)lpDIB))
  1731.     return;
  1732.  
  1733.   SetCursor (LoadCursor (NULL, IDC_WAIT));
  1734.   pDevNames = (LPDEVNAMES)GlobalLock (pPrintDlgStruct->hDevNames);
  1735.   pDevMode = (LPDEVMODE)GlobalLock (pPrintDlgStruct->hDevMode);
  1736.   pDevMode->dmCopies = uPrintCopies;
  1737.   hDC = CreateDC ((LPCSTR)pDevNames + pDevNames->wDriverOffset, (LPCSTR)pDevNames + pDevNames->wDeviceOffset,
  1738.                   (LPCSTR)pDevNames + pDevNames->wOutputOffset, pDevMode);
  1739.  
  1740.   if (bHalftoneImgLib)
  1741.   {
  1742.     lpDIBPrint = HalftoneDIB (lpDIB);
  1743.     pBih = (LPBITMAPINFOHEADER) lpDIBPrint;
  1744.   }
  1745.   else
  1746.   {
  1747.     pBih = (LPBITMAPINFOHEADER) lpDIB;
  1748.   }
  1749.   iXMargin = GetDeviceCaps (hDC, HORZRES) / 20;
  1750.   iYMargin = GetDeviceCaps (hDC, VERTRES) / 20;
  1751.  
  1752.   if (bFillPage)
  1753.   {
  1754.     iWidth = GetDeviceCaps (hDC, HORZRES) - iXMargin * 2;
  1755.     iHeight = GetDeviceCaps (hDC, VERTRES) - iYMargin * 2;
  1756.  
  1757.     if (iWidth / pBih->biWidth > iHeight / pBih->biHeight)
  1758.       iWidth = (int)pBih->biWidth * iHeight / (int)pBih->biHeight;
  1759.     else
  1760.       iHeight = (int)pBih->biHeight * iWidth / (int)pBih->biWidth;
  1761.   }
  1762.   else
  1763.   {
  1764.     iWidth = (int)pBih->biWidth;
  1765.     iHeight = (int)pBih->biHeight;
  1766.  
  1767.     /*
  1768.      * ImgLib halftonning increases the image size 4 times.  To make the
  1769.      * output look the same size, size the output the same for GDI.
  1770.      */
  1771.     if (!bHalftoneImgLib)
  1772.     {
  1773.       iWidth *= 4;
  1774.       iHeight *= 4;
  1775.     }
  1776.   }
  1777.   pBmi = (LPBITMAPINFO)pBih;
  1778.   GetWindowText (hwndMain, szTitle, sizeof (szTitle));
  1779.   DocInfo.cbSize = sizeof (DocInfo);
  1780.   DocInfo.lpszDocName = szTitle;
  1781.   DocInfo.lpszOutput = NULL;
  1782.   StartDoc (hDC, &DocInfo);
  1783.   StartPage (hDC);
  1784.   StretchDIBits (hDC, iXMargin, iYMargin, iWidth, iHeight, 0, 0, (int)pBih->biWidth,
  1785.                                  (int)pBih->biHeight, (HPSTR)&pBmi->bmiColors[pBih->biClrUsed], pBmi,
  1786.                                  DIB_RGB_COLORS, SRCCOPY);
  1787.   EndPage (hDC);
  1788.   EndDoc (hDC);
  1789.   DeleteDC (hDC);
  1790.  
  1791.   if (lpDIBPrint)
  1792.     DIBFree (lpDIBPrint);
  1793.  
  1794.   GlobalUnlock (pPrintDlgStruct->hDevNames);
  1795.   GlobalUnlock (pPrintDlgStruct->hDevMode);
  1796.   SetCursor (LoadCursor (NULL, IDC_ARROW));
  1797. }
  1798.  
  1799. /*************************************************************************
  1800.   Function:  InitializePrintStruct ()
  1801.    Purpose:  Initialize the printing structure with default printer information.
  1802.    Returns:  none
  1803. *************************************************************************/
  1804.  
  1805. static void InitializePrintStruct (void)
  1806. {
  1807.   if (pPrintDlgStruct)
  1808.     freemem (pPrintDlgStruct);
  1809.  
  1810.   pPrintDlgStruct = (LPPRINTDLG)allocmem (sizeof (PRINTDLG));
  1811.  
  1812.   if (pPrintDlgStruct)
  1813.   {
  1814. #ifdef WIN32
  1815.     memset (pPrintDlgStruct, 0, sizeof (PRINTDLG));
  1816. #else
  1817.     _fmemset (pPrintDlgStruct, 0, sizeof (PRINTDLG));
  1818. #endif
  1819.     pPrintDlgStruct->lStructSize = sizeof (PRINTDLG);
  1820.     pPrintDlgStruct->hwndOwner = hwndMain;
  1821.     pPrintDlgStruct->Flags = PD_PRINTSETUP | PD_RETURNDEFAULT;
  1822.  
  1823.     if (PrintDlg (pPrintDlgStruct) == FALSE)
  1824.     {
  1825.       freemem (pPrintDlgStruct);
  1826.       pPrintDlgStruct = NULL;
  1827.       MessageBox (hwndMain, "Error getting the default printer information", WINDOW_NAME, MB_OK | MB_ICONSTOP);
  1828.       return;
  1829.     }
  1830.   }
  1831. }
  1832.  
  1833. /*************************************************************************
  1834.   Function:  HandleMenuPopup ()
  1835.    Purpose:  Prepare a menu for display based on the current application state
  1836.    Returns:  none
  1837. *************************************************************************/
  1838.  
  1839. static void HandleMenuPopup (WPARAM wParam, LPARAM lParam)
  1840. {
  1841. HMENU             hMenuParent, hMenuPopup;
  1842. UINT              uIndex;
  1843. BOOL              bSystemMenu;
  1844. HDC               hDC;
  1845. LPBITMAPINFOHEADER pBmi;
  1846.  
  1847.   bSystemMenu = HIWORD (lParam);
  1848.  
  1849.   if (bSystemMenu)
  1850.     return;
  1851.  
  1852.   hMenuParent = GetMenu (hwndMain);
  1853.   hMenuPopup = (HMENU)wParam;
  1854.   uIndex = LOWORD (lParam);
  1855.  
  1856.   if (hMenuPopup == GetSubMenu (hMenuParent, 0))
  1857.   {
  1858.     if (lpDIBDisplay)
  1859.     {
  1860.       EnableMenuItem (hMenuPopup, ID_FILE_SAVE, MF_BYCOMMAND | MF_ENABLED);
  1861.       EnableMenuItem (hMenuPopup, ID_FILE_PRINT, MF_BYCOMMAND | MF_ENABLED);
  1862.     }
  1863.     else
  1864.     {
  1865.       EnableMenuItem (hMenuPopup, ID_FILE_SAVE, MF_BYCOMMAND | MF_GRAYED);
  1866.       EnableMenuItem (hMenuPopup, ID_FILE_PRINT, MF_BYCOMMAND | MF_GRAYED);
  1867.     }
  1868.   }
  1869.   else if (hMenuPopup == GetSubMenu (hMenuParent, 1))
  1870.   {
  1871.     if (lpDIB1 && lpDIB2)
  1872.       EnableMenuItem (hMenuPopup, ID_EDIT_UNDO, MF_BYCOMMAND | MF_ENABLED);
  1873.     else
  1874.       EnableMenuItem (hMenuPopup, ID_EDIT_UNDO, MF_BYCOMMAND | MF_GRAYED);
  1875.  
  1876.     if (lpDIB1)
  1877.       EnableMenuItem (hMenuPopup, ID_EDIT_COPY, MF_BYCOMMAND | MF_ENABLED);
  1878.     else
  1879.       EnableMenuItem (hMenuPopup, ID_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
  1880.  
  1881.     if (IsClipboardFormatAvailable (CF_BITMAP) || IsClipboardFormatAvailable (CF_DIB))
  1882.       EnableMenuItem (hMenuPopup, ID_EDIT_PASTE, MF_BYCOMMAND | MF_ENABLED);
  1883.     else
  1884.       EnableMenuItem (hMenuPopup, ID_EDIT_PASTE, MF_BYCOMMAND | MF_GRAYED);
  1885.  
  1886.     if (bDrawSelection)
  1887.       EnableMenuItem (hMenuPopup, ID_EDIT_ZOOM, MF_BYCOMMAND | MF_ENABLED);
  1888.     else
  1889.       EnableMenuItem (hMenuPopup, ID_EDIT_ZOOM, MF_BYCOMMAND | MF_GRAYED);
  1890.   }
  1891.   else if (hMenuPopup == GetSubMenu (hMenuParent, 2))
  1892.   {
  1893.     if (lpDIB1)
  1894.     {
  1895.       pBmi = (LPBITMAPINFOHEADER) lpDIBDisplay;
  1896.       
  1897.       /*
  1898.        * Disallow controlling brightness of monochrome bitmaps
  1899.        */
  1900.       if (pBmi->biPlanes * pBmi->biBitCount > 1)
  1901.         EnableMenuItem (hMenuPopup, ID_PROCESS_BRIGHTNESS, MF_BYCOMMAND | MF_ENABLED);
  1902.       else
  1903.         EnableMenuItem (hMenuPopup, ID_PROCESS_BRIGHTNESS, MF_BYCOMMAND | MF_GRAYED);
  1904.  
  1905.       EnableMenuItem (hMenuPopup, ID_PROCESS_SMOOTH, MF_BYCOMMAND | MF_ENABLED);
  1906.       EnableMenuItem (hMenuPopup, ID_PROCESS_HALFTONE, MF_BYCOMMAND | MF_ENABLED);
  1907.       EnableMenuItem (hMenuPopup, ID_PROCESS_GRAY, MF_BYCOMMAND | MF_ENABLED);
  1908.  
  1909.       if (pBmi->biPlanes * pBmi->biBitCount <= 8)
  1910.         EnableMenuItem (hMenuPopup, ID_PROCESS_EXPAND, MF_BYCOMMAND | MF_ENABLED);
  1911.       else
  1912.         EnableMenuItem (hMenuPopup, ID_PROCESS_EXPAND, MF_BYCOMMAND | MF_GRAYED);
  1913.  
  1914.       EnableMenuItem (hMenuPopup, MENU_POSITION_ROTATE, MF_BYPOSITION | MF_ENABLED);
  1915.       EnableMenuItem (hMenuPopup, MENU_POSITION_MIRROR, MF_BYPOSITION | MF_ENABLED);
  1916.     }
  1917.     else
  1918.     {
  1919.       EnableMenuItem (hMenuPopup, ID_PROCESS_BRIGHTNESS, MF_BYCOMMAND | MF_GRAYED);
  1920.       EnableMenuItem (hMenuPopup, ID_PROCESS_SMOOTH, MF_BYCOMMAND | MF_GRAYED);
  1921.       EnableMenuItem (hMenuPopup, ID_PROCESS_HALFTONE, MF_BYCOMMAND | MF_GRAYED);
  1922.       EnableMenuItem (hMenuPopup, ID_PROCESS_GRAY, MF_BYCOMMAND | MF_GRAYED);
  1923.       EnableMenuItem (hMenuPopup, ID_PROCESS_EXPAND, MF_BYCOMMAND | MF_GRAYED);
  1924.       EnableMenuItem (hMenuPopup, MENU_POSITION_ROTATE, MF_BYPOSITION | MF_GRAYED);
  1925.       EnableMenuItem (hMenuPopup, MENU_POSITION_MIRROR, MF_BYPOSITION | MF_GRAYED);
  1926.     }
  1927.   }
  1928.   else if (hMenuPopup == GetSubMenu (hMenuParent, 3))
  1929.   {
  1930.     hDC = GetDC (NULL);
  1931.  
  1932.     if (GetDeviceCaps (hDC, BITSPIXEL) > 8)
  1933.       EnableMenuItem (hMenuPopup, MENU_POSITION_TC_OPT, MF_BYPOSITION | MF_GRAYED);
  1934.     else
  1935.       EnableMenuItem (hMenuPopup, MENU_POSITION_TC_OPT, MF_BYPOSITION | MF_ENABLED);
  1936.  
  1937.     ReleaseDC (NULL, hDC);
  1938.   }
  1939. }
  1940.  
  1941. /*************************************************************************
  1942.   Function:  HandleLButtonDown ()
  1943.    Purpose:  Process the WM_LBUTTONDOWN message
  1944.    Returns:  none
  1945. *************************************************************************/
  1946. static void HandleLButtonDown (WPARAM wParam, LPARAM lParam)
  1947. {
  1948.   SetCapture (hwndMain);
  1949.  
  1950.   if (!bPasting)
  1951.   {
  1952.     if (bDrawSelection)
  1953.       EraseSelectionBox ();
  1954.     else
  1955.       bDrawSelection = TRUE;
  1956.  
  1957.     ptAnchor.x = rcSelection.left = rcSelection.right = LOWORD (lParam);
  1958.     ptAnchor.y = rcSelection.top = rcSelection.bottom = HIWORD (lParam);
  1959.     DrawSelectionBox ();
  1960.   }
  1961. }
  1962.  
  1963. /*************************************************************************
  1964.   Function:  HandleLButtonUp ()
  1965.    Purpose:  Process the WM_LBUTTONUP message
  1966.    Returns:  none
  1967. *************************************************************************/
  1968. static void HandleLButtonUp (WPARAM wParam, LPARAM lParam)
  1969. {
  1970. HANDLE            hDIB;
  1971. LPBITMAPINFOHEADER pBih;
  1972. HBITMAP           hBitmap;
  1973. HPALETTE          hPalTemp;
  1974. LPVOID            lpDIBNew, lpDIBTemp;
  1975.  
  1976.   if (bPasting)
  1977.   {
  1978.     if (OpenClipboard (hwndMain))
  1979.     {
  1980.       SetCursor (LoadCursor (NULL, IDC_WAIT));
  1981.  
  1982.       if (IsClipboardFormatAvailable (CF_DIB))
  1983.       {
  1984.         hDIB = GetClipboardData (CF_DIB);
  1985.         pBih = (LPBITMAPINFOHEADER)GlobalLock (hDIB);
  1986.         lpDIBNew = MergeDIB (lpDIB1, pBih, rcSelection.left, rcSelection.top);
  1987.         GlobalUnlock (hDIB);
  1988.       }
  1989.       else if (IsClipboardFormatAvailable (CF_BITMAP))
  1990.       {
  1991.         hBitmap = GetClipboardData (CF_BITMAP);
  1992.         hPalTemp = GetClipboardData (CF_PALETTE);
  1993.         lpDIBTemp = DDBToDIB (hBitmap, hPalTemp);
  1994.  
  1995.         if (lpDIBTemp)
  1996.         {
  1997.           lpDIBNew = MergeDIB (lpDIB1, lpDIBTemp, rcSelection.left, rcSelection.top);
  1998.           DIBFree (lpDIBTemp);
  1999.         }
  2000.       }
  2001.       else
  2002.       {
  2003.         CloseClipboard ();
  2004.         return;
  2005.       }
  2006.       CloseClipboard ();
  2007.       EraseSelectionBox ();
  2008.       bDrawSelection = FALSE;
  2009.       ProcessNewDIB (lpDIBNew);
  2010.       SetCursor (LoadCursor (NULL, IDC_ARROW));
  2011.     }
  2012.     bPasting = FALSE;
  2013.   }
  2014.   else
  2015.   {
  2016.     if (rcSelection.right - rcSelection.left < 5 || rcSelection.bottom - rcSelection.top < 5)
  2017.     {
  2018.       EraseSelectionBox ();
  2019.       bDrawSelection = FALSE;
  2020.     }
  2021.   }
  2022.   ReleaseCapture ();
  2023. }
  2024.  
  2025. /*************************************************************************
  2026.   Function:  HandleRButtonDown ()
  2027.    Purpose:  Process the WM_RBUTTONDOWN message
  2028.    Returns:  none
  2029. *************************************************************************/
  2030. static void HandleRButtonDown (WPARAM wParam, LPARAM lParam)
  2031. {
  2032.   if (GetCapture () == hwndMain)
  2033.   {
  2034.     EraseSelectionBox ();
  2035.     bDrawSelection = FALSE;
  2036.     bPasting = FALSE;
  2037.     ReleaseCapture ();
  2038.   }
  2039. }
  2040.  
  2041. /*************************************************************************
  2042.   Function:  HandleMouseMove ()
  2043.    Purpose:  Process the WM_MOUSEMOVE message
  2044.    Returns:  none
  2045. *************************************************************************/
  2046. static void HandleMouseMove (WPARAM wParam, LPARAM lParam)
  2047. {
  2048. LONG              lX, lY, ldx, ldy;
  2049.  
  2050.   if (GetCapture () == hwndMain)
  2051.   {
  2052.     EraseSelectionBox ();
  2053.     lX = LOWORD (lParam);
  2054.     lY = HIWORD (lParam);
  2055.  
  2056.     if (lX < 0)
  2057.       lX = 0;
  2058.  
  2059.     if (lY < 0)
  2060.       lY = 0;
  2061.     
  2062.     if (bPasting)
  2063.     {
  2064.       ldx = lX - rcSelection.left;
  2065.       ldy = lY - rcSelection.top;
  2066.       OffsetRect (&rcSelection, (int)ldx, (int)ldy);
  2067.     }
  2068.     else
  2069.     {
  2070.       if (lX > ptAnchor.x)
  2071.       {
  2072.         rcSelection.right = (int)lX;
  2073.         rcSelection.left = ptAnchor.x;
  2074.       }
  2075.       else
  2076.       {
  2077.         rcSelection.left = (int)lX;
  2078.         rcSelection.right = ptAnchor.x;
  2079.       }
  2080.  
  2081.       if (lY > ptAnchor.y)
  2082.       {
  2083.         rcSelection.bottom = (int)lY;
  2084.         rcSelection.top = ptAnchor.y;
  2085.       }
  2086.       else
  2087.       {
  2088.         rcSelection.top = (int)lY;
  2089.         rcSelection.bottom = ptAnchor.y;
  2090.       }
  2091.     }
  2092.     DrawSelectionBox ();
  2093.   }
  2094. }
  2095.  
  2096. /*************************************************************************
  2097.   Function:  HandleCharacter ()
  2098.    Purpose:  Process the WM_CHAR message
  2099.    Returns:  none
  2100. *************************************************************************/
  2101. static void HandleCharacter (WPARAM wParam, LPARAM lParam)
  2102. {
  2103.   if (GetCapture () == hwndMain && wParam == VK_ESCAPE)
  2104.   {
  2105.     EraseSelectionBox ();
  2106.     bDrawSelection = FALSE;
  2107.     bPasting = FALSE;
  2108.     ReleaseCapture ();
  2109.   }
  2110. }
  2111.  
  2112. /*************************************************************************
  2113.   Function:  HandlePasting ()
  2114.    Purpose:  Process the clipdoard paste
  2115.    Returns:  none
  2116. *************************************************************************/
  2117. static void HandlePasting (WPARAM wParam, LPARAM lParam)
  2118. {
  2119. HANDLE            hDIB;
  2120. LPBITMAPINFOHEADER pBih;
  2121. long              lWidth, lHeight;
  2122. HBITMAP           hBitmap;
  2123. BITMAP            bm;
  2124. POINT             ptCursor;
  2125. LPVOID            lpDIBNew;
  2126. HPALETTE          hPalTemp;
  2127.  
  2128.   if (OpenClipboard (hwndMain))
  2129.   {
  2130.     if (lpDIB1)
  2131.     {
  2132.       if (IsClipboardFormatAvailable (CF_DIB))
  2133.       {
  2134.         hDIB = GetClipboardData (CF_DIB);
  2135.         pBih = (LPBITMAPINFOHEADER)GlobalLock (hDIB);
  2136.         lWidth = pBih->biWidth;
  2137.         lHeight = pBih->biHeight;
  2138.         GlobalUnlock (hDIB);
  2139.       }
  2140.       else if (IsClipboardFormatAvailable (CF_BITMAP))
  2141.       {
  2142.         hBitmap = GetClipboardData (CF_BITMAP);
  2143.         GetObject (hBitmap, sizeof (bm), &bm);
  2144.         lWidth = bm.bmWidth;
  2145.         lHeight = bm.bmHeight;
  2146.       }
  2147.       else
  2148.       {
  2149.         CloseClipboard ();
  2150.         return;
  2151.       }
  2152.       GetCursorPos (&ptCursor);
  2153.       ScreenToClient (hwndMain, &ptCursor);
  2154.       rcSelection.left = ptCursor.x;
  2155.       rcSelection.top = ptCursor.y;
  2156.       rcSelection.right = ptCursor.x + (int)lWidth;
  2157.       rcSelection.bottom = ptCursor.y + (int)lHeight;
  2158.       bDrawSelection = TRUE;
  2159.       bPasting = TRUE;
  2160.       DrawSelectionBox ();
  2161.       SetCapture (hwndMain);
  2162.     }
  2163.     else
  2164.     {
  2165.       if (IsClipboardFormatAvailable (CF_DIB))
  2166.       {
  2167.         hDIB = GetClipboardData (CF_DIB);
  2168.         pBih = (LPBITMAPINFOHEADER)GlobalLock (hDIB);
  2169.         lpDIBNew = CopyDIB (pBih);
  2170.         GlobalUnlock (hDIB);
  2171.       }
  2172.       else if (IsClipboardFormatAvailable (CF_BITMAP))
  2173.       {
  2174.         hBitmap = GetClipboardData (CF_BITMAP);
  2175.         hPalTemp = GetClipboardData (CF_PALETTE);
  2176.         lpDIBNew = DDBToDIB (hBitmap, hPalTemp);
  2177.       }
  2178.       else
  2179.       {
  2180.         CloseClipboard ();
  2181.         return;
  2182.       }
  2183.       ProcessNewDIB (lpDIBNew);
  2184.     }
  2185.     CloseClipboard ();
  2186.   }
  2187. }
  2188.  
  2189. /*************************************************************************
  2190.   Function:  HandleCopying ()
  2191.    Purpose:  Process the clipdoard copy
  2192.    Returns:  none
  2193. *************************************************************************/
  2194. static void HandleCopying (WPARAM wParam, LPARAM lParam)
  2195. {
  2196. LPVOID            lpDIBTemp, lpDIB;
  2197. DWORD             dwSize;
  2198. HANDLE            hDIB;
  2199.  
  2200.   if (lpDIB1)
  2201.   {
  2202.     if (OpenClipboard (hwndMain))
  2203.     {
  2204.       if (bDrawSelection)
  2205.       {
  2206.         EraseSelectionBox ();
  2207.         bDrawSelection = FALSE;
  2208.         lpDIBTemp = ClipDIB (lpDIB1, rcSelection.left, rcSelection.top, rcSelection.right - rcSelection.left + 1, rcSelection.bottom - rcSelection.top + 1);
  2209.       }
  2210.       else
  2211.         lpDIBTemp = lpDIB1;
  2212.  
  2213.       if (lpDIBTemp)
  2214.       {
  2215.         dwSize = GetDIBSize (lpDIBTemp);
  2216.         hDIB = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, dwSize);
  2217.         lpDIB = GlobalLock (hDIB);
  2218.  
  2219.         if (lpDIB)
  2220.         {
  2221.           copymem (lpDIB, lpDIBTemp, dwSize);
  2222.           GlobalUnlock (hDIB);
  2223.           EmptyClipboard ();
  2224.           SetClipboardData (CF_DIB, hDIB);
  2225.         }
  2226.         
  2227.         if (bDrawSelection)
  2228.           DIBFree (lpDIBTemp);
  2229.       }
  2230.       CloseClipboard ();
  2231.     }
  2232.   }
  2233. }
  2234.  
  2235. /*************************************************************************
  2236.   Function:  HandleZoomin ()
  2237.    Purpose:  Process the zoomin procedure
  2238.    Returns:  none
  2239. *************************************************************************/
  2240. static void HandleZoomin (WPARAM wParam, LPARAM lParam)
  2241. {
  2242. LPVOID            lpDIBTemp, lpDIBNew;
  2243.  
  2244.   if (lpDIB1 && bDrawSelection)
  2245.   {
  2246.     SetCursor (LoadCursor (NULL, IDC_WAIT));
  2247.     EraseSelectionBox ();
  2248.     bDrawSelection = FALSE;
  2249.     lpDIBTemp = ClipDIB (lpDIB1, rcSelection.left, rcSelection.top, rcSelection.right - rcSelection.left + 1, rcSelection.bottom - rcSelection.top + 1);
  2250.  
  2251.     if (lpDIBTemp)
  2252.     {
  2253.       lpDIBNew = ZoomDIB (lpDIBTemp, 500, 500);
  2254.       DIBFree (lpDIBTemp);
  2255.       
  2256.       if (lpDIBNew)
  2257.         ProcessNewDIB (lpDIBNew);
  2258.     }
  2259.     SetCursor (LoadCursor (NULL, IDC_ARROW));
  2260.   }
  2261. }
  2262.  
  2263. /*************************************************************************
  2264.   Function:  DrawSelectionBox ()
  2265.    Purpose:  Draw the selection
  2266.    Returns:  none
  2267. *************************************************************************/
  2268. static void DrawSelectionBox (void)
  2269. {
  2270. HDC               hDC;
  2271.   
  2272.   UpdateWindow (hwndMain);
  2273.   hDC = GetDC (hwndMain);
  2274.  
  2275.   if (hDC)
  2276.   {
  2277.     SetROP2 (hDC, R2_XORPEN);
  2278.     SelectObject (hDC, GetStockObject (WHITE_PEN));
  2279.     SelectObject (hDC, GetStockObject (HOLLOW_BRUSH));
  2280.     Rectangle (hDC, rcSelection.left, rcSelection.top, rcSelection.right, rcSelection.bottom);
  2281.     ReleaseDC (hwndMain, hDC);
  2282.   }
  2283. }
  2284.  
  2285. /*************************************************************************
  2286.   Function:  EraseSelectionBox ()
  2287.    Purpose:  Erase the selection
  2288.    Returns:  none
  2289. *************************************************************************/
  2290. static void EraseSelectionBox (void)
  2291. {
  2292.   if (bDrawSelection)
  2293.     DrawSelectionBox ();
  2294. }
  2295.  
  2296. /*************************************************************************
  2297.   Function:  ProcessNewDIB ()
  2298.    Purpose:  Set up to display a newly loaded/created DIB
  2299.    Returns:  none
  2300. *************************************************************************/
  2301. static void       ProcessNewDIB (LPVOID lpDIBNew)
  2302. {
  2303.   if (lpDIBNew && lpDIBNew != lpDIB1)
  2304.   {
  2305.     if (lpDIBDisplay && lpDIBDisplay != lpDIB1)
  2306.       DIBFree (lpDIBDisplay);
  2307.  
  2308.     if (lpDIB2)
  2309.       DIBFree (lpDIB2);
  2310.  
  2311.     lpDIB2 = lpDIB1;
  2312.     lpDIB1 = lpDIBNew;
  2313.  
  2314.     if (hPalette)
  2315.     {
  2316.       DeleteObject (hPalette);
  2317.       hPalette = NULL;
  2318.     }
  2319.     lpDIBDisplay = CreateDisplayDIB (hwndMain, &lpDIB1, &hPalette);
  2320.  
  2321.     if (lpDIBDisplay)
  2322.       ResizeWindowToDIB (hwndMain, lpDIBDisplay);
  2323.   }
  2324. }
  2325.  
  2326. /*************************************************************************
  2327.   Function:  HandlePaintingAndUpdates ()
  2328.    Purpose:  Process image painting and palette management
  2329.    Returns:  none
  2330. *************************************************************************/
  2331. static LRESULT HandlePaintingAndUpdates (UINT message, WPARAM wParam, LPARAM lParam)
  2332. {
  2333. RECT              rcClient;
  2334. HPALETTE          hPalOld;
  2335. HDC               hDC;
  2336. int               iCount, iXPos, iYPos, iYStart;
  2337. PAINTSTRUCT       PaintStruct;
  2338. HPSTR             hpBits;
  2339. LPBITMAPINFO      pBitmapInfo;
  2340.  
  2341.   switch (message)
  2342.   {
  2343.     case WM_QUERYNEWPALETTE:
  2344.  
  2345.     /*
  2346.      * If palette realization causes a palette change,
  2347.      * we need to do a full redraw.
  2348.      */
  2349.     if (hPalette && wParam != (UINT)hwndMain)
  2350.     {
  2351.       hDC = GetDC (hwndMain);
  2352.       hPalOld = SelectPalette (hDC, hPalette, FALSE);
  2353.       iCount = RealizePalette (hDC);
  2354.       InvalidateRect (hwndMain, (LPRECT) (NULL), FALSE);
  2355.       UpdateWindow (hwndMain);
  2356.       SelectPalette (hDC, hPalOld, 0);
  2357.       ReleaseDC (hwndMain, hDC);
  2358.       return TRUE;
  2359.     }
  2360.     break;
  2361.  
  2362.     case WM_PALETTECHANGED:
  2363.  
  2364.       if (hPalette && wParam != (UINT)hwndMain)
  2365.         InvalidateRect (hwndMain, (LPRECT) (NULL), FALSE);
  2366.  
  2367.       break;
  2368.  
  2369.     case WM_PAINT:
  2370.       
  2371.       hDC = BeginPaint (hwndMain, &PaintStruct);
  2372.  
  2373.       if (lpDIBDisplay)
  2374.       {
  2375.         if (hPalette)
  2376.         {
  2377.           hPalOld = SelectPalette (hDC, hPalette, FALSE);
  2378.           RealizePalette (hDC);
  2379.         }
  2380.  
  2381.         GetClientRect (hwndMain, &rcClient);
  2382.         iXPos = GetScrollPos (hwndMain, SB_HORZ);
  2383.         iYPos = GetScrollPos (hwndMain, SB_VERT);
  2384.         pBitmapInfo = (LPBITMAPINFO) lpDIBDisplay;
  2385. #ifdef USE_WING
  2386.         if (hWinGInst && hbmpWinG)
  2387.         {
  2388.           fpWinGStretchBlt (hDC, 0, 0, rcClient.right, rcClient.bottom, hdcWinG, iXPos, iYPos,
  2389.                             rcClient.right, rcClient.bottom);
  2390.         }
  2391.         else
  2392. #endif
  2393.         {
  2394.           iYStart = (int)pBitmapInfo->bmiHeader.biHeight - rcClient.bottom - iYPos;
  2395.           hpBits = (HPSTR)&pBitmapInfo->bmiColors[pBitmapInfo->bmiHeader.biClrUsed];
  2396.           StretchDIBits (hDC, 0, 0, rcClient.right, rcClient.bottom, iXPos, iYStart,
  2397.                          rcClient.right, rcClient.bottom, hpBits, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  2398.         }
  2399.         if (hPalette)
  2400.           SelectPalette (hDC, hPalOld, FALSE);
  2401.       }
  2402.  
  2403.       if (bDrawSelection)
  2404.         DrawSelectionBox ();
  2405.  
  2406.       EndPaint (hwndMain, &PaintStruct);
  2407.       break;
  2408.   }
  2409.   return (0);
  2410. }
  2411.  
  2412. #ifdef USE_WING
  2413.  
  2414. /*************************************************************************
  2415.   Function:  InitializeWinG ()
  2416.    Purpose:  Initializes WinG
  2417.    Returns:  none
  2418. *************************************************************************/
  2419. static void InitializeWinG ()
  2420. {
  2421.   fpWinGCreateDC = (WINGCREATEDC) GetProcAddress (hWinGInst, "WinGCreateDC");
  2422.   fpWinGCreateBitmap = (WINGCREATEBITMAP) GetProcAddress (hWinGInst, "WinGCreateBitmap");
  2423.   fpWinGStretchBlt = (WINGSTRETCHBLT) GetProcAddress (hWinGInst, "WinGStretchBlt");
  2424.   hdcWinG = fpWinGCreateDC ();
  2425. }
  2426.  
  2427. /*************************************************************************
  2428.   Function:  UpdateWinGBitmap ()
  2429.    Purpose:  Updates WinG bitmap used to draw DIBs
  2430.    Returns:  none
  2431. *************************************************************************/
  2432. static void UpdateWinGBitmap (LPVOID lpDIB)
  2433. {
  2434. LPBITMAPINFO      pBiDIB = (LPBITMAPINFO) lpDIB;
  2435. HPALETTE          hpalTemp, hpalOld;
  2436. HPSTR             hpBits;
  2437.  
  2438.   if (hbmpWinG)
  2439.   {
  2440.     SelectObject (hdcWinG, hbmpWinGOld);
  2441.     DeleteObject (hbmpWinG);
  2442.   }
  2443.  
  2444.   /*
  2445.    * Create a new bitmap and put it in WinG DC for quick repaints.  WinG
  2446.    * deals with 8-bit-per-pixel bitmaps only.
  2447.    */
  2448.   hbmpWinG = fpWinGCreateBitmap (hdcWinG, pBiDIB, NULL);
  2449.   
  2450.   if (hbmpWinG)
  2451.   {
  2452.     hbmpWinGOld = SelectObject (hdcWinG, hbmpWinG);
  2453.     hpalTemp = CreateDIBPalette (lpDIB);
  2454.     hpalOld = SelectPalette (hdcWinG, hpalTemp, FALSE);
  2455.     RealizePalette (hdcWinG);
  2456.     hpBits = (HPSTR)&pBiDIB->bmiColors[pBiDIB->bmiHeader.biClrUsed];
  2457.     StretchDIBits (hdcWinG, 0, 0, (int)pBiDIB->bmiHeader.biWidth, (int)pBiDIB->bmiHeader.biHeight, 0, 0,
  2458.                    (int)pBiDIB->bmiHeader.biWidth, (int)pBiDIB->bmiHeader.biHeight, hpBits, pBiDIB, DIB_RGB_COLORS, SRCCOPY);
  2459.     SelectPalette (hdcWinG, hpalOld, FALSE);
  2460.     DeleteObject (hpalTemp);
  2461.   }
  2462. }
  2463.  
  2464. #endif
  2465.