home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 17.ddi / SAMPLES / SHOWDIB / DRAWDIB.C_ / DRAWDIB.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  37.6 KB  |  987 lines

  1. /*******************************************************************************
  2.  *                                                                             *
  3.  *  MODULE      : DrawDIB.c                                                    *
  4.  *                                                                             *
  5.  *  PURPOSE     : Handles most of the SHOWDIB's DIB drawing and clipboard      *
  6.  *                operations.                                                  *
  7.  *                                                                             *
  8.  *  FUNCTIONS   :                                                              *
  9.  *                PrintDIB()             -  Sets the current DIB bits to the   *
  10.  *                                          printer DC.                        *
  11.  *                                                                             *
  12.  *                AppPaint()             -  Sets the DIB/bitmap bits on the    *
  13.  *                                          screen or the given device.        *
  14.  *                                                                             *
  15.  *                DrawSelect()           -  Draws selected clip rectangle on   *
  16.  *                                          the DC/screen.                     *
  17.  *                                                                             *
  18.  *                NormalizeRect()        -  Swaps reversed rectangle coords.   *
  19.  *                                                                             *
  20.  *                TrackMouse()           -  Draws rubberbanding rectangle and  *
  21.  *                                          displays it's dimensions.          *
  22.  *                                                                             *
  23.  *                BandDIB()              -  Outputs DIB in bands to device.    *
  24.  *                                                                             *
  25.  *                SizeWindow()           -  Sizes app. window based on client  *
  26.  *                                          dimensions and style.              *
  27.  *                                                                             *
  28.  *                GetRealClientRect()    -  Calculates client rectangle dimen- *
  29.  *                                          sions if scrollbars are present.   *
  30.  *                                                                             *
  31.  *                SetScrollRanges()      -  Sets global scroll ranges.         *
  32.  *                                                                             *
  33.  *                CopyHandle()           -  Makes a copy of memory block.      *
  34.  *                                                                             *
  35.  *                CopyPalette()          -  Makes a copy of the GDI logical    *
  36.  *                                          palette.                           *
  37.  *                                                                             *
  38.  *                CopyBitmap()           -  Copies given bitmap to another.    *
  39.  *                                                                             *
  40.  *                CropBitmap()           -  Crops a bitmap to the given size.  *
  41.  *                                                                             *
  42.  *                RenderFormat()         -  renders currently displayed DIB    *
  43.  *                                          in CF_BITMAP or CF_DIB format.     *
  44.  *                                                                             *
  45.  *                RealizeDibFormat()     -  Realizes the DIB in given format.  *
  46.  *                                                                             *
  47.  *                ErrMsg()               -  Pops an error message to user.     *
  48.  *                                                                             *
  49.  *                fDialog()              -  Displays a dialog box.             *
  50.  *                                                                             *
  51.  *                AppAbout()             -  Shows the About.. dialog box.      *
  52.  *                                                                             *
  53.  *******************************************************************************/
  54. #include <windows.h>
  55. #include <io.h>
  56. #include <stdio.h>
  57. #include "showdib.h"
  58.  
  59. POINT                 ptSize;       /* Stores DIB dimensions                   */
  60.  
  61. /****************************************************************************
  62.  *                                                                          *
  63.  *  FUNCTION   :  PrintDIB(HWND hWnd, HDC hDC, int x, int y, int dx, int dy)*
  64.  *                                                                          *
  65.  *  PURPOSE    :  Set the DIB bits to the printer DC.                       *
  66.  *                                                                          *
  67.  ****************************************************************************/
  68. void PrintDIB (hWnd, hDC, x, y, dx, dy)
  69. HWND hWnd;
  70. HDC hDC;
  71. int x, y;
  72. int dx, dy;
  73.  
  74. {
  75.     BITMAPINFOHEADER bi;
  76.     int dibX,  dibY;
  77.     int dibDX, dibDY;
  78.  
  79.     if (!bLegitDraw)
  80.         return;
  81.  
  82.     DibInfo (hbiCurrent, &bi);
  83.  
  84.     if (IsRectEmpty (&rcClip)){
  85.         dibX  = 0;
  86.         dibY  = 0;
  87.         dibDX = (int)bi.biWidth;
  88.         dibDY = (int)bi.biHeight;
  89.     }
  90.     else{
  91.         dibX  = rcClip.left;
  92.         dibY  = (int)bi.biHeight - 1 - rcClip.bottom;
  93.         dibDX = rcClip.right  - rcClip.left;
  94.         dibDY = rcClip.bottom - rcClip.top;
  95.     }
  96.  
  97.     if (hdibCurrent){
  98.         /* Stretch the DIB to printer DC */
  99.         StretchDibBlt ( hDC,
  100.                         x,
  101.                         y,
  102.                         dx,
  103.                         dy,
  104.                         hdibCurrent,
  105.                         dibX,
  106.                         dibY,
  107.                         dibDX,
  108.                         dibDY,
  109.                         SRCCOPY);
  110.     }
  111.     else if (achFileName[0]) {
  112.  
  113.         SetMapMode (hDC, MM_ANISOTROPIC);
  114.         SetViewportOrg (hDC, x, y);
  115.         SetViewportExt (hDC, dx, dy);
  116.  
  117.         BandDIB (hWnd, hDC, 0, 0);
  118.     }
  119. }
  120.  
  121. /****************************************************************************
  122.  *                                                                          *
  123.  *  FUNCTION   :  AppPaint(HWND hWnd, HDC hDC, int x, int y)                *
  124.  *                                                                          *
  125.  *  PURPOSE    :  Sets the DIB/bitmap bits on the screen or the given device*
  126.  *                                                                          *
  127.  ****************************************************************************/
  128. void AppPaint (hWnd, hDC, x, y)
  129.  
  130. HWND hWnd;
  131. HDC hDC;
  132. int x, y;
  133. {
  134.     HPALETTE hpalT;
  135.     BITMAPINFOHEADER bi;
  136.  
  137.     SetWindowOrg (hDC, x, y);
  138.     SetBkMode (hDC, wTransparent);
  139.  
  140.     if (bLegitDraw) {
  141.         hpalT = SelectPalette (hDC, hpalCurrent, FALSE);
  142.         RealizePalette (hDC);
  143.  
  144.         if (hbmCurrent && !bDIBToDevice) {
  145.             DrawBitmap (hDC, 0, 0, hbmCurrent, SRCCOPY);
  146.         }
  147.         else if (hdibCurrent) {
  148.             DibInfo (hdibCurrent, &bi);
  149.             DibBlt (hDC,
  150.                     0,
  151.                     0,
  152.                     (int)bi.biWidth,
  153.                     (int)bi.biHeight,
  154.                     hdibCurrent,
  155.                     0,
  156.                     0,
  157.                     SRCCOPY);
  158.         }
  159.         else if (achFileName[0]) {
  160.             BandDIB (hWnd, hDC, 0, 0);
  161.         }
  162.  
  163.         SelectPalette(hDC,hpalT,FALSE);
  164.     }
  165.  
  166.     DrawSelect(hDC, TRUE);
  167. }
  168.  
  169. /****************************************************************************
  170.  *                                                                          *
  171.  *  FUNCTION   :  DrawSelect(HDC hdc, BOOL fDraw)                           *
  172.  *                                                                          *
  173.  *  PURPOSE    :  Draws the selected clip rectangle with its dimensions on  *
  174.  *                the DC/screen                                             *
  175.  *                                                                          *
  176.  ****************************************************************************/
  177. void DrawSelect( hdc, fDraw)
  178.  
  179. HDC hdc;
  180. BOOL fDraw;
  181. {
  182.     char  sz[80];
  183.     DWORD dw;
  184.     int   x,y,len,dx,dy;
  185.     HDC   hdcBits;
  186.     HBITMAP hbm;
  187.  
  188.     if (!IsRectEmpty (&rcClip)) {
  189.  
  190.         /* If a rectangular clip region has been selected, draw it */
  191.         PatBlt(hdc, rcClip.left,    rcClip.top,        rcClip.right-rcClip.left, 1,  DSTINVERT);
  192.         PatBlt(hdc, rcClip.left,    rcClip.bottom, 1, -(rcClip.bottom-rcClip.top),   DSTINVERT);
  193.         PatBlt(hdc, rcClip.right-1, rcClip.top, 1,   rcClip.bottom-rcClip.top,   DSTINVERT);
  194.         PatBlt(hdc, rcClip.right,   rcClip.bottom-1, -(rcClip.right-rcClip.left), 1, DSTINVERT);
  195.  
  196.         /* Format the dimensions string ...*/
  197.         wsprintf( sz,
  198.                   "%dx%d",
  199.                   rcClip.right  - rcClip.left,
  200.                   rcClip.bottom - rcClip.top );
  201.         len = lstrlen(sz);
  202.  
  203.         /* ... and center it in the rectangle */
  204.         dw = GetTextExtent (hdc, sz, len);
  205.         dx = LOWORD (dw);
  206.         dy = HIWORD (dw);
  207.         x  =  (rcClip.right  + rcClip.left - dx) / 2;
  208.         y  =  (rcClip.bottom + rcClip.top  - dy) / 2;
  209.  
  210.         hdcBits = CreateCompatibleDC (hdc);
  211.         SetTextColor (hdcBits, 0xFFFFFFL);
  212.         SetBkColor (hdcBits, 0x000000L);
  213.  
  214.         /* Output the text to the DC */
  215.         if (hbm = CreateBitmap (dx, dy, 1, 1, NULL)){
  216.             hbm = SelectObject (hdcBits, hbm);
  217.             ExtTextOut (hdcBits, 0, 0, 0, NULL, sz, len, NULL);
  218.             BitBlt (hdc, x, y, dx, dy, hdcBits, 0, 0, SRCINVERT);
  219.             hbm = SelectObject (hdcBits, hbm);
  220.             DeleteObject (hbm);
  221.         }
  222.         DeleteDC (hdcBits);
  223.     }
  224. }
  225. /****************************************************************************
  226.  *                                                                          *
  227.  *  FUNCTION   : NormalizeRect(RECT *prc)                                   *
  228.  *                                                                          *
  229.  *  PURPOSE    : If the rectangle coordinates are reversed, swaps them      *
  230.  *                                                                          *
  231.  ****************************************************************************/
  232. void PASCAL NormalizeRect (prc)
  233. RECT *prc;
  234. {
  235.     if (prc->right < prc->left)
  236.         SWAP(prc->right,prc->left);
  237.     if (prc->bottom < prc->top)
  238.         SWAP(prc->bottom,prc->top);
  239. }
  240.  
  241. /****************************************************************************
  242.  *                                                                          *
  243.  *  FUNCTION   : TrackMouse(HWND hwnd, POINT pt)                            *
  244.  *                                                                          *
  245.  *  PURPOSE    : Draws a rubberbanding rectangle and displays it's          *
  246.  *               dimensions till the mouse button is released               *
  247.  *                                                                          *
  248.  ****************************************************************************/
  249. void TrackMouse (hwnd, pt)
  250. HWND hwnd;
  251. POINT pt;
  252. {
  253.     HDC   hdc;
  254.     MSG   msg;
  255.     POINT ptOrigin;
  256.     RECT  rcClient;
  257.  
  258.     hdc = GetDC(hwnd);
  259.     SetCapture(hwnd);
  260.  
  261.     GetClientRect(hwnd,&rcClient);
  262.  
  263.     /* Get mouse coordinates relative to origin of DIB */
  264.     ptOrigin.x = GetScrollPos(hwnd,SB_HORZ);
  265.     ptOrigin.y = GetScrollPos(hwnd,SB_VERT);
  266.  
  267.     pt.x += ptOrigin.x;
  268.     pt.y += ptOrigin.y;
  269.  
  270.     /* Display the coordinates */
  271.     SetWindowOrg(hdc,ptOrigin.x,ptOrigin.y);
  272.     DrawSelect(hdc,FALSE);
  273.  
  274.     /* Initialize clip rectangle to the point */
  275.     rcClip.left   = pt.x;
  276.     rcClip.top    = pt.y;
  277.     rcClip.right  = pt.x;
  278.     rcClip.bottom = pt.y;
  279.  
  280.     /* Eat mouse messages until a WM_LBUTTONUP is encountered. Meanwhile
  281.      * continue to draw a rubberbanding rectangle and display it's dimensions
  282.      */
  283.     for (;;){
  284.     if (GetMessage(&msg,NULL,WM_MOUSEFIRST,WM_MOUSELAST)){
  285.  
  286.         DrawSelect(hdc,FALSE);
  287.  
  288.             rcClip.left   = pt.x;
  289.             rcClip.top    = pt.y;
  290.             rcClip.right  = LOWORD(msg.lParam) + ptOrigin.x;
  291.             rcClip.bottom = HIWORD(msg.lParam) + ptOrigin.y;
  292.  
  293.             NormalizeRect(&rcClip);
  294.             DrawSelect(hdc,TRUE);
  295.  
  296.             if (msg.message == WM_LBUTTONUP)
  297.                 break;
  298.         }
  299.         else
  300.             continue;
  301.     }
  302.  
  303.     ReleaseCapture();
  304.     ReleaseDC(hwnd,hdc);
  305. }
  306.  
  307. /****************************************************************************
  308.  *                                                                          *
  309.  *  FUNCTION   : BandDIB(HWND hWnd, HDC hDC, int x, int y)                  *
  310.  *                                                                          *
  311.  *  PURPOSE    : Outputs the DIB in bands to a device or the screen, using  *
  312.  *               the maximum possible band size.                            *
  313.  *                                                                          *
  314.  ****************************************************************************/
  315. void BandDIB (hWnd, hDC, x, y)
  316. HWND hWnd;
  317. HDC hDC;
  318. int x, y;
  319. {
  320.     HBITMAP            hBitmap, hOld ;
  321.     HDC                hMemDC ;
  322.     LPSTR              pBuf;
  323.     LPBITMAPINFOHEADER lpbi;
  324.     WORD               wRead, wActualPosition, wScansLeft  ;
  325.     DWORD              dwMapSize;
  326.     DWORD              dwScans;
  327.     WORD               wBitmapHeight;
  328.     RECT               Rect;
  329.     HANDLE             hBuf;
  330.     BOOL               bSuccess = FALSE;
  331.     WORD               nBandSize;
  332.     HPALETTE           hOldMemPal;
  333.     HPALETTE           hOldPal;
  334.     int                fh;
  335.     OFSTRUCT           of;
  336.  
  337.     /* Open the map file and get the information out */
  338.     fh = OpenFile (achFileName, (LPOFSTRUCT)&of, OF_READ);
  339.  
  340.     if (fh == -1)
  341.         return;
  342.     lpbi = (VOID FAR *)GlobalLock(hbiCurrent);
  343.     if (!lpbi){
  344.         _lclose (fh);
  345.         return;
  346.     }
  347.  
  348.     /* Compute scan size in bytes */
  349.     dwScans = WIDTHBYTES((DWORD)lpbi->biWidth * lpbi->biBitCount);
  350.  
  351.     wBitmapHeight = (WORD)lpbi->biHeight ;
  352.     wScansLeft    = (WORD)lpbi->biHeight ;
  353.  
  354.     hMemDC = NULL;
  355.     for ( nBandSize = wScansLeft;
  356.           nBandSize >= MINBAND || nBandSize == wScansLeft;
  357.           nBandSize -= BANDINCREMENT) {
  358.  
  359.         /* Attempt to maximize band size by trying to allocate a buffer
  360.          * for the given band size. If allocation fails, try again with the
  361.          * smaller band size.
  362.          */
  363.         hBuf = GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT, dwScans * nBandSize) ;
  364.         if (!hBuf)
  365.             continue;
  366.  
  367.         /* Show success and exit loop if we're going to set bits to device. */
  368.         if (bDIBToDevice) {
  369.             hMemDC = 1;
  370.             break;
  371.         }
  372.         else {
  373.             /* Create a device-dependent bitmap to hold the bits */
  374.             hBitmap = CreateCompatibleBitmap (hDC,
  375.                                               (WORD)lpbi->biWidth,
  376.                                               nBandSize);
  377.             if (!hBitmap) {
  378.                 /* Try again for the next smaller band size */
  379.                 GlobalFree (hBuf);
  380.                 continue;
  381.             }
  382.  
  383.             /* Create a memory context for the bitmap */
  384.             if (!(hMemDC = CreateCompatibleDC (hDC))) {
  385.                 GlobalFree (hBuf);
  386.                 DeleteObject (hBitmap);
  387.                 continue;
  388.             } else
  389.                 /* Success in creating a DC */
  390.                 break;
  391.         }
  392.     }
  393.     if (!hMemDC) {
  394.  
  395.         /* We failed allocation , so give error message and quit */
  396.         if (GetFocus () == hWnd) {
  397.             ErrMsg ("No memory available!");
  398.             ValidateRect (hWnd, (LPRECT) (NULL));
  399.         } else
  400.             MessageBeep(0);
  401.  
  402.         GlobalUnlock(hbiCurrent);
  403.         _lclose (fh);
  404.         return;
  405.     }
  406.     pBuf = GlobalLock (hBuf);
  407.  
  408.     /* Calculate number of bytes to be transferred */
  409.     dwMapSize = dwScans * nBandSize ;
  410.  
  411.     /* Manipulate palette appropriately */
  412.     if (!bDIBToDevice)
  413.         hOldMemPal = SelectPalette (hMemDC, hpalCurrent, 0) ;
  414.  
  415.     /* Now get to the start of the map in the file */
  416.     _llseek(fh, dwOffset, SEEK_SET);
  417.  
  418.     /* we are now all set to start off */
  419.     wActualPosition = wScansLeft ;
  420.  
  421.     Rect.left  = 0;
  422.     Rect.right = (WORD)lpbi->biWidth;
  423.  
  424.     hOldPal = SelectPalette(hDC, hpalCurrent, 0);
  425.     RealizePalette(hDC);
  426.  
  427.     do {
  428.         /* Read in nBandSize scans or whatever is left */
  429.         if (wScansLeft > nBandSize)
  430.             wRead = nBandSize ;
  431.         else
  432.             wRead = wScansLeft ;
  433.  
  434.         Rect.bottom = wActualPosition;
  435.         wActualPosition -= wRead ;
  436.         Rect.top = wActualPosition;
  437.  
  438.         dwMapSize = ((DWORD) wRead) * dwScans ;
  439.  
  440.         /* Now read in the map to the global buffer */
  441.         if (RectVisible (hDC, &Rect)) {
  442.             lread(fh, (LPSTR)pBuf, dwMapSize);
  443.  
  444.             if (bDIBToDevice) {
  445.                 if (wRead != (WORD)SetDIBitsToDevice (hDC, x, y,
  446.                                                 (WORD)lpbi->biWidth,
  447.                                                 wBitmapHeight,
  448.                                                 0,
  449.                                                 0,
  450.                                                 wBitmapHeight - wScansLeft,
  451.                                                 wRead,
  452.                                                 pBuf,
  453.                                                 (LPBITMAPINFO)lpbi,
  454.                                                 fPalColors ?
  455.                                                 DIB_PAL_COLORS :
  456.                                                 DIB_RGB_COLORS)){
  457.                     ErrMsg ("Could not draw DIB scans to device!");
  458.                     GlobalUnlock (hBuf);
  459.                     GlobalFree (hBuf);
  460.                     GlobalUnlock(hbiCurrent);
  461.                     _lclose (fh);
  462.                     return;
  463.                 }
  464.             } else {
  465.                 lpbi->biHeight = wRead ;
  466.  
  467.                 /* Set the DIB bits to a device-dependent format */
  468.                 if ((WORD)lpbi->biHeight != (WORD)SetDIBits (hMemDC,
  469.                                                        hBitmap,
  470.                                                        0,
  471.                                                        (WORD)lpbi->biHeight,
  472.                                                        pBuf,
  473.                                                        (LPBITMAPINFO)lpbi,
  474.                                                        fPalColors ?
  475.                                                        DIB_PAL_COLORS :
  476.                                                        DIB_RGB_COLORS)){
  477.                     ErrMsg ("Could not draw DIB scans!");
  478.                     GlobalUnlock (hBuf);
  479.                     GlobalFree (hBuf);
  480.                     GlobalUnlock(hbiCurrent);
  481.                     _lclose (fh);
  482.                     return;
  483.                 }
  484.  
  485.                 /* Blt own map onto the screen, remembering the point to start */
  486.                 hOld = SelectObject (hMemDC, hBitmap) ;
  487.                 if (!BitBlt (hDC, 0, wActualPosition,
  488.                              (WORD)lpbi->biWidth,
  489.                              (WORD)lpbi->biHeight,
  490.                              hMemDC, 0, 0, SRCCOPY)){
  491.                     ErrMsg ("Could not draw map to screen!");
  492.                     GlobalUnlock (hBuf);
  493.                     GlobalFree (hBuf);
  494.                     GlobalUnlock(hbiCurrent);
  495.                     _lclose (fh);
  496.                     return;
  497.                 }
  498.                 SelectObject (hMemDC, hOld) ;
  499.  
  500.                 /* Restore the value of bitmap height */
  501.                 lpbi->biHeight = wBitmapHeight ;
  502.             }
  503.         }
  504.         else {
  505.             /* This chunk is not visible, seek over the data in the file */
  506.             _llseek(fh, dwMapSize, SEEK_CUR);
  507.         }
  508.         wScansLeft -= wRead ;
  509.     } while (wScansLeft > 0 ) ;
  510.  
  511.     /* Delete the objects just created above */
  512.     GlobalUnlock (hBuf);
  513.     GlobalFree (hBuf);
  514.     SelectPalette (hDC, hOldPal, 0);
  515.  
  516.     /* Set success flag */
  517.     bSuccess = TRUE;
  518.  
  519.     if (!bDIBToDevice) {
  520.         SelectPalette (hMemDC, hOldMemPal, 0);
  521.         DeleteDC (hMemDC) ;
  522.         DeleteObject (hBitmap) ;
  523.     }
  524.     GlobalUnlock(hbiCurrent);
  525.  
  526.     /* Close the file */
  527.     _lclose (fh);
  528. }
  529.  
  530. /****************************************************************************
  531.  *                                                                          *
  532.  *  FUNCTION   : SizeWindow(HWND hWnd)                                      *
  533.  *                                                                          *
  534.  *  PURPOSE    : Sizes the app. window based on client dimensions (DIB      *
  535.  *               dimensions) and style. Sets the caption text.              *
  536.  *                                                                          *
  537.  ****************************************************************************/
  538. void SizeWindow (hWnd)
  539. HWND hWnd;
  540. {
  541.     char  *pstr;
  542.     char  Name[60];
  543.     RECT  Rectangle;
  544.     BITMAPINFOHEADER bi;
  545.  
  546.     /* Get information about current DIB */
  547.     DibInfo(hbiCurrent,&bi);
  548.  
  549.     /* Extract the filename from the full pathname */
  550.     pstr = achFileName + lstrlen(achFileName) - 1;
  551.     while ((*pstr != '\\') && (*pstr != ':') && (pstr >= achFileName))
  552.             pstr--;
  553.     pstr++;
  554.  
  555.     /* Format filename along with the DIB attributes */
  556.     wsprintf (Name,
  557.               "%ls (%ls %dx%dx%d%ls)",
  558.               (LPSTR)szAppName,
  559.               (LPSTR)pstr,
  560.               (WORD)bi.biWidth,
  561.               (WORD)bi.biHeight,
  562.               (WORD)bi.biBitCount,
  563.               bi.biCompression == BI_RGB  ? (LPSTR)" RGB" :
  564.               bi.biCompression == BI_RLE8 ? (LPSTR)" RLE8" : (LPSTR)" RLE4" );
  565.  
  566.     /* Show formatted text in the caption bar */
  567.     SetWindowText (hWnd, Name);
  568.  
  569.     /* Store the size in ptSize, so the scroll bars will work. */
  570.     ptSize.x = (WORD)bi.biWidth;
  571.     ptSize.y = (WORD)bi.biHeight;
  572.  
  573.     if (IsZoomed (hWnd))
  574.         SetScrollRanges (hWnd);
  575.     else {
  576.         Rectangle.left   = 0;
  577.         Rectangle.top    = 0;
  578.         Rectangle.right  = (WORD)bi.biWidth;
  579.         Rectangle.bottom = (WORD)bi.biHeight;
  580.  
  581.         /* Compute the size of the window rectangle based on the given
  582.          * client rectangle size and the window style, then size the
  583.          * window.
  584.          */
  585.         AdjustWindowRect (&Rectangle, dwStyle, TRUE);
  586.         SetWindowPos (hWnd, (HWND)NULL, 0, 0,
  587.                       Rectangle.right  - Rectangle.left + 1,
  588.                       Rectangle.bottom - Rectangle.top + 1,
  589.                       SWP_NOMOVE | SWP_NOZORDER);
  590.     }
  591.  
  592.     InvalidateRect(hWnd,NULL,TRUE);
  593. }
  594.  
  595. /****************************************************************************
  596.  *                                                                          *
  597.  *  FUNCTION   : GetRealClientRect(HWND hwnd, LPRECT lprc)                  *
  598.  *                                                                          *
  599.  *  PURPOSE    : Calculates the client rectangle taking scrollbars into     *
  600.  *               consideration.                                             *
  601.  *                                                                          *
  602.  ****************************************************************************/
  603. void GetRealClientRect (hwnd, lprc)
  604. HWND hwnd;
  605. PRECT lprc;
  606. {
  607.     DWORD dwStyle;
  608.  
  609.     dwStyle = GetWindowLong (hwnd, GWL_STYLE);
  610.     GetClientRect (hwnd,lprc);
  611.  
  612.     if (dwStyle & WS_HSCROLL)
  613.         lprc->bottom += GetSystemMetrics (SM_CYHSCROLL);
  614.  
  615.     if (dwStyle & WS_VSCROLL)
  616.         lprc->right  += GetSystemMetrics (SM_CXVSCROLL);
  617. }
  618.  
  619. /****************************************************************************
  620.  *                                                                          *
  621.  *  FUNCTION   : SetScrollRanges(hwnd)                                      *
  622.  *                                                                          *
  623.  *  PURPOSE    :                                                            *
  624.  *                                                                          *
  625.  ****************************************************************************/
  626. void SetScrollRanges(hwnd)
  627.  
  628. HWND hwnd;
  629. {
  630.     RECT       rc;
  631.     int        iRangeH, iRangeV, i;
  632.     static int iSem = 0;
  633.  
  634.     if (!iSem){
  635.         iSem++;
  636.         GetRealClientRect (hwnd, &rc);
  637.  
  638.         for (i = 0; i < 2; i++){
  639.             iRangeV = ptSize.y - rc.bottom;
  640.             iRangeH = ptSize.x - rc.right;
  641.  
  642.             if (iRangeH < 0) iRangeH = 0;
  643.             if (iRangeV < 0) iRangeV = 0;
  644.  
  645.             if (GetScrollPos ( hwnd,
  646.                                SB_VERT) > iRangeV ||
  647.                                GetScrollPos (hwnd, SB_HORZ) > iRangeH)
  648.                 InvalidateRect (hwnd, NULL, TRUE);
  649.  
  650.             SetScrollRange (hwnd, SB_VERT, 0, iRangeV, TRUE);
  651.             SetScrollRange (hwnd, SB_HORZ, 0, iRangeH, TRUE);
  652.  
  653.             GetClientRect (hwnd, &rc);
  654.         }
  655.         iSem--;
  656.     }
  657. }
  658.  
  659. /*********** THE FOLLOWING FUNCTIONS ARE FOR CLIPBOARD SUPPORT **************/
  660. /****************************************************************************
  661.  *                                                                          *
  662.  *  FUNCTION   : CopyHandle (HANDLE h)                                      *
  663.  *                                                                          *
  664.  *  PURPOSE    : Makes a copy of the given global memory block.             *
  665.  *                                                                          *
  666.  *  RETURNS    : A handle to the new block.                                 *
  667.  *                                                                          *
  668.  ****************************************************************************/
  669. HANDLE CopyHandle (h)
  670. HANDLE h;
  671. {
  672.     BYTE huge *lpCopy;
  673.     BYTE huge *lp;
  674.     HANDLE hCopy;
  675.     DWORD  dwLen;
  676.  
  677.     dwLen = GlobalSize (h);
  678.     if (hCopy = GlobalAlloc (GHND, dwLen)) {
  679.  
  680.         lpCopy = (BYTE huge *)GlobalLock (hCopy);
  681.         lp     = (BYTE huge *)GlobalLock (h);
  682.         while (dwLen--) *lpCopy++ = *lp++;
  683.         GlobalUnlock (hCopy);
  684.         GlobalUnlock (h);
  685.     }
  686.     return hCopy;
  687. }
  688.  
  689. /****************************************************************************
  690.  *                                                                          *
  691.  *  FUNCTION   : CopyPalette(HPALETTE hpal)                                 *
  692.  *                                                                          *
  693.  *  PURPOSE    : Makes a copy of a GDI logical palette                      *
  694.  *                                                                          *
  695.  *  RETURNS    : A handle to the new palette.                               *
  696.  *                                                                          *
  697.  ****************************************************************************/
  698. HPALETTE CopyPalette (hpal)
  699. HPALETTE hpal;
  700. {
  701.     PLOGPALETTE ppal;
  702.     int         nNumEntries;
  703.  
  704.     if (!hpal)
  705.         return NULL;
  706.  
  707.     GetObject(hpal,sizeof(int),(LPSTR)&nNumEntries);
  708.  
  709.     if (nNumEntries == 0)
  710.         return NULL;
  711.  
  712.     ppal = (PLOGPALETTE)LocalAlloc(LPTR,sizeof(LOGPALETTE) +
  713.                 nNumEntries * sizeof(PALETTEENTRY));
  714.  
  715.     if (!ppal)
  716.         return NULL;
  717.  
  718.     ppal->palVersion    = PALVERSION;
  719.     ppal->palNumEntries = nNumEntries;
  720.  
  721.     GetPaletteEntries(hpal,0,nNumEntries,ppal->palPalEntry);
  722.  
  723.     hpal = CreatePalette(ppal);
  724.  
  725.     LocalFree((HANDLE)ppal);
  726.     return hpal;
  727. }
  728. /****************************************************************************
  729.  *                                                                          *
  730.  *  FUNCTION   : CopyBitmap (HBITMAP hbm)                                   *
  731.  *                                                                          *
  732.  *  PURPOSE    : Copies the given bitmap to another.                        *
  733.  *                                                                          *
  734.  *  RETURNS    : A handle to the new bitmap.                                *
  735.  *                                                                          *
  736.  ****************************************************************************/
  737. HBITMAP CopyBitmap (hbm)
  738. HBITMAP hbm;
  739. {
  740.     BITMAP  bm;
  741.     RECT    rc;
  742.  
  743.     if (!hbm)
  744.          return NULL;
  745.  
  746.     GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
  747.     rc.left   = 0;
  748.     rc.top    = 0;
  749.     rc.right  = bm.bmWidth;
  750.     rc.bottom = bm.bmHeight;
  751.  
  752.     return CropBitmap (hbm, &rc);
  753. }
  754. /****************************************************************************
  755.  *                                                                          *
  756.  *  FUNCTION   :  CropBitmap (hbm,lprect)                                   *
  757.  *                                                                          *
  758.  *  PURPOSE    :  Crops a bitmap to a new size specified by the lprect      *
  759.  *                parameter.                                                *
  760.  *                                                                          *
  761.  *  RETURNS    :  A handle to the new bitmap.                               *
  762.  *                                                                          *
  763.  ****************************************************************************/
  764. HBITMAP CropBitmap (hbm, prc)
  765. HBITMAP hbm;
  766. PRECT prc;
  767. {
  768.     HDC     hMemDCsrc;
  769.     HDC     hMemDCdst;
  770.     HDC     hdc;
  771.     HBITMAP hNewBm;
  772.     BITMAP  bm;
  773.     int     dx,dy;
  774.  
  775.     if (!hbm)
  776.          return NULL;
  777.  
  778.     hdc = GetDC (NULL);
  779.     hMemDCsrc = CreateCompatibleDC (hdc);
  780.     hMemDCdst = CreateCompatibleDC (hdc);
  781.  
  782.     GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
  783.     dx = prc->right  - prc->left;
  784.     dy = prc->bottom - prc->top;
  785.  
  786.     hNewBm = CreateBitmap (dx, dy, bm.bmPlanes, bm.bmBitsPixel, NULL);
  787.     if (hNewBm){
  788.         SelectObject (hMemDCsrc, hbm);
  789.         SelectObject (hMemDCdst, hNewBm);
  790.  
  791.         BitBlt (hMemDCdst,
  792.                 0,
  793.                 0,
  794.                 dx,
  795.                 dy,
  796.                 hMemDCsrc,
  797.                 prc->left,
  798.                 prc->top,
  799.                 SRCCOPY);
  800.     }
  801.  
  802.     ReleaseDC (NULL,hdc);
  803.     DeleteDC (hMemDCsrc);
  804.     DeleteDC (hMemDCdst);
  805.     return hNewBm;
  806. }
  807.  
  808. /****************************************************************************
  809.  *                                                                          *
  810.  *  FUNCTION   : RenderFormat(int cf)                                       *
  811.  *                                                                          *
  812.  *  PURPOSE    : Renders the currently displayed DIB in CF_DIB or           *
  813.  *               CF_BITMAP format.The bitmap is clipped to the current      *
  814.  *               rcClip.                                                    *
  815.  *                                                                          *
  816.  *  RETURNS    : A handle to the DIB                                        *
  817.  *                                                                          *
  818.  ****************************************************************************/
  819. HANDLE RenderFormat (cf)
  820. int cf;
  821. {
  822.     HANDLE  h = NULL;
  823.     HBITMAP hbm;
  824.  
  825.     if (!bLegitDraw)
  826.         return NULL;
  827.  
  828.     switch (cf){
  829.         case CF_BITMAP:
  830.             if (hbmCurrent && !IsRectEmpty (&rcClip))
  831.                 h = CropBitmap (hbmCurrent, &rcClip);
  832.             else{
  833.                 if (hbmCurrent)
  834.                     h = CopyBitmap (hbmCurrent);
  835.                 else if (hdibCurrent)
  836.                     h = BitmapFromDib (hdibCurrent, hpalCurrent);
  837.                 else if (achFileName[0] && (hdibCurrent = OpenDIB (achFileName)))
  838.                     h = BitmapFromDib (hdibCurrent, hpalCurrent);
  839.                 else
  840.                     h = NULL;
  841.  
  842.                 if (h && !IsRectEmpty (&rcClip)){
  843.                     hbm = CropBitmap (h,&rcClip);
  844.                     DeleteObject (h);
  845.                     h = hbm;
  846.                 }
  847.             }
  848.             break;
  849.  
  850.         case CF_DIB:
  851.             if (!IsRectEmpty (&rcClip)){
  852.                 if (hbm = RenderFormat (CF_BITMAP)){
  853.                     h = DibFromBitmap (hbm, BI_RGB, 0, hpalCurrent);
  854.                     DeleteObject (hbm);
  855.                 }
  856.             }
  857.             else{
  858.                 if (!hdibCurrent && hbmCurrent)
  859.                     h = DibFromBitmap (hbmCurrent, BI_RGB, 0, hpalCurrent);
  860.                 else if (hdibCurrent)
  861.                     h = CopyHandle (hdibCurrent);
  862.                 else if (achFileName[0])
  863.                     h = OpenDIB (achFileName);
  864.                 else
  865.                     h = NULL;
  866.             }
  867.             break;
  868.  
  869.         case CF_PALETTE:
  870.             if (hpalCurrent)
  871.                 h = CopyPalette (hpalCurrent);
  872.             break;
  873.     }
  874.     return h;
  875. }
  876. /****************************************************************************
  877.  *                                                                          *
  878.  *  FUNCTION   :  RealizeDibFormat(DWORD biStyle, WORD biBits)              *
  879.  *                                                                          *
  880.  *  PURPOSE    :  Realize the current DIB in the specifed format            *
  881.  *                This function is used to get a specific format of CF_DIB  *
  882.  *                                                                          *
  883.  *                    biStyle     DIB format      RGB or RLE                *
  884.  *                    biBits      Bits per pixel  1,4,8,24                  *
  885.  *                                                                          *
  886.  *  RETURNS    :  A handle to the created DIB.                              *
  887.  *                                                                          *
  888.  ****************************************************************************/
  889. HANDLE RealizeDibFormat (biStyle, biBits)
  890. DWORD biStyle;
  891. WORD biBits;
  892. {
  893.     BITMAPINFOHEADER bi;
  894.  
  895.     if (!bLegitDraw)
  896.         return NULL;
  897.  
  898.     DibInfo (hbiCurrent, &bi);
  899.  
  900.     /*  Do we have the requested format already? */
  901.     if (bi.biCompression == biStyle && bi.biBitCount == biBits){
  902.         if (!hdibCurrent)
  903.             hdibCurrent = RenderFormat (CF_DIB);
  904.     }
  905.     else{
  906.         if (!hbmCurrent)
  907.             hbmCurrent = RenderFormat (CF_BITMAP);
  908.  
  909.         if (hbmCurrent){
  910.             if (hdibCurrent)
  911.                 GlobalFree (hdibCurrent);
  912.  
  913.             hdibCurrent = DibFromBitmap (hbmCurrent, biStyle, biBits, hpalCurrent);
  914.         }
  915.     }
  916.  
  917.     return hdibCurrent;
  918. }
  919. /****************************************************************************
  920.  *                                                                          *
  921.  *  FUNCTION   : ErrMsg (PSTR sz,...)                                       *
  922.  *                                                                          *
  923.  *  PURPOSE    : Opens a Message box with a error message in it.The user can*
  924.  *               select the OK button to continue                           *
  925.  *                                                                          *
  926.  *  RETURNS    : FALSE to indicate an error has occured.                    *
  927.  *                                                                          *
  928.  ****************************************************************************/
  929. int ErrMsg (PSTR sz,...)
  930. {
  931.     char ach[128];
  932.  
  933.     wvsprintf (ach, sz, (LPSTR)(&sz+1));   /* Format the string */
  934.     MessageBox (NULL, ach, NULL, MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
  935.     return FALSE;
  936. }
  937.  
  938. /****************************************************************************
  939.  *                                                                          *
  940.  *  FUNCTION   : fDialog(int id,HWND hwnd,FARPROC fpfn)                     *
  941.  *                                                                          *
  942.  *  PURPOSE    : This function displays a dialog box                        *
  943.  *                                                                          *
  944.  *  RETURNS    : The exit code.                                             *
  945.  *                                                                          *
  946.  ****************************************************************************/
  947. BOOL fDialog (id, hwnd, fpfn)
  948. int id;
  949. HWND hwnd;
  950. FARPROC fpfn;
  951. {
  952.     BOOL        f;
  953.     HANDLE      hInst;
  954.  
  955.     hInst = GetWindowWord (hwnd, GWW_HINSTANCE);
  956.     fpfn  = MakeProcInstance (fpfn, hInst);
  957.     f = DialogBox (hInst, MAKEINTRESOURCE(id), hwnd, fpfn);
  958.     FreeProcInstance (fpfn);
  959.     return f;
  960. }
  961.  
  962. /****************************************************************************
  963.  *                                                                          *
  964.  *  FUNCTION   : AppAbout( hDlg, uiMessage, wParam, lParam )                *
  965.  *                                                                          *
  966.  *  PURPOSE    : Dialog function for the About... dialog box                *
  967.  *                                                                          *
  968.  ****************************************************************************/
  969. BOOL FAR PASCAL __export AppAbout( hDlg, uiMessage, wParam, lParam )
  970.  
  971. HWND     hDlg;
  972. unsigned uiMessage;
  973. WORD     wParam;
  974. long     lParam;
  975. {
  976.     switch (uiMessage) {
  977.         case WM_COMMAND:
  978.             if (wParam == IDOK)
  979.                 EndDialog (hDlg, TRUE);
  980.             break;
  981.  
  982.         case WM_INITDIALOG:
  983.             return TRUE;
  984.     }
  985.     return FALSE;
  986. }
  987.