You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
994 lines
25 KiB
994 lines
25 KiB
/////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
|
|
//
|
|
// Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
|
|
//
|
|
// Other brand and product names used herein are trademarks of their respective owners.
|
|
//
|
|
// The entire program and user interface including the structure, sequence, selection,
|
|
// and arrangement of the dialog, the exclusively "yes" and "no" choices represented
|
|
// by "1" and "2," and each dialog message are protected by copyrights registered in
|
|
// the United States and by international treaties.
|
|
//
|
|
// Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
|
|
// 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
|
|
//
|
|
// Active Voice Corporation
|
|
// Seattle, Washington
|
|
// USA
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////
|
|
// gfx.c - Windows graphics functions
|
|
////
|
|
|
|
#include "winlocal.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "gfx.h"
|
|
#include "mem.h"
|
|
#include "str.h"
|
|
#include "trace.h"
|
|
|
|
////
|
|
// public functions
|
|
////
|
|
|
|
////
|
|
// bitmap routines
|
|
////
|
|
|
|
// GfxBitmapBackfill - replace bitmap's white backg with curr backg color
|
|
// <hBitmap> (i/o) bitmap handle
|
|
// <crBkColor> (i) current background color
|
|
// <wFlags> (i) option flags
|
|
// 0 use default method
|
|
// BF_EXTFLOODFILL use ExtFloodFill function
|
|
// BF_GETSETPIXEL use GetPixel/SetPixel functions
|
|
// NOTE: rarely, ExtFloodFill will GP the display device driver
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI GfxBitmapBackfill(HBITMAP hBitmap, COLORREF crBkColor, WORD wFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
BOOL fExtFloodFill = (BOOL) !(wFlags & BF_GETSETPIXEL);
|
|
BITMAP Bitmap;
|
|
HDC hdc = NULL;
|
|
HDC hdcMem = NULL;
|
|
HBITMAP hBitmapOld = NULL;
|
|
HBRUSH hbr = NULL;
|
|
HBRUSH hbrOld = NULL;
|
|
COLORREF crMaskColor = RGB(255, 255, 255); // RGB_WHITE
|
|
|
|
// need not continue if COLOR_WINDOW is white
|
|
//
|
|
if (crMaskColor == crBkColor)
|
|
return 0;
|
|
|
|
if (hBitmap == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// get width and height of bitmap
|
|
//
|
|
else if (GetObject((HGDIOBJ) hBitmap, sizeof(BITMAP), &Bitmap) == 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// get device context for screen
|
|
//
|
|
else if ((hdc = GetDC(NULL)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// create a memory device context
|
|
//
|
|
else if ((hdcMem = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// select the bitmap into the memory device context
|
|
//
|
|
else if ((hBitmapOld = SelectObject(hdcMem, hBitmap)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// create a brush with specified background color
|
|
//
|
|
else if ((hbr = CreateSolidBrush(crBkColor)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// select the brush into the memory device context
|
|
//
|
|
else if ((hbrOld = SelectObject(hdcMem, hbr)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
int cx = Bitmap.bmWidth;
|
|
int cy = Bitmap.bmHeight;
|
|
|
|
if (fExtFloodFill)
|
|
{
|
|
ExtFloodFill(hdcMem, 0, 0, crMaskColor, FLOODFILLSURFACE);
|
|
ExtFloodFill(hdcMem, cx - 1, 0, crMaskColor, FLOODFILLSURFACE);
|
|
ExtFloodFill(hdcMem, 0, cy - 1, crMaskColor, FLOODFILLSURFACE);
|
|
ExtFloodFill(hdcMem, cx - 1, cy - 1, crMaskColor, FLOODFILLSURFACE);
|
|
}
|
|
else
|
|
{
|
|
int x;
|
|
int y;
|
|
for (x = 0; x < cx; ++x)
|
|
for (y = 0; y < cy; ++y)
|
|
if (GetPixel(hdcMem, x, y) == crMaskColor)
|
|
SetPixel(hdcMem, x, y, crBkColor);
|
|
}
|
|
}
|
|
|
|
// restore old brush, if any
|
|
//
|
|
if (hbrOld != NULL)
|
|
SelectObject(hdcMem, hbrOld);
|
|
|
|
// delete new brush
|
|
//
|
|
if (hbr != NULL && !DeleteObject(hbr))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// restore old bitmap, if any
|
|
//
|
|
if (hBitmapOld != NULL)
|
|
SelectObject(hdcMem, hBitmapOld);
|
|
|
|
// free the memory device context
|
|
//
|
|
if (hdcMem != NULL && !DeleteDC(hdcMem))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// release the common device context
|
|
//
|
|
if (hdc != NULL && !ReleaseDC(NULL, hdc))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// GfxBitmapDisplay - display specified bitmap
|
|
// <hdc> (i) device context for destination window
|
|
// <hBitmap> (i) bitmap handle for source bitmap
|
|
// <x> (i) x coordinate for destination window
|
|
// <y> (i) y coordinate for destination window
|
|
// <fInvert> (i) display bitmap inverted
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI GfxBitmapDisplay(HDC hdc, HBITMAP hBitmap, int x, int y, BOOL fInvert)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
HDC hdcMem = NULL;
|
|
HBITMAP hBitmapOld = NULL;
|
|
BITMAP Bitmap;
|
|
|
|
if (hdc == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (hBitmap == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// get width and height of bitmap
|
|
//
|
|
else if (GetObject((HGDIOBJ) hBitmap, sizeof(BITMAP), &Bitmap) == 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// create a memory device context
|
|
//
|
|
else if ((hdcMem = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// select the bitmap into the memory device context
|
|
//
|
|
else if ((hBitmapOld = SelectObject(hdcMem, hBitmap)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// copy the bitmap from hdcMem to hdc, inverted if necessary
|
|
//
|
|
else if (!BitBlt(hdc, x, y, Bitmap.bmWidth, Bitmap.bmHeight,
|
|
hdcMem, 0, 0, fInvert ? NOTSRCCOPY : SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// restore old bitmap, if any
|
|
//
|
|
if (hBitmapOld != NULL)
|
|
SelectObject(hdcMem, hBitmapOld);
|
|
|
|
// free the memory device context
|
|
//
|
|
if (hdcMem != NULL)
|
|
DeleteDC(hdcMem);
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// GfxBitmapDrawTransparent - draw specified bitmap
|
|
// <hdc> (i) device context for destination window
|
|
// <hBitmap> (i) bitmap handle for source bitmap
|
|
// <x> (i) x coordinate for destination window
|
|
// <y> (i) y coordinate for destination window
|
|
// <crTransparent> (i) transparent color
|
|
// <dwFlags> (i) control flags
|
|
// 0 reserved; must be zero
|
|
// return 0 if success
|
|
//
|
|
#if 1
|
|
int DLLEXPORT WINAPI GfxBitmapDrawTransparent(HDC hdc, HBITMAP hBitmap, int x, int y, COLORREF crTransparent, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
BITMAP bmp;
|
|
int cx;
|
|
int cy;
|
|
HBITMAP hbmpMask = NULL;
|
|
HDC hdcMem = NULL;
|
|
HDC hdcMem2 = NULL;
|
|
HBITMAP hbmpOld;
|
|
HBITMAP hbmpOld2;
|
|
COLORREF crBkOld;
|
|
COLORREF crTextOld;
|
|
|
|
if (GetObject(hBitmap, sizeof(BITMAP), (LPVOID) &bmp) == 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (cx = bmp.bmWidth, cy = bmp.bmHeight, FALSE)
|
|
;
|
|
|
|
else if ((hbmpMask = CreateBitmap(cx, cy, 1, 1, NULL)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hdcMem = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hdcMem2 = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpOld = SelectObject(hdcMem, hBitmap)), FALSE)
|
|
;
|
|
|
|
else if ((hbmpOld2 = SelectObject(hdcMem2, hbmpMask)), FALSE)
|
|
;
|
|
|
|
else if (SetBkColor(hdcMem, crTransparent), FALSE)
|
|
;
|
|
|
|
else if (!BitBlt(hdcMem2, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((crBkOld = SetBkColor(hdc, RGB(255, 255, 255))) == CLR_INVALID)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((crTextOld = SetTextColor(hdc, RGB(0, 0, 0))) == CLR_INVALID)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!BitBlt(hdc, x, y, cx, cy, hdcMem, 0, 0, SRCINVERT))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!BitBlt(hdc, x, y, cx, cy, hdcMem2, 0, 0, SRCAND))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!BitBlt(hdc, x, y, cx, cy, hdcMem, 0, 0, SRCINVERT))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (SetBkColor(hdc, crBkOld) == CLR_INVALID)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (SetTextColor(hdc, crTextOld) == CLR_INVALID)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (SelectObject(hdcMem, hbmpOld), FALSE)
|
|
;
|
|
|
|
else if (SelectObject(hdcMem2, hbmpOld2), FALSE)
|
|
;
|
|
|
|
if (hbmpMask != NULL && !DeleteObject(hbmpMask))
|
|
fSuccess = TraceFALSE(NULL);
|
|
else
|
|
hbmpMask = NULL;
|
|
|
|
if (hdcMem != NULL && !DeleteDC(hdcMem))
|
|
fSuccess = TraceFALSE(NULL);
|
|
else
|
|
hdcMem = NULL;
|
|
|
|
if (hdcMem2 != NULL && !DeleteDC(hdcMem2))
|
|
fSuccess = TraceFALSE(NULL);
|
|
else
|
|
hdcMem2 = NULL;
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
int DLLEXPORT WINAPI GfxBitmapDrawTransparent(HDC hdc, HBITMAP hBitmap, int x, int y, COLORREF crTransparent, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
BITMAP bmp;
|
|
POINT ptSize;
|
|
COLORREF cr;
|
|
HBITMAP hbmpAndBack = NULL;
|
|
HBITMAP hbmpAndObject = NULL;
|
|
HBITMAP hbmpAndMem = NULL;
|
|
HBITMAP hbmpSave = NULL;
|
|
HBITMAP hbmpBackOld = NULL;
|
|
HBITMAP hbmpObjectOld = NULL;
|
|
HBITMAP hbmpMemOld = NULL;
|
|
HBITMAP hbmpSaveOld = NULL;
|
|
HDC hdcTemp = NULL;
|
|
HDC hdcBack = NULL;
|
|
HDC hdcObject = NULL;
|
|
HDC hdcMem = NULL;
|
|
HDC hdcSave = NULL;
|
|
|
|
// Select the bitmap
|
|
//
|
|
if ((hdcTemp = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (SelectObject(hdcTemp, hBitmap), FALSE)
|
|
;
|
|
|
|
// Get dimensions of bitmap
|
|
//
|
|
else if (GetObject(hBitmap, sizeof(BITMAP), (LPVOID) &bmp) == 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (ptSize.x = bmp.bmWidth, ptSize.y = bmp.bmHeight, FALSE)
|
|
;
|
|
|
|
// Convert from device to logical points
|
|
//
|
|
else if (!DPtoLP(hdcTemp, &ptSize, 1))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Create some DCs to hold temporary data.
|
|
//
|
|
else if ((hdcBack = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hdcObject = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hdcMem = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hdcSave = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Create a bitmap for each DC. DCs are required for a number of GDI functions.
|
|
//
|
|
else if ((hbmpAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Each DC must select a bitmap object to store pixel data.
|
|
//
|
|
else if ((hbmpBackOld = SelectObject(hdcBack, hbmpAndBack)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpObjectOld = SelectObject(hdcObject, hbmpAndObject)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpMemOld = SelectObject(hdcMem, hbmpAndMem)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpSaveOld = SelectObject(hdcSave, hbmpSave)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Set proper mapping mode.
|
|
//
|
|
else if (SetMapMode(hdcTemp, GetMapMode(hdc)) == 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Save the bitmap sent here, because it will be overwritten.
|
|
//
|
|
else if (!BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Set the background color of the source DC to the color.
|
|
// contained in the parts of the bitmap that should be transparent
|
|
//
|
|
else if ((cr = SetBkColor(hdcTemp, crTransparent)) == CLR_INVALID)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Create the object mask for the bitmap by performing a BitBlt
|
|
// from the source bitmap to a monochrome bitmap.
|
|
//
|
|
else if (!BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Set the background color of the source DC back to original color.
|
|
//
|
|
else if (SetBkColor(hdcTemp, cr) == CLR_INVALID)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Create the inverse of the object mask.
|
|
//
|
|
else if (!BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Copy the background of the main DC to the destination.
|
|
//
|
|
else if (!BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, x, y, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Mask out the places where the bitmap will be placed.
|
|
//
|
|
else if (!BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Mask out the transparent colored pixels on the bitmap.
|
|
//
|
|
else if (!BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// XOR the bitmap with the background on the destination DC.
|
|
//
|
|
else if (!BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Copy the destination to the screen.
|
|
//
|
|
else if (!BitBlt(hdc, x, y, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Place the original bitmap back into the bitmap sent here.
|
|
//
|
|
else if (!BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// restore old bitmaps
|
|
//
|
|
if (hdcBack != NULL && hbmpBackOld != NULL &&
|
|
SelectObject(hdcBack, hbmpBackOld) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hdcObject != NULL && hbmpObjectOld != NULL &&
|
|
SelectObject(hdcObject, hbmpObjectOld) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hdcMem != NULL && hbmpMemOld != NULL &&
|
|
SelectObject(hdcMem, hbmpMemOld) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hdcSave != NULL && hbmpSaveOld != NULL &&
|
|
SelectObject(hdcSave, hbmpSaveOld) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Delete the memory bitmaps.
|
|
//
|
|
if (hbmpAndBack != NULL && !DeleteObject(hbmpAndBack))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hbmpAndObject != NULL && !DeleteObject(hbmpAndObject))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hbmpAndMem != NULL && !DeleteObject(hbmpAndMem))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hbmpSave != NULL && !DeleteObject(hbmpSave))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// Delete the memory DCs.
|
|
//
|
|
if (hdcBack != NULL && !DeleteDC(hdcBack))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hdcObject != NULL && !DeleteDC(hdcObject))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hdcMem != NULL && !DeleteDC(hdcMem))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hdcSave != NULL && !DeleteDC(hdcSave))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hdcTemp != NULL && !DeleteDC(hdcTemp))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
#endif
|
|
|
|
// GfxBitmapScroll - scroll specified bitmap
|
|
// <hdc> (i) device context for destination window
|
|
// <hBitmap> (i) bitmap handle for source bitmap
|
|
// <dx> (i) amt of horizontal scroll (cx < 0 scrolls left)
|
|
// <dy> (i) amt of vertical scroll (cx < 0 scrolls up)
|
|
// <dwFlags> (i) control flags
|
|
// BS_ROTATE rotate bitmap
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI GfxBitmapScroll(HDC hdc, HBITMAP hBitmap, int dx, int dy, DWORD dwFlags)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
BITMAP bmp;
|
|
POINT ptSize;
|
|
HDC hdcMem = NULL;
|
|
HDC hdcTemp = NULL;
|
|
HBITMAP hbmpTemp = NULL;
|
|
HBITMAP hbmpSave = NULL;
|
|
int dxAbs;
|
|
int dyAbs;
|
|
|
|
// Get dimensions of bitmap
|
|
//
|
|
if (GetObject(hBitmap, sizeof(BITMAP), (LPVOID) &bmp) == 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (ptSize.x = bmp.bmWidth, ptSize.y = bmp.bmHeight, FALSE)
|
|
;
|
|
|
|
else if (dx = dx % ptSize.x, dy = dy % ptSize.y, FALSE)
|
|
;
|
|
|
|
else if (dxAbs = abs(dx), dyAbs = abs(dy), FALSE)
|
|
;
|
|
|
|
// prepare mem dc
|
|
//
|
|
else if ((hdcMem = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!DPtoLP(hdcMem, &ptSize, 1))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (SelectObject(hdcMem, hBitmap), FALSE)
|
|
;
|
|
|
|
// Set proper mapping mode.
|
|
//
|
|
else if (SetMapMode(hdcMem, GetMapMode(hdc)) == 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// prepare temp copy
|
|
//
|
|
else if (dwFlags & BS_ROTATE)
|
|
{
|
|
if ((hdcTemp = CreateCompatibleDC(hdc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpTemp = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hbmpSave = SelectObject(hdcTemp, hbmpTemp)), FALSE)
|
|
;
|
|
|
|
else if (!BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// scroll (rotate if specified)
|
|
//
|
|
if (fSuccess && dx < 0)
|
|
{
|
|
if (!BitBlt(hdcMem,
|
|
0, 0,
|
|
ptSize.x - dxAbs, ptSize.y,
|
|
hdcMem,
|
|
dxAbs, 0,
|
|
SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((dwFlags & BS_ROTATE) &&
|
|
!BitBlt(hdcMem,
|
|
ptSize.x - dxAbs, 0,
|
|
dxAbs, ptSize.y,
|
|
hdcTemp,
|
|
0, 0,
|
|
SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (fSuccess && dx > 0)
|
|
{
|
|
if (!BitBlt(hdcMem,
|
|
dxAbs, 0,
|
|
ptSize.x - dxAbs, ptSize.y,
|
|
hdcMem,
|
|
0, 0,
|
|
SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((dwFlags & BS_ROTATE) &&
|
|
!BitBlt(hdcMem,
|
|
0, 0,
|
|
dxAbs, ptSize.y,
|
|
hdcTemp,
|
|
ptSize.x - dxAbs, 0,
|
|
SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (fSuccess && dy < 0)
|
|
{
|
|
if ((dwFlags & BS_ROTATE) && dx != 0 &&
|
|
!BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!BitBlt(hdcMem,
|
|
0, 0,
|
|
ptSize.x, ptSize.y - dyAbs,
|
|
hdcMem,
|
|
0, dyAbs,
|
|
SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((dwFlags & BS_ROTATE) &&
|
|
!BitBlt(hdcMem,
|
|
0, ptSize.y - dyAbs,
|
|
ptSize.x, dyAbs,
|
|
hdcTemp,
|
|
0, 0,
|
|
SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (fSuccess && dy > 0)
|
|
{
|
|
if ((dwFlags & BS_ROTATE) && dx != 0 &&
|
|
!BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (!BitBlt(hdcMem,
|
|
0, dyAbs,
|
|
ptSize.x, ptSize.y - dyAbs,
|
|
hdcMem,
|
|
0, 0,
|
|
SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((dwFlags & BS_ROTATE) &&
|
|
!BitBlt(hdcMem,
|
|
0, 0,
|
|
ptSize.x, dyAbs,
|
|
hdcTemp,
|
|
0, ptSize.y - dyAbs,
|
|
SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (!fSuccess)
|
|
;
|
|
|
|
// copy back to original bitmap
|
|
//
|
|
else if (!BitBlt(hdc, 0, 0, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// clean up
|
|
//
|
|
|
|
if (hdcTemp != NULL)
|
|
SelectObject(hdcTemp, hbmpSave);
|
|
|
|
if (hdcMem != NULL && !DeleteDC(hdcMem))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hbmpTemp != NULL && !DeleteObject(hbmpTemp))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if (hdcTemp != NULL && !DeleteDC(hdcTemp))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// GfxLoadBitmapEx - load specified bitmap resource, get palette
|
|
// <hInstance> (i) handle of module to load resource from
|
|
// NULL load pre-defined Windows bitmap
|
|
// <lpszBitmap> (i) name of bitmap resource
|
|
// or MAKEINTRESOURCE(idBitmap)
|
|
// or <OBM_xxx> if hInstance is NULL
|
|
// <lphPalette> (o) palette is returned here
|
|
// NULL do not return palette
|
|
// return bitmap handle if success, otherwise NULL
|
|
// NOTE: see documentation for LoadBitmap function
|
|
// NOTE: call DeleteObject() to free returned bitmap and palette handles
|
|
//
|
|
HBITMAP DLLEXPORT WINAPI GfxLoadBitmapEx(HINSTANCE hInstance,
|
|
LPCTSTR lpszBitmap, HPALETTE FAR *lphPalette)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
HRSRC hRsrc = NULL;
|
|
HGLOBAL hGlobal = NULL;
|
|
LPBITMAPINFOHEADER lpbi = NULL;
|
|
HDC hdc = NULL;
|
|
HPALETTE hPalette = NULL;
|
|
HBITMAP hBitmap = NULL;
|
|
int nColors;
|
|
|
|
if ((hRsrc = FindResource(hInstance, lpszBitmap, RT_BITMAP)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hGlobal = LoadResource(hInstance, hRsrc)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((lpbi = (LPBITMAPINFOHEADER) LockResource(hGlobal)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hdc = GetDC(NULL)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hPalette = CreateDIBPalette((LPBITMAPINFO)lpbi, &nColors)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (SelectPalette(hdc, hPalette, FALSE), FALSE)
|
|
;
|
|
|
|
else if (RealizePalette(hdc) == GDI_ERROR)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if ((hBitmap = CreateDIBitmap(hdc,
|
|
(LPBITMAPINFOHEADER) lpbi, (LONG) CBM_INIT,
|
|
(LPSTR)lpbi + lpbi->biSize + nColors * sizeof(RGBQUAD),
|
|
(LPBITMAPINFO) lpbi, DIB_RGB_COLORS)) == NULL)
|
|
{
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// clean up
|
|
//
|
|
|
|
#ifndef _WIN32
|
|
if (hGlobal != NULL)
|
|
{
|
|
UnlockResource(hGlobal);
|
|
FreeResource(hGlobal);
|
|
}
|
|
#endif
|
|
|
|
if (hdc != NULL)
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
if (!fSuccess || lphPalette == NULL)
|
|
{
|
|
if (hPalette != NULL && !DeleteObject(hPalette))
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
// return palette handle here
|
|
//
|
|
if (fSuccess && lphPalette != NULL)
|
|
*lphPalette = hPalette;
|
|
|
|
// return bitmap handle here
|
|
//
|
|
return fSuccess ? hBitmap : NULL;
|
|
}
|
|
|
|
// GfxCreateDIBPalette - create palette
|
|
// <lpbmi> (i) ptr to BITMAPINFO struct, describes DIB
|
|
// <lpnColors> (o) number of colors is returned here
|
|
// return new palette handle if success, otherwise NULL
|
|
//
|
|
HPALETTE DLLEXPORT WINAPI CreateDIBPalette (LPBITMAPINFO lpbmi, LPINT lpnColors)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
LPBITMAPINFOHEADER lpbi;
|
|
LPLOGPALETTE lpPal = NULL;
|
|
HPALETTE hPal = NULL;
|
|
int nColors;
|
|
|
|
if ((lpbi = (LPBITMAPINFOHEADER) lpbmi) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
// calculate color table size
|
|
//
|
|
if (lpbi->biBitCount <= 8)
|
|
nColors = (1 << lpbi->biBitCount);
|
|
else
|
|
nColors = 0; // No palette needed for 24 BPP DIB
|
|
|
|
if (lpbi->biClrUsed > 0)
|
|
nColors = lpbi->biClrUsed; // Use biClrUsed
|
|
|
|
if (nColors <= 0)
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
if (fSuccess)
|
|
{
|
|
if ((lpPal = (LPLOGPALETTE) MemAlloc(NULL, sizeof(LOGPALETTE) +
|
|
sizeof(PALETTEENTRY) * nColors, 0)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
int i;
|
|
|
|
//
|
|
// We have to initalize the memory allocated with MemAlloc
|
|
//
|
|
|
|
memset( lpPal, 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nColors);
|
|
|
|
lpPal->palVersion = 0x300;
|
|
lpPal->palNumEntries = (unsigned short) nColors;
|
|
|
|
for (i = 0; i < nColors; i++)
|
|
{
|
|
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
|
|
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
|
|
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
|
|
lpPal->palPalEntry[i].peFlags = 0;
|
|
}
|
|
|
|
if ((hPal = CreatePalette(lpPal)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
if ((lpPal = MemFree(NULL, lpPal)) != NULL)
|
|
{
|
|
//
|
|
// We should delete hPal resource
|
|
//
|
|
|
|
DeleteObject( hPal );
|
|
hPal = NULL;
|
|
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
// return number of colors here
|
|
//
|
|
if (fSuccess && lpnColors != NULL)
|
|
*lpnColors = nColors;
|
|
|
|
// return new palette here
|
|
//
|
|
return fSuccess ? hPal : NULL;
|
|
}
|
|
|
|
////
|
|
// text routines
|
|
////
|
|
|
|
// GfxTextExtentTruncate - truncate string if too long
|
|
// <lpsz> (i/o) string to truncate
|
|
// <hdc> (i) current device context
|
|
// <cxMax> (i) maximum string width in logical units
|
|
// return new length of string (0 if error)
|
|
//
|
|
int DLLEXPORT WINAPI GfxTextExtentTruncate(LPTSTR lpsz, HDC hdc, int cxMax)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
int cbString;
|
|
|
|
if (hdc == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (lpsz == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
// calculate how many chars in string will fit within cxMax
|
|
//
|
|
cbString = StrLen(lpsz);
|
|
while (fSuccess && cbString > 0)
|
|
{
|
|
SIZE size;
|
|
|
|
if (!GetTextExtentPoint(hdc, lpsz, cbString, &size))
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else if (size.cx <= cxMax)
|
|
break;
|
|
|
|
else
|
|
--cbString;
|
|
}
|
|
|
|
// truncate string so it fits
|
|
//
|
|
*(lpsz + cbString) = '\0';
|
|
}
|
|
|
|
return fSuccess ? cbString : 0;
|
|
}
|
|
|
|
////
|
|
// cursor routines
|
|
////
|
|
|
|
// GfxShowHourglass - show the hourglass cursor
|
|
// <hwndCapture> (i) window to capture mouse input during hourglass
|
|
// return old cursor (NULL if error or none)
|
|
//
|
|
HCURSOR DLLEXPORT WINAPI GfxShowHourglass(HWND hwnd)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
HCURSOR hCursorSave;
|
|
HCURSOR hCursorHourglass;
|
|
|
|
// get predefined hourglass cursor handle
|
|
//
|
|
if ((hCursorHourglass = LoadCursor(NULL, IDC_WAIT)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
// capture all mouse input to specified window
|
|
//
|
|
SetCapture(hwnd);
|
|
|
|
// replace previous cursor with hourglass
|
|
//
|
|
hCursorSave = SetCursor(hCursorHourglass);
|
|
}
|
|
|
|
return fSuccess ? hCursorSave : NULL;
|
|
}
|
|
|
|
// GfxHideHourglass - hide the hourglass cursor
|
|
// <hCursorRestore> (i) cursor handle returned from GfxShowHourglass
|
|
// NULL replace cursor with IDC_ARROW
|
|
// return 0 if success
|
|
//
|
|
int DLLEXPORT WINAPI GfxHideHourglass(HCURSOR hCursorRestore)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
|
|
// get predefined arrow cursor handle if necessary
|
|
//
|
|
if (hCursorRestore == NULL)
|
|
hCursorRestore = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
// replace hourglass with previous cursor
|
|
//
|
|
if (SetCursor(hCursorRestore) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
// restore normal mouse input processing
|
|
//
|
|
ReleaseCapture();
|
|
|
|
return fSuccess ? 0 : -1;
|
|
}
|
|
|
|
// GfxDeviceIsMono - determine if device context is monochrome
|
|
// <hdc> (i) device context
|
|
// NULL use screen device context
|
|
// return TRUE if monochrome, FALSE if color
|
|
//
|
|
BOOL DLLEXPORT WINAPI GfxDeviceIsMono(HDC hdc)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
BOOL fMono;
|
|
HDC hdcScreen = NULL;
|
|
|
|
// get screen device context if none specified
|
|
//
|
|
if (hdc == NULL && (hdc = hdcScreen = GetDC(NULL)) == NULL)
|
|
fSuccess = TraceFALSE(NULL);
|
|
|
|
else
|
|
{
|
|
int nColors = GetDeviceCaps(hdc, NUMCOLORS);
|
|
|
|
fMono = (BOOL) (nColors >= 0 && nColors <= 2);
|
|
|
|
// release screen device context if necessary
|
|
//
|
|
if (hdcScreen != NULL && !ReleaseDC(NULL, hdcScreen))
|
|
fSuccess = TraceFALSE(NULL);
|
|
}
|
|
|
|
return fSuccess ? fMono : TRUE;
|
|
}
|