mirror of https://github.com/lianthony/NT4.0
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.
560 lines
14 KiB
560 lines
14 KiB
/**************************** Module Header ********************************\
|
|
* Module Name: mngray.c
|
|
*
|
|
* Copyright 1985-1996, Microsoft Corporation
|
|
*
|
|
* Server-side version of DrawState
|
|
*
|
|
* History:
|
|
* 06-Jan-1993 FritzS Created
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#define PATOR 0x00FA0089L
|
|
#define SRCSTENCIL 0x00B8074AL
|
|
#define SRCINVSTENCIL 0x00E20746L
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* DrawState()
|
|
*
|
|
* Generic state drawing routine. Does simple drawing into same DC if
|
|
* normal state; uses offscreen bitmap otherwise.
|
|
*
|
|
* We do drawing for these simple types ourselves:
|
|
* (1) Text
|
|
* lData is string pointer.
|
|
* wData is string length
|
|
* (2) Icon
|
|
* LOWORD(lData) is hIcon
|
|
* (3) Bitmap
|
|
* LOWORD(lData) is hBitmap
|
|
* (4) Glyph (internal)
|
|
* LOWORD(lData) is OBI_ value, one of
|
|
* OBI_CHECKMARK
|
|
* OBI_BULLET
|
|
* OBI_MENUARROW
|
|
* right now
|
|
*
|
|
* Other types are required to draw via the callback function, and are
|
|
* allowed to stick whatever they want in lData and wData.
|
|
*
|
|
* We apply the following effects onto the image:
|
|
* (1) Normal (nothing)
|
|
* (2) Default (drop shadow)
|
|
* (3) Union (gray string dither)
|
|
* (4) Disabled (embossed)
|
|
*
|
|
* Note that we do NOT stretch anything. We just clip.
|
|
*
|
|
\***************************************************************************/
|
|
BOOL _DrawState(
|
|
HDC hdcDraw,
|
|
HBRUSH hbrFore,
|
|
DRAWSTATEPROC qfnCallBack,
|
|
LPARAM lData,
|
|
WPARAM wData,
|
|
int x,
|
|
int y,
|
|
int cx,
|
|
int cy,
|
|
UINT uFlags)
|
|
{
|
|
HFONT hFont;
|
|
HFONT hFontSave = NULL;
|
|
HDC hdcT;
|
|
HBITMAP hbmpT;
|
|
POINT ptOrg;
|
|
BOOL fResult;
|
|
|
|
/*
|
|
* These require monochrome conversion
|
|
*
|
|
* Enforce monochrome: embossed doesn't look great with 2 color displays
|
|
*/
|
|
if ((uFlags & DSS_DISABLED) &&
|
|
((oemInfo.BitCount == 1) || SYSMET(SLOWMACHINE))) {
|
|
|
|
uFlags &= ~DSS_DISABLED;
|
|
uFlags |= DSS_UNION;
|
|
}
|
|
|
|
if (uFlags & (DSS_DISABLED | DSS_DEFAULT | DSS_UNION))
|
|
uFlags |= DSS_MONO;
|
|
|
|
/*
|
|
* Get drawing sizes etc. AND VALIDATE.
|
|
*/
|
|
switch (uFlags & DST_TYPEMASK) {
|
|
|
|
case DST_GLYPH:
|
|
|
|
/*
|
|
* LOWORD(lData) is OBI_ value.
|
|
*/
|
|
UserAssert(LOWORD(lData) < (WORD)OBI_COUNT);
|
|
|
|
if (!cx)
|
|
cx = oemInfo.bm[LOWORD(lData)].cx;
|
|
|
|
if (!cy)
|
|
cy = oemInfo.bm[LOWORD(lData)].cy;
|
|
break;
|
|
|
|
case DST_BITMAP:
|
|
/*
|
|
* (lData) is hbmp.
|
|
*/
|
|
// if (IsGDIObject((HBITMAP)LOWORD(lData)) != GDIOBJ_BITMAP)
|
|
// return FALSE;
|
|
|
|
if (!cx || !cy) {
|
|
BITMAP bmp;
|
|
|
|
try {
|
|
|
|
GreExtGetObjectW((HBITMAP)lData, sizeof(BITMAP), &bmp);
|
|
|
|
if (!cx)
|
|
cx = bmp.bmWidth;
|
|
|
|
if (!cy)
|
|
cy = bmp.bmHeight;
|
|
|
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DST_ICON:
|
|
|
|
/*
|
|
* lData is picon.
|
|
*/
|
|
if (!cx || !cy) {
|
|
|
|
if (!cx)
|
|
cx = ((PICON)lData)->cx;
|
|
|
|
if (!cy)
|
|
cy = ((PICON)lData)->cy / 2; // Icons are double height in NT
|
|
}
|
|
break;
|
|
|
|
case DST_TEXT:
|
|
|
|
/*
|
|
* lData is LPSTR
|
|
* NOTE THAT WE DO NOT VALIDATE lData, DUE TO COMPATIBILITY
|
|
* WITH GRAYSTRING(). THIS _SHOULD_ FAULT IF YOU PASS IN NULL.
|
|
*
|
|
* wData is cch.
|
|
*/
|
|
if (!wData)
|
|
wData = wcslen((LPWSTR)lData);
|
|
|
|
if (!cx || !cy) {
|
|
|
|
SIZE size;
|
|
|
|
/*
|
|
* Make sure we use right dc w/ right font.
|
|
*/
|
|
GreGetTextExtentW(hdcDraw,
|
|
(LPWSTR)lData,
|
|
wData,
|
|
&size,
|
|
GGTE_WIN3_EXTENT);
|
|
|
|
if (!cx)
|
|
cx = size.cx;
|
|
if (!cy)
|
|
cy = size.cy;
|
|
}
|
|
|
|
/*
|
|
* Now, pretend we're complex if qfnCallBack is supplied AND
|
|
* we're supporting GrayString().
|
|
*/
|
|
// if ((uFlags & DST_GRAYSTRING) && SELECTOROF(qfnCallBack)) {
|
|
// uFlags &= ~DST_TYPEMASK;
|
|
// uFlags |= DST_COMPLEX;
|
|
// }
|
|
break;
|
|
|
|
case DST_PREFIXTEXT:
|
|
|
|
if (lData==0) {
|
|
RIPMSG0(RIP_ERROR, "DrawState: NULL DST_PREFIXTEXT string");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!wData)
|
|
wData = wcslen((LPWSTR)lData);
|
|
|
|
if (!cx || !cy) {
|
|
|
|
SIZE size;
|
|
|
|
PSMGetTextExtent(hdcDraw, (LPWSTR)lData, wData, &size);
|
|
|
|
if (!cx)
|
|
cx = size.cx;
|
|
if (!cy)
|
|
cy = size.cy;
|
|
}
|
|
|
|
/*
|
|
* Add on height for prefix
|
|
*/
|
|
cy += 2*SYSMET(CYBORDER);
|
|
break;
|
|
|
|
case DST_COMPLEX:
|
|
if (qfnCallBack == NULL) {
|
|
RIPMSG0(RIP_ERROR, "DrawState: invalid callback for DST_COMPLEX");
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
RIPMSG0(RIP_ERROR, "DrawState: invalid DST_ type");
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Optimize: nothing to draw
|
|
* Have to call callback if GRAYSTRING for compatibility.
|
|
*/
|
|
if ((!cx || !cy)
|
|
// && !(uFlags & DST_GRAYSTRING)
|
|
) {
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Setup drawing dc
|
|
*/
|
|
if (uFlags & DSS_MONO) {
|
|
|
|
hdcT = gpDispInfo->hdcGray;
|
|
|
|
/*
|
|
* Is our scratch bitmap big enough? We need potentially
|
|
* cx+1 by cy pixels for default etc.
|
|
*/
|
|
if ((gpDispInfo->cxGray < cx + 1) || (gpDispInfo->cyGray < cy)) {
|
|
|
|
if (hbmpT = GreCreateBitmap(max(gpDispInfo->cxGray, cx + 1), max(gpDispInfo->cyGray, cy), 1, 1, 0L)) {
|
|
|
|
HBITMAP hbmGray;
|
|
|
|
hbmGray = GreSelectBitmap(gpDispInfo->hdcGray, hbmpT);
|
|
GreDeleteObject(hbmGray);
|
|
|
|
GreSetBitmapOwner(hbmpT, OBJECT_OWNER_PUBLIC);
|
|
|
|
gpDispInfo->cxGray = max(gpDispInfo->cxGray, cx + 1);
|
|
gpDispInfo->cyGray = max(gpDispInfo->cyGray, cy);
|
|
|
|
} else {
|
|
cx = gpDispInfo->cxGray - 1;
|
|
cy = gpDispInfo->cyGray;
|
|
}
|
|
}
|
|
|
|
GrePatBlt(gpDispInfo->hdcGray,
|
|
0,
|
|
0,
|
|
gpDispInfo->cxGray,
|
|
gpDispInfo->cyGray,
|
|
WHITENESS);
|
|
|
|
GreSetTextCharacterExtra(gpDispInfo->hdcGray,
|
|
GreGetTextCharacterExtra(hdcDraw));
|
|
|
|
/*
|
|
* Setup font
|
|
*/
|
|
if ((uFlags & DST_TYPEMASK) <= DST_TEXTMAX) {
|
|
|
|
if (GreGetHFONT(hdcDraw) != ghFontSys) {
|
|
hFont = GreSelectFont(hdcDraw, ghFontSys);
|
|
GreSelectFont(hdcDraw, hFont);
|
|
hFontSave = GreSelectFont(gpDispInfo->hdcGray, hFont);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
hdcT = hdcDraw;
|
|
|
|
/*
|
|
* Adjust viewport
|
|
* Note -- GreSetViewportOrg does not return the previous
|
|
* point. FritzS. Yeah, I know, it should. So it goes.
|
|
*/
|
|
GreGetViewportOrg(hdcT, &ptOrg);
|
|
|
|
#ifdef MEMPHIS_MENU_ANIMATION
|
|
if (hdcDraw == ghdcBits2 && (ptOrg.x == 0 && ptOrg.y == 0)) {
|
|
GreSetViewportOrg(hdcT, x + VIEWPORT_X_OFFSET_GDIBUG,
|
|
y + VIEWPORT_Y_OFFSET_GDIBUG, NULL);
|
|
} else {
|
|
GreSetViewportOrg(hdcT, ptOrg.x+x, ptOrg.y+y, NULL);
|
|
}
|
|
#else
|
|
GreSetViewportOrg(hdcT, x, y, NULL);
|
|
#endif // MEMPHIS_MENU_ANIMATION
|
|
|
|
}
|
|
|
|
/*
|
|
* Now, draw original image
|
|
*/
|
|
fResult = TRUE;
|
|
|
|
switch (uFlags & DST_TYPEMASK) {
|
|
|
|
case DST_GLYPH:
|
|
/*
|
|
* Blt w/ current brush in hdcT
|
|
*/
|
|
BitBltSysBmp(hdcT, 0, 0, LOWORD(lData));
|
|
break;
|
|
|
|
case DST_BITMAP:
|
|
/*
|
|
* Draw the bitmap. If mono, it'll use the colors set up
|
|
* in the dc.
|
|
*/
|
|
UserAssert(GreGetBkColor(ghdcMem) == RGB(255, 255, 255));
|
|
UserAssert(GreGetTextColor(ghdcMem) == RGB(0, 0, 0));
|
|
|
|
hbmpT = GreSelectBitmap(ghdcMem, (HBITMAP)lData);
|
|
GreBitBlt(hdcT, 0, 0, cx, cy, ghdcMem, 0, 0, SRCCOPY, 0);
|
|
GreSelectBitmap(ghdcMem, hbmpT);
|
|
break;
|
|
|
|
case DST_ICON:
|
|
/*
|
|
* Draw the icon.
|
|
*/
|
|
_DrawIconEx(hdcT, 0, 0, (PICON)lData, 0, 0, 0, 0,
|
|
DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE);
|
|
break;
|
|
|
|
case DST_PREFIXTEXT:
|
|
PSMTextOut(hdcT, 0, 0, (LPWSTR)lData, (int)wData);
|
|
break;
|
|
|
|
case DST_TEXT:
|
|
fResult = GreExtTextOutW(hdcT,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
(LPWSTR)lData,
|
|
(int)wData,
|
|
NULL);
|
|
break;
|
|
|
|
default:
|
|
fResult = (qfnCallBack)(hdcT, lData, wData, cx, cy);
|
|
|
|
/*
|
|
* The callbacks could have altered the attributes of hdcGray
|
|
*/
|
|
if (hdcT == gpDispInfo->hdcGray) {
|
|
GreSetBkColor(gpDispInfo->hdcGray, RGB(255, 255, 255));
|
|
GreSetTextColor(gpDispInfo->hdcGray, RGB(0, 0, 0));
|
|
GreSelectBrush(gpDispInfo->hdcGray, ghbrBlack);
|
|
GreSetBkMode(gpDispInfo->hdcGray, OPAQUE);
|
|
}
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Clean up
|
|
*/
|
|
if (uFlags & DSS_MONO) {
|
|
|
|
/*
|
|
* Reset font
|
|
*/
|
|
if (hFontSave)
|
|
GreSelectFont(hdcT, hFontSave);
|
|
} else {
|
|
|
|
/*
|
|
* Reset DC.
|
|
*/
|
|
GreSetViewportOrg(hdcT, ptOrg.x, ptOrg.y, NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* UNION state
|
|
* Dither over image
|
|
* We want white pixels to stay white, in either dest or pattern.
|
|
*/
|
|
if (uFlags & DSS_UNION) {
|
|
|
|
POLYPATBLT PolyData;
|
|
|
|
PolyData.x = 0;
|
|
PolyData.y = 0;
|
|
PolyData.cx = cx;
|
|
PolyData.cy = cy;
|
|
PolyData.BrClr.hbr = ghbrGray;
|
|
|
|
GrePolyPatBlt(gpDispInfo->hdcGray, PATOR, &PolyData, 1, PPB_BRUSH);
|
|
}
|
|
|
|
#ifdef MEMPHIS_MENU_ANIMATION
|
|
if (hdcDraw == ghdcBits2) {
|
|
GreGetViewportOrg(hdcDraw, &ptOrg);
|
|
if (ptOrg.x == 0 && ptOrg.y == 0) {
|
|
GreSetViewportOrg(hdcDraw, VIEWPORT_X_OFFSET_GDIBUG,
|
|
VIEWPORT_X_OFFSET_GDIBUG, NULL);
|
|
}
|
|
}
|
|
#endif // MEMPHIS_MENU_ANIMATION
|
|
|
|
/*
|
|
* Emboss
|
|
* Draw over-1/down-1 in hilight color, and in same position in shadow.
|
|
*/
|
|
if (uFlags & DSS_DISABLED) {
|
|
|
|
BltColor(hdcDraw,
|
|
SYSHBR(3DHILIGHT),
|
|
gpDispInfo->hdcGray,
|
|
x+1,
|
|
y+1,
|
|
cx,
|
|
cy,
|
|
0,
|
|
0,
|
|
TRUE);
|
|
|
|
BltColor(hdcDraw,
|
|
SYSHBR(3DSHADOW),
|
|
gpDispInfo->hdcGray,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
0,
|
|
0,
|
|
TRUE);
|
|
|
|
} else if (uFlags & DSS_DEFAULT) {
|
|
|
|
BltColor(hdcDraw,
|
|
hbrFore,
|
|
gpDispInfo->hdcGray,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
0,
|
|
0,
|
|
TRUE);
|
|
|
|
BltColor(hdcDraw,
|
|
hbrFore,
|
|
gpDispInfo->hdcGray,
|
|
x+1,
|
|
y,
|
|
cx,
|
|
cy,
|
|
0,
|
|
0,
|
|
TRUE);
|
|
|
|
} else {
|
|
|
|
BltColor(hdcDraw,
|
|
hbrFore,
|
|
gpDispInfo->hdcGray,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
0,
|
|
0,
|
|
TRUE);
|
|
}
|
|
|
|
#ifdef MEMPHIS_MENU_ANIMATION
|
|
if (hdcDraw == ghdcBits2) {
|
|
GreSetViewportOrg(hdcDraw, ptOrg.x, ptOrg.y, NULL);
|
|
}
|
|
#endif // MEMPHIS_MENU_ANIMATION
|
|
|
|
return fResult;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* BltColor
|
|
*
|
|
* <brief description>
|
|
*
|
|
* History:
|
|
* 13-Nov-1990 JimA Ported from Win3.
|
|
\***************************************************************************/
|
|
|
|
VOID BltColor(
|
|
HDC hdc,
|
|
HBRUSH hbr,
|
|
HDC hdcSrce,
|
|
int xO,
|
|
int yO,
|
|
int cx,
|
|
int cy,
|
|
int xO1,
|
|
int yO1,
|
|
BOOL fInvert)
|
|
{
|
|
HBRUSH hbrSave;
|
|
DWORD textColorSave;
|
|
DWORD bkColorSave;
|
|
|
|
/*
|
|
* Set the Text and Background colors so that bltColor handles the
|
|
* background of buttons (and other bitmaps) properly.
|
|
* Save the HDC's old Text and Background colors. This causes problems
|
|
* with Omega (and probably other apps) when calling GrayString which
|
|
* uses this routine...
|
|
*/
|
|
textColorSave = GreSetTextColor(hdc, 0x00000000L);
|
|
bkColorSave = GreSetBkColor(hdc, 0x00FFFFFFL);
|
|
|
|
if (hbr != NULL)
|
|
hbrSave = GreSelectBrush(hdc, hbr);
|
|
|
|
GreBitBlt(hdc,
|
|
xO,
|
|
yO,
|
|
cx,
|
|
cy,
|
|
hdcSrce ? hdcSrce : gpDispInfo->hdcGray,
|
|
xO1,
|
|
yO1,
|
|
(fInvert ? 0xB8074AL : 0xE20746L),
|
|
0x00FFFFFF);
|
|
|
|
if (hbr != NULL)
|
|
GreSelectBrush(hdc, hbrSave);
|
|
|
|
/*
|
|
* Restore saved colors
|
|
*/
|
|
GreSetTextColor(hdc, textColorSave);
|
|
GreSetBkColor(hdc, bkColorSave);
|
|
}
|