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