home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / showdib / drawdib.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  40KB  |  1,019 lines

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