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