mirror of https://github.com/tongzx/nt5src
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.
370 lines
12 KiB
370 lines
12 KiB
/*
|
|
* RESIMAGE.CPP
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
#include "resimage.h"
|
|
#include "uiclass.h"
|
|
OLEDBGDATA
|
|
|
|
//Reference counter indicating how many times fResultImageInitialize has been
|
|
//successfully called
|
|
static UINT uRegistered = 0;
|
|
|
|
//Bitmap and image dimensions for result images.
|
|
static HBITMAP hBmpResults = NULL;
|
|
static UINT cxBmpResult;
|
|
static UINT cyBmpResult;
|
|
|
|
/*
|
|
* 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.
|
|
*
|
|
* Return Value:
|
|
* BOOL TRUE if all initialization succeeded, FALSE otherwise.
|
|
*/
|
|
|
|
#pragma code_seg(".text$initseg")
|
|
|
|
BOOL FResultImageInitialize(HINSTANCE hInst, HINSTANCE hPrevInst)
|
|
{
|
|
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;
|
|
|
|
if (NULL == hBmpResults)
|
|
{
|
|
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/CIMAGESX;
|
|
cyBmpResult = bm.bmHeight;
|
|
}
|
|
|
|
|
|
// Only register class if we're the first instance
|
|
if (hPrevInst)
|
|
uRegistered++;
|
|
else
|
|
{
|
|
// Static flag fRegistered guards against calling this function more
|
|
// than once in the same instance
|
|
|
|
if (0 == uRegistered)
|
|
{
|
|
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.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
|
|
|
|
wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE1);
|
|
uRegistered = RegisterClass(&wc) ? 1 : 0;
|
|
|
|
wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE2);
|
|
uRegistered = RegisterClass(&wc) ? 1 : 0;
|
|
|
|
wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE3);
|
|
uRegistered = RegisterClass(&wc) ? 1 : 0;
|
|
}
|
|
else
|
|
uRegistered++;
|
|
}
|
|
|
|
return (uRegistered > 0);
|
|
}
|
|
|
|
#pragma code_seg()
|
|
|
|
|
|
/*
|
|
* ResultImageUninitialize
|
|
*
|
|
* Purpose:
|
|
* Cleans up anything done in FResultImageInitialize, such as freeing
|
|
* the bitmaps. Call from WEP.
|
|
*
|
|
* Parameters:
|
|
* None
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
void ResultImageUninitialize(void)
|
|
{
|
|
--uRegistered;
|
|
if (0 == uRegistered)
|
|
{
|
|
if (NULL != hBmpResults)
|
|
{
|
|
DeleteObject(hBmpResults);
|
|
hBmpResults = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
LRESULT CALLBACK 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 (LRESULT)0;
|
|
|
|
case WM_PAINT:
|
|
iBmp = GetWindowWord(hWnd, RIWW_IMAGEINDEX);
|
|
hDC = BeginPaint(hWnd, &ps);
|
|
|
|
RECT rc;
|
|
UINT x, y;
|
|
HDC hDCDlg;
|
|
HBRUSH hBr;
|
|
LOGBRUSH lb;
|
|
HWND hDlg;
|
|
|
|
/*
|
|
* Our job before using TransparentBlt 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 (hDCDlg)
|
|
{
|
|
//hDCDlg might be NULL in low-memory situations.
|
|
hBr = (HBRUSH)SendMessage(hDlg,
|
|
WM_CTLCOLORDLG,
|
|
(WPARAM)hDCDlg,
|
|
(LPARAM)hDlg);
|
|
ReleaseDC(hDlg, hDCDlg);
|
|
GetObject(hBr, sizeof(LOGBRUSH), &lb);
|
|
SetBkColor(hDC, lb.lbColor);
|
|
}
|
|
|
|
|
|
if (RESULTIMAGE_NONE != iBmp)
|
|
{
|
|
|
|
TransparentBlt(hDC, x, y, hBmpResults, iBmp*cxBmpResult, 0,
|
|
cxBmpResult, cyBmpResult, RGBTRANSPARENT);
|
|
}
|
|
else
|
|
{
|
|
FillRect(hDC, &rc, hBr);
|
|
}
|
|
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_MAX >= wParam)))
|
|
{
|
|
SetWindowWord(hWnd, RIWW_IMAGEINDEX, (WORD)wParam);
|
|
InvalidateRect(hWnd, NULL, FALSE);
|
|
UpdateWindow(hWnd);
|
|
}
|
|
// Return the previous index.
|
|
return (LRESULT)iBmp;
|
|
|
|
case RIM_IMAGEGET:
|
|
// Return the current index.
|
|
iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
|
|
return (LRESULT)iBmp;
|
|
|
|
default:
|
|
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
|
}
|
|
|
|
return (LRESULT)0;
|
|
}
|
|
|
|
|
|
/*
|
|
* TransparentBlt
|
|
*
|
|
* Purpose:
|
|
* Given a DC, a bitmap, and a color to assume as transparent in that
|
|
* bitmap, BitBlts the bitmap to the DC letting the existing background
|
|
* show in place of the transparent 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 transparent.
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
void TransparentBlt(HDC hDC, UINT x, UINT y, HBITMAP hBmp, UINT xOrg, UINT yOrg,
|
|
UINT cx, UINT cy, COLORREF cr)
|
|
{
|
|
if (hBmp)
|
|
{
|
|
// Get three intermediate DC's
|
|
HDC hDCSrc = CreateCompatibleDC(hDC);
|
|
if (hDCSrc)
|
|
{
|
|
HDC hDCMid = CreateCompatibleDC(hDC);
|
|
if (hDCMid)
|
|
{
|
|
HDC hMemDC = CreateCompatibleDC(hDC);
|
|
if (hMemDC)
|
|
{
|
|
SelectObject(hDCSrc, hBmp);
|
|
|
|
// Create a monochrome bitmap for masking
|
|
HBITMAP hBmpMono = CreateCompatibleBitmap(hDCMid, cx, cy);
|
|
if (hBmpMono)
|
|
{
|
|
SelectObject(hDCMid, hBmpMono);
|
|
|
|
// Create a middle bitmap
|
|
HBITMAP hBmpT = CreateCompatibleBitmap(hDC, cx, cy);
|
|
if (hBmpT)
|
|
{
|
|
SelectObject(hMemDC, hBmpT);
|
|
|
|
// Create a monochrome mask where we have 0's in the image, 1's elsewhere.
|
|
COLORREF 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
|
|
HBRUSH hBr = CreateSolidBrush(GetBkColor(hDC));
|
|
if (hBr)
|
|
{
|
|
HBRUSH hBrT = (HBRUSH)SelectObject(hMemDC, hBr);
|
|
|
|
// Force conversion of the monochrome to stay black and white.
|
|
COLORREF 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);
|
|
} // if (hBr)
|
|
DeleteObject(hBmpT);
|
|
} // if (hBmpT)
|
|
DeleteObject(hBmpMono);
|
|
} // if (hBmpMono)
|
|
DeleteDC(hMemDC);
|
|
} // if (hMemDC)
|
|
DeleteDC(hDCMid);
|
|
} // if (hDCMid)
|
|
DeleteDC(hDCSrc);
|
|
} // if (hDCSrc)
|
|
} // if (hBmp)
|
|
}
|