|
|
/*
* 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; }
|