COPY.C

//********************************************************************** 
//
// copy.c
//
// Source file for Device-Independent Bitmap (DIB) API. Provides
// the following functions:
//
// CopyWindowToDIB() - Copies a window to a DIB
// CopyScreenToDIB() - Copies entire screen to a DIB
// CopyWindowToBitmap()- Copies a window to a standard Bitmap
// CopyScreenToBitmap()- Copies entire screen to a standard Bitmap
// PaintDIB() - Displays DIB in the specified DC
// PaintBitmap() - Displays bitmap in the specified DC
//
// The following functions are called from DIBUTIL.C:
//
// DIBToBitmap() - Creates a bitmap from a DIB
// BitmapToDIB() - Creates a DIB from a bitmap
// DIBWidth() - Gets the width of the DIB
// DIBHeight() - Gets the height of the DIB
// CreateDIBPalette() - Gets the DIB's palette
// GetSystemPalette() - Gets the current palette
//
// Written by Microsoft Product Support Services, Developer Support.
// Copyright 1991-1998 Microsoft Corporation. All rights reserved.
//**********************************************************************

#define STRICT // enable strict type checking

#include <WINDOWS.H>
#include "DIBUTIL.H"
#include "DIBAPI.H"

/*************************************************************************
*
* CopyWindowToDIB()
*
* Parameters:
*
* HWND hWnd - specifies the window
*
* WORD fPrintArea - specifies the window area to copy into the device-
* independent bitmap
*
* Return Value:
*
* HDIB - identifies the device-independent bitmap
*
* Description:
*
* This function copies the specified part(s) of the window to a device-
* independent bitmap.
*
************************************************************************/


HDIB CopyWindowToDIB(HWND hWnd, WORD fPrintArea)
{
HDIB hDIB = NULL; // handle to DIB

// check for a valid window handle

if (!hWnd)
return NULL;

switch (fPrintArea)
{
case PW_WINDOW: // copy entire window
{
RECT rectWnd;

// get the window rectangle

GetWindowRect(hWnd, &rectWnd);

// get the DIB of the window by calling
// CopyScreenToDIB and passing it the window rect

hDIB = CopyScreenToDIB(&rectWnd);
break;
}

case PW_CLIENT: // copy client area
{
RECT rectClient;
POINT pt1, pt2;

// get the client area dimensions

GetClientRect(hWnd, &rectClient);

// convert client coords to screen coords

pt1.x = rectClient.left;
pt1.y = rectClient.top;
pt2.x = rectClient.right;
pt2.y = rectClient.bottom;
ClientToScreen(hWnd, &pt1);
ClientToScreen(hWnd, &pt2);
rectClient.left = pt1.x;
rectClient.top = pt1.y;
rectClient.right = pt2.x;
rectClient.bottom = pt2.y;

// get the DIB of the client area by calling
// CopyScreenToDIB and passing it the client rect

hDIB = CopyScreenToDIB(&rectClient);
break;
}

default: // invalid print area
return NULL;
}

// return the handle to the DIB

return hDIB;
}


/*************************************************************************
*
* CopyScreenToDIB()
*
* Parameter:
*
* LPRECT lpRect - specifies the window
*
* Return Value:
*
* HDIB - identifies the device-independent bitmap
*
* Description:
*
* This function copies the specified part of the screen to a device-
* independent bitmap.
*
************************************************************************/

HDIB CopyScreenToDIB(LPRECT lpRect)
{
HBITMAP hBitmap; // handle to device-dependent bitmap
HPALETTE hPalette; // handle to palette
HDIB hDIB = NULL; // handle to DIB

// get the device-dependent bitmap in lpRect by calling
// CopyScreenToBitmap and passing it the rectangle to grab

hBitmap = CopyScreenToBitmap(lpRect);

// check for a valid bitmap handle

if (!hBitmap)
return NULL;

// get the current palette

hPalette = GetSystemPalette();

// convert the bitmap to a DIB

hDIB = BitmapToDIB(hBitmap, hPalette);

// clean up

DeleteObject(hPalette);
DeleteObject(hBitmap);

// return handle to the packed-DIB
return hDIB;
}


/*************************************************************************
*
* CopyWindowToBitmap()
*
* Parameters:
*
* HWND hWnd - specifies the window
*
* WORD fPrintArea - specifies the window area to copy into the device-
* dependent bitmap
*
* Return Value:
*
* HDIB - identifies the device-dependent bitmap
*
* Description:
*
* This function copies the specified part(s) of the window to a device-
* dependent bitmap.
*
*
************************************************************************/

HBITMAP CopyWindowToBitmap(HWND hWnd, WORD fPrintArea)
{
HBITMAP hBitmap = NULL; // handle to device-dependent bitmap

// check for a valid window handle

if (!hWnd)
return NULL;

switch (fPrintArea)
{
case PW_WINDOW: // copy entire window
{
RECT rectWnd;

// get the window rectangle

GetWindowRect(hWnd, &rectWnd);

// get the bitmap of that window by calling
// CopyScreenToBitmap and passing it the window rect

hBitmap = CopyScreenToBitmap(&rectWnd);
break;
}


case PW_CLIENT: // copy client area
{
RECT rectClient;
POINT pt1, pt2;

// get client dimensions

GetClientRect(hWnd, &rectClient);

// convert client coords to screen coords

pt1.x = rectClient.left;
pt1.y = rectClient.top;
pt2.x = rectClient.right;
pt2.y = rectClient.bottom;
ClientToScreen(hWnd, &pt1);
ClientToScreen(hWnd, &pt2);
rectClient.left = pt1.x;
rectClient.top = pt1.y;
rectClient.right = pt2.x;
rectClient.bottom = pt2.y;

// get the bitmap of the client area by calling
// CopyScreenToBitmap and passing it the client rect

hBitmap = CopyScreenToBitmap(&rectClient);
break;
}

default: // invalid print area
return NULL;
}

// return handle to the bitmap

return hBitmap;
}


/*************************************************************************
*
* CopyScreenToBitmap()
*
* Parameter:
*
* LPRECT lpRect - specifies the window
*
* Return Value:
*
* HDIB - identifies the device-dependent bitmap
*
* Description:
*
* This function copies the specified part of the screen to a device-
* dependent bitmap.
*
*
************************************************************************/

HBITMAP CopyScreenToBitmap(LPRECT lpRect)
{
HDC hScrDC, hMemDC; // screen DC and memory DC
HBITMAP hBitmap, hOldBitmap; // handles to deice-dependent bitmaps
int nX, nY, nX2, nY2; // coordinates of rectangle to grab
int nWidth, nHeight; // DIB width and height
int xScrn, yScrn; // screen resolution

// check for an empty rectangle

if (IsRectEmpty(lpRect))
return NULL;

// create a DC for the screen and create
// a memory DC compatible to screen DC

hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
hMemDC = CreateCompatibleDC(hScrDC);

// get points of rectangle to grab

nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;

// get screen resolution

xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);

//make sure bitmap rectangle is visible

if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScrn)
nX2 = xScrn;
if (nY2 > yScrn)
nY2 = yScrn;

nWidth = nX2 - nX;
nHeight = nY2 - nY;

// create a bitmap compatible with the screen DC
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);

// select new bitmap into memory DC
hOldBitmap = SelectObject(hMemDC, hBitmap);

// bitblt screen DC to memory DC
BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);

// select old bitmap back into memory DC and get handle to
// bitmap of the screen

hBitmap = SelectObject(hMemDC, hOldBitmap);

// clean up

DeleteDC(hScrDC);
DeleteDC(hMemDC);

// return handle to the bitmap

return hBitmap;
}


/*************************************************************************
*
* PaintDIB()
*
* Parameters:
*
* HDC hDC - DC to do output to
*
* LPRECT lpDCRect - rectangle on DC to do output to
*
* HDIB hDIB - handle to global memory with a DIB spec
* in it followed by the DIB bits
*
* LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
*
* Return Value:
*
* BOOL - TRUE if DIB was drawn, FALSE otherwise
*
* Description:
* Painting routine for a DIB. Calls StretchDIBits() or
* SetDIBitsToDevice() to paint the DIB. The DIB is
* output to the specified DC, at the coordinates given
* in lpDCRect. The area of the DIB to be output is
* given by lpDIBRect.
*
* NOTE: This function always selects the palette as background. Before
* calling this function, be sure your palette is selected to desired
* priority (foreground or background).
*
*
************************************************************************/

BOOL PaintDIB(HDC hDC, LPRECT lpDCRect, HDIB hDIB, LPRECT lpDIBRect,
HPALETTE hPal)
{
LPSTR lpDIBHdr; // Pointer to BITMAPINFOHEADER
LPSTR lpDIBBits; // Pointer to DIB bits
BOOL bSuccess=FALSE; // Success/fail flag
HPALETTE hOldPal=NULL; // Previous palette

// Check for valid DIB handle

if (!hDIB)
return FALSE;

// Lock down the DIB, and get a pointer to the beginning of the bit
// buffer

lpDIBHdr = GlobalLock(hDIB);
lpDIBBits = FindDIBBits(lpDIBHdr);

// Select and realize our palette as background

if (hPal)
{
hOldPal = SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
}

// Make sure to use the stretching mode best for color pictures

SetStretchBltMode(hDC, COLORONCOLOR);

// Determine whether to call StretchDIBits() or SetDIBitsToDevice()

if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
{
bSuccess = SetDIBitsToDevice(hDC, lpDCRect->left, lpDCRect->top,
RECTWIDTH(lpDCRect), RECTHEIGHT(lpDCRect), lpDIBRect->left,
(int)DIBHeight(lpDIBHdr) - lpDIBRect->top -
RECTHEIGHT(lpDIBRect), 0, DIBHeight(lpDIBHdr), lpDIBBits,
(LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS);
}
else
bSuccess = StretchDIBits(hDC, lpDCRect->left, lpDCRect->top,
RECTWIDTH(lpDCRect), RECTHEIGHT(lpDCRect), lpDIBRect->left,
lpDIBRect->top, RECTWIDTH(lpDIBRect), RECTHEIGHT(lpDIBRect),
lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS, SRCCOPY);

// Unlock the memory block

GlobalUnlock(hDIB);

// Reselect old palette

if (hOldPal)
SelectPalette(hDC, hOldPal, FALSE);

// Return with success/fail flag
return bSuccess;
}


/*************************************************************************
*
* PaintBitmap()
*
* Parameters:
*
* HDC hDC - DC to do output to
*
* LPRECT lpDCRect - rectangle on DC to do output to
*
* HBITMAP hDDB - handle to device-dependent bitmap (DDB)
*
* LPRECT lpDDBRect - rectangle of DDB to output into lpDCRect
*
* HPALETTE hPalette - handle to the palette to use with hDDB
*
* Return Value:
*
* BOOL - TRUE if bitmap was drawn, FLASE otherwise
*
* Description:
*
* Painting routine for a DDB. Calls BitBlt() or
* StretchBlt() to paint the DDB. The DDB is
* output to the specified DC, at the coordinates given
* in lpDCRect. The area of the DDB to be output is
* given by lpDDBRect. The specified palette is used.
*
* NOTE: This function always selects the palette as background. Before
* calling this function, be sure your palette is selected to desired
* priority (foreground or background).
*
************************************************************************/

BOOL PaintBitmap(HDC hDC, LPRECT lpDCRect, HBITMAP hDDB, LPRECT lpDDBRect,
HPALETTE hPal)
{
HDC hMemDC; // Handle to memory DC
HBITMAP hOldBitmap; // Handle to previous bitmap
HPALETTE hOldPal1 = NULL; // Handle to previous palette
HPALETTE hOldPal2 = NULL; // Handle to previous palette
BOOL bSuccess = FALSE; // Success/fail flag

// Create a memory DC

hMemDC = CreateCompatibleDC (hDC);

// If this failed, return FALSE

if (!hMemDC)
return FALSE;

// If we have a palette, select and realize it

if (hPal)
{
hOldPal1 = SelectPalette(hMemDC, hPal, TRUE);
hOldPal2 = SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
}

// Select bitmap into the memory DC

hOldBitmap = SelectObject (hMemDC, hDDB);

// Make sure to use the stretching mode best for color pictures

SetStretchBltMode (hDC, COLORONCOLOR);

// Determine whether to call StretchBlt() or BitBlt()
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDDBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDDBRect)))
bSuccess = BitBlt(hDC, lpDCRect->left, lpDCRect->top,
lpDCRect->right - lpDCRect->left,
lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left,
lpDDBRect->top, SRCCOPY);
else
bSuccess = StretchBlt(hDC, lpDCRect->left, lpDCRect->top,
lpDCRect->right - lpDCRect->left,
lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left,
lpDDBRect->top, lpDDBRect->right - lpDDBRect->left,
lpDDBRect->bottom - lpDDBRect->top, SRCCOPY);

// Clean up

SelectObject(hMemDC, hOldBitmap);

if (hOldPal1)
SelectPalette (hMemDC, hOldPal1, FALSE);

if (hOldPal2)
SelectPalette (hDC, hOldPal2, FALSE);

DeleteDC (hMemDC);

// Return with success/fail flag

return bSuccess;
}