365 lines
9.8 KiB
C
365 lines
9.8 KiB
C
/*
|
||
* RESIMAGE.C
|
||
*
|
||
* Implementation of the Results Image control for OLE 2.0 UI dialogs.
|
||
* We need a separate control for dialogs in order to control the repaints
|
||
* properly and to provide a clean message interface for the dialog
|
||
* implementations.
|
||
*
|
||
* Copyright (c)1992 Microsoft Corporation, All Right Reserved
|
||
*/
|
||
|
||
|
||
#define STRICT 1
|
||
#include "ole2ui.h"
|
||
#include "resimage.h"
|
||
|
||
OLEDBGDATA
|
||
|
||
//Flag indicating if we've registered the class
|
||
static BOOL fRegistered=FALSE;
|
||
|
||
//Bitmap and image dimensions for result images.
|
||
static HBITMAP hBmpResults=NULL;
|
||
static UINT cxBmpResult=0;
|
||
static UINT cyBmpResult=0;
|
||
|
||
/*
|
||
* FResultImageInitialize
|
||
*
|
||
* Purpose:
|
||
* Attempts to load result bitmaps for the current display driver
|
||
* for use in OLE 2.0 UI dialogs. Also registers the ResultImage
|
||
* control class.
|
||
*
|
||
* Parameters:
|
||
* hInst HINSTANCE instance of the DLL.
|
||
*
|
||
* hPrevInst HINSTANCE of the previous instance. Used to
|
||
* determine whether to register window classes or not.
|
||
*
|
||
* lpszClassName LPSTR containing the class name to register the
|
||
* ResultImage control class with.
|
||
*
|
||
* Return Value:
|
||
* BOOL TRUE if all initialization succeeded, FALSE otherwise.
|
||
*/
|
||
|
||
BOOL FResultImageInitialize(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpszClassName)
|
||
{
|
||
int cx, iBmp;
|
||
HDC hDC;
|
||
BITMAP bm;
|
||
|
||
WNDCLASS wc;
|
||
|
||
|
||
/*
|
||
* Determine the aspect ratio of the display we're currently
|
||
* running on and load the appropriate bitmap into the global
|
||
* hBmpResults (used from the ResultImage control only).
|
||
*
|
||
* By retrieving the logical Y extent of the display driver, you
|
||
* only have limited possibilities:
|
||
* LOGPIXELSY Display
|
||
* ----------------------------------------
|
||
* 48 CGA (unsupported)
|
||
* 72 EGA
|
||
* 96 VGA
|
||
* 120 8514/a (i.e. HiRes VGA)
|
||
*/
|
||
|
||
hDC=GetDC(NULL);
|
||
|
||
if (NULL==hDC)
|
||
return FALSE;
|
||
|
||
cx=GetDeviceCaps(hDC, LOGPIXELSY);
|
||
ReleaseDC(NULL, hDC);
|
||
|
||
/*
|
||
* Instead of single comparisons, check ranges instead, so in case
|
||
* we get something funky, we'll act reasonable.
|
||
*/
|
||
if (72 >=cx) iBmp=IDB_RESULTSEGA;
|
||
if (72 < cx && 120 > cx) iBmp=IDB_RESULTSVGA;
|
||
if (120 <=cx) iBmp=IDB_RESULTSHIRESVGA;
|
||
|
||
hBmpResults=LoadBitmap(hInst, MAKEINTRESOURCE(iBmp));
|
||
|
||
if (NULL==hBmpResults)
|
||
{
|
||
//On error, fail loading the DLL
|
||
OleDbgOut1(TEXT("FResultImageInitialize: Failed LoadBitmap.\r\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
OleDbgOut4(TEXT("FResultImageInitialize: Loaded hBmpResults\r\n"));
|
||
|
||
//Now that we have the bitmap, calculate image dimensions
|
||
GetObject(hBmpResults, sizeof(BITMAP), &bm);
|
||
cxBmpResult=bm.bmWidth;
|
||
cyBmpResult=bm.bmHeight/CIMAGESY;
|
||
|
||
|
||
// Only register class if we're the first instance
|
||
if (hPrevInst)
|
||
fRegistered = TRUE;
|
||
else
|
||
{
|
||
// Static flag fRegistered guards against calling this function more
|
||
// than once in the same instance
|
||
|
||
if (!fRegistered)
|
||
{
|
||
wc.lpfnWndProc =ResultImageWndProc;
|
||
wc.cbClsExtra =0;
|
||
wc.cbWndExtra =CBRESULTIMAGEWNDEXTRA;
|
||
wc.hInstance =hInst;
|
||
wc.hIcon =NULL;
|
||
wc.hCursor =LoadCursor(NULL, IDC_ARROW);
|
||
wc.hbrBackground =NULL;
|
||
wc.lpszMenuName =NULL;
|
||
wc.lpszClassName =lpszClassName;
|
||
wc.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
|
||
|
||
fRegistered = RegisterClass(&wc);
|
||
}
|
||
}
|
||
|
||
return fRegistered;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/*
|
||
* ResultImageUninitialize
|
||
*
|
||
* Purpose:
|
||
* Cleans up anything done in FResultImageInitialize, such as freeing
|
||
* the bitmaps. Call from WEP.
|
||
*
|
||
* Parameters:
|
||
* None
|
||
*
|
||
* Return Value:
|
||
* None
|
||
*/
|
||
|
||
void ResultImageUninitialize(void)
|
||
{
|
||
if (NULL!=hBmpResults)
|
||
{
|
||
DeleteObject(hBmpResults);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/*
|
||
* ResultImageWndProc
|
||
*
|
||
* Purpose:
|
||
* Window Procedure for the ResultImage custom control. Only handles
|
||
* WM_CREATE, WM_PAINT, and private messages to manipulate the bitmap.
|
||
*
|
||
* Parameters:
|
||
* Standard
|
||
*
|
||
* Return Value:
|
||
* Standard
|
||
*/
|
||
|
||
LONG CALLBACK EXPORT ResultImageWndProc(HWND hWnd, UINT iMsg
|
||
, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
UINT iBmp;
|
||
PAINTSTRUCT ps;
|
||
HDC hDC;
|
||
|
||
//Handle standard Windows messages.
|
||
switch (iMsg)
|
||
{
|
||
case WM_CREATE:
|
||
SetWindowWord(hWnd, RIWW_IMAGEINDEX, RESULTIMAGE_NONE);
|
||
return 0L;
|
||
|
||
case WM_PAINT:
|
||
iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
|
||
|
||
hDC=BeginPaint(hWnd, &ps);
|
||
|
||
if (RESULTIMAGE_NONE!=iBmp)
|
||
{
|
||
RECT rc;
|
||
UINT x, y;
|
||
HDC hDCDlg;
|
||
HBRUSH hBr;
|
||
LOGBRUSH lb;
|
||
HWND hDlg;
|
||
|
||
/*
|
||
* Our job before using TransparantBlt is to figure out
|
||
* where to position the result image. We place it centered
|
||
* on this control, so get our rect's center and subtract
|
||
* half of the image dimensions.
|
||
*/
|
||
GetClientRect(hWnd, &rc);
|
||
x=(rc.right+rc.left-cxBmpResult)/2;
|
||
y=(rc.bottom+rc.top-cyBmpResult)/2;
|
||
|
||
//Get the backgroup color the dialog is using.
|
||
hDlg=GetParent(hWnd);
|
||
hDCDlg=GetDC(hDlg);
|
||
#if defined( WIN32 )
|
||
hBr = (HBRUSH)SendMessage(hDlg,
|
||
WM_CTLCOLORDLG,
|
||
(WPARAM)hDCDlg,
|
||
(LPARAM)hDlg);
|
||
#else
|
||
hBr = (HBRUSH)SendMessage(hDlg,
|
||
WM_CTLCOLOR,
|
||
(WPARAM)hDCDlg,
|
||
MAKELPARAM(hDlg, CTLCOLOR_DLG));
|
||
#endif
|
||
ReleaseDC(hDlg, hDCDlg);
|
||
|
||
GetObject(hBr, sizeof(LOGBRUSH), &lb);
|
||
SetBkColor(hDC, lb.lbColor);
|
||
|
||
TransparantBlt(hDC, x, y, hBmpResults, 0, iBmp*cyBmpResult
|
||
, cxBmpResult, cyBmpResult, RGBTRANSPARENT);
|
||
}
|
||
|
||
EndPaint(hWnd, &ps);
|
||
break;
|
||
|
||
case RIM_IMAGESET:
|
||
//wParam contains the new index.
|
||
iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
|
||
|
||
//Validate the index before changing it and repainting
|
||
if (RESULTIMAGE_NONE==wParam ||
|
||
((RESULTIMAGE_MIN <= wParam) && (RESULTIMAGE_MAX >= wParam)))
|
||
{
|
||
SetWindowWord(hWnd, RIWW_IMAGEINDEX, (WORD)wParam);
|
||
InvalidateRect(hWnd, NULL, FALSE);
|
||
UpdateWindow(hWnd);
|
||
}
|
||
|
||
//Return the previous index.
|
||
return iBmp;
|
||
|
||
case RIM_IMAGEGET:
|
||
//Return the current index.
|
||
iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
|
||
return (LONG)iBmp;
|
||
|
||
default:
|
||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||
}
|
||
|
||
return 0L;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/*
|
||
* TransparantBlt
|
||
*
|
||
* Purpose:
|
||
* Given a DC, a bitmap, and a color to assume as transparant in that
|
||
* bitmap, BitBlts the bitmap to the DC letting the existing background
|
||
* show in place of the transparant color.
|
||
*
|
||
* Parameters:
|
||
* hDC HDC on which to draw.
|
||
* x, y UINT location at which to draw the bitmap
|
||
* hBmp HBITMIP to draw from
|
||
* xOrg, yOrg UINT coordinates from which to draw the bitamp
|
||
* cx, cy UINT dimensions of the bitmap to Blt.
|
||
* cr COLORREF to consider as transparant.
|
||
*
|
||
* Return Value:
|
||
* None
|
||
*/
|
||
|
||
void TransparantBlt(HDC hDC, UINT x, UINT y, HBITMAP hBmp, UINT xOrg, UINT yOrg
|
||
, UINT cx, UINT cy, COLORREF cr)
|
||
{
|
||
HDC hDCSrc, hDCMid, hMemDC;
|
||
HBITMAP hBmpMono, hBmpT;
|
||
HBRUSH hBr, hBrT;
|
||
COLORREF crBack, crText;
|
||
|
||
if (NULL==hBmp)
|
||
return;
|
||
|
||
//Get three intermediate DC's
|
||
hDCSrc=CreateCompatibleDC(hDC);
|
||
hDCMid=CreateCompatibleDC(hDC);
|
||
hMemDC=CreateCompatibleDC(hDC);
|
||
|
||
SelectObject(hDCSrc, hBmp);
|
||
|
||
//Create a monochrome bitmap for masking
|
||
hBmpMono=CreateCompatibleBitmap(hDCMid, cx, cy);
|
||
SelectObject(hDCMid, hBmpMono);
|
||
|
||
//Create a middle bitmap
|
||
hBmpT=CreateCompatibleBitmap(hDC, cx, cy);
|
||
SelectObject(hMemDC, hBmpT);
|
||
|
||
|
||
//Create a monochrome mask where we have 0's in the image, 1's elsewhere.
|
||
crBack=SetBkColor(hDCSrc, cr);
|
||
BitBlt(hDCMid, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY);
|
||
SetBkColor(hDCSrc, crBack);
|
||
|
||
//Put the unmodified image in the temporary bitmap
|
||
BitBlt(hMemDC, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY);
|
||
|
||
//Create an select a brush of the background color
|
||
hBr=CreateSolidBrush(GetBkColor(hDC));
|
||
hBrT=SelectObject(hMemDC, hBr);
|
||
|
||
//Force conversion of the monochrome to stay black and white.
|
||
crText=SetTextColor(hMemDC, 0L);
|
||
crBack=SetBkColor(hMemDC, RGB(255, 255, 255));
|
||
|
||
/*
|
||
* Where the monochrome mask is 1, Blt the brush; where the mono mask
|
||
* is 0, leave the destination untouches. This results in painting
|
||
* around the image with the background brush. We do this first
|
||
* in the temporary bitmap, then put the whole thing to the screen.
|
||
*/
|
||
BitBlt(hMemDC, 0, 0, cx, cy, hDCMid, 0, 0, ROP_DSPDxax);
|
||
BitBlt(hDC, x, y, cx, cy, hMemDC, 0, 0, SRCCOPY);
|
||
|
||
|
||
SetTextColor(hMemDC, crText);
|
||
SetBkColor(hMemDC, crBack);
|
||
|
||
SelectObject(hMemDC, hBrT);
|
||
DeleteObject(hBr);
|
||
|
||
DeleteDC(hMemDC);
|
||
DeleteDC(hDCSrc);
|
||
DeleteDC(hDCMid);
|
||
DeleteObject(hBmpT);
|
||
DeleteObject(hBmpMono);
|
||
|
||
return;
|
||
}
|
||
|