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.
1353 lines
37 KiB
1353 lines
37 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: dtbitmap.c
|
|
*
|
|
* Copyright (c) 1985-1995, Microsoft Corporation
|
|
*
|
|
* Desktop Wallpaper Routines.
|
|
*
|
|
* History:
|
|
* 29-Jul-1991 MikeKe From win31
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
/*
|
|
* Local Constants.
|
|
*/
|
|
#define MAXPAL 256
|
|
#define MAXSTATIC 20
|
|
#define TILE_XMINSIZE 2
|
|
#define TILE_YMINSIZE 4
|
|
|
|
#define SetBestStretchMode(hdc, bpp, fHT) \
|
|
GreSetStretchBltMode(hdc, \
|
|
(fHT ? HALFTONE : \
|
|
((bpp) == 1 ? BLACKONWHITE : COLORONCOLOR)))
|
|
|
|
#ifdef DEBUG
|
|
/*
|
|
* The version strings are stored in a contiguous-buffer. Each string
|
|
* is of equal-size (MAXVERSIONSTRING).
|
|
*/
|
|
#define MAXTXTBUFFER 80
|
|
#define MAXVERSIONBUFFER 400 // Max size of buffer (contains all 3 strings).
|
|
#define MAXVERSIONSTRING 100 // Size of each string buffer.
|
|
#define OFFSET_VERSTRING 0 // Offset into verbuffer of version-string.
|
|
#define OFFSET_BLDSTRING 100 // Offset into verbuffer of build-string.
|
|
#define OFFSET_CSDSTRING 200 // Offset into verbuffer of CSD string.
|
|
#define OFFSET_PTHSTRING 300 // Offset into verbuffer of path string.
|
|
|
|
|
|
UNICODE_STRING UserVersionString;
|
|
UNICODE_STRING UserBuildString;
|
|
UNICODE_STRING UserCSDString;
|
|
UNICODE_STRING UserPathString;
|
|
WCHAR wszT[MAXTXTBUFFER];
|
|
|
|
/***************************************************************************\
|
|
* GetVersionInfo
|
|
*
|
|
* Outputs a string on the desktop indicating debug-version.
|
|
*
|
|
* History:
|
|
\***************************************************************************/
|
|
|
|
RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[] = {
|
|
|
|
{NULL,
|
|
RTL_QUERY_REGISTRY_DIRECT,
|
|
L"CurrentVersion",
|
|
&UserVersionString,REG_SZ,
|
|
L"4.00",
|
|
0
|
|
},
|
|
|
|
{NULL,
|
|
RTL_QUERY_REGISTRY_DIRECT,
|
|
L"CurrentBuildNumber",
|
|
&UserBuildString,
|
|
REG_NONE,
|
|
NULL,
|
|
0
|
|
},
|
|
|
|
{NULL,
|
|
RTL_QUERY_REGISTRY_DIRECT,
|
|
L"CSDVersion",
|
|
&UserCSDString,
|
|
REG_NONE,
|
|
NULL,
|
|
0
|
|
},
|
|
|
|
{NULL,
|
|
RTL_QUERY_REGISTRY_DIRECT,
|
|
L"PathName",
|
|
&UserPathString,
|
|
REG_NONE,
|
|
NULL,
|
|
0
|
|
},
|
|
|
|
{NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
REG_NONE,
|
|
NULL,
|
|
0
|
|
}
|
|
};
|
|
|
|
|
|
VOID GetVersionInfo(VOID)
|
|
{
|
|
WCHAR NameBuffer[MAXVERSIONBUFFER];
|
|
NTSTATUS Status;
|
|
|
|
UserVersionString.Buffer = &NameBuffer[OFFSET_VERSTRING];
|
|
UserVersionString.Length = 0;
|
|
UserVersionString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
|
|
|
|
UserBuildString.Buffer = &NameBuffer[OFFSET_BLDSTRING];
|
|
UserBuildString.Length = 0;
|
|
UserBuildString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
|
|
|
|
UserCSDString.Buffer = &NameBuffer[OFFSET_CSDSTRING];
|
|
UserCSDString.Length = 0;
|
|
UserCSDString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
|
|
|
|
UserPathString.Buffer = &NameBuffer[OFFSET_PTHSTRING];
|
|
UserPathString.Length = 0;
|
|
UserPathString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
|
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
|
|
L"",
|
|
BaseServerRegistryConfigurationTable,
|
|
NULL,
|
|
NULL);
|
|
|
|
UserAssert(NT_SUCCESS(Status));
|
|
|
|
/*
|
|
* Write out Debugging Version message.
|
|
*/
|
|
wsprintfW(wszT,
|
|
UserCSDString.Length == 0 ?
|
|
L"Microsoft (R) Windows NT (TM) %ws (Build %ws%0.0ws) %ws" :
|
|
L"Microsoft (R) Windows NT (TM) %ws (Build %ws: %ws) %ws",
|
|
UserVersionString.Buffer,
|
|
UserBuildString.Buffer,
|
|
UserCSDString.Buffer,
|
|
UserPathString.Buffer);
|
|
|
|
}
|
|
#endif // DEBUG
|
|
|
|
/***************************************************************************\
|
|
* GetDefaultWallpaperName
|
|
*
|
|
* Get initial bitmap name
|
|
*
|
|
* History:
|
|
* 21-Feb-1995 JimA Created.
|
|
* 06-Mar-1996 ChrisWil Moved to kernel to facilite ChangeDisplaySettings.
|
|
\***************************************************************************/
|
|
|
|
VOID GetDefaultWallpaperName(
|
|
LPWSTR lpszWallpaper)
|
|
{
|
|
HANDLE hkRegistry;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
WCHAR achProductType[512];
|
|
DWORD cbStringSize;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status;
|
|
LPWSTR lpszBitmap;
|
|
|
|
/*
|
|
* Get the product name. There is a bitmap by this name in the windows
|
|
* directory.
|
|
*/
|
|
RtlInitUnicodeString(&UnicodeString,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\"
|
|
L"Control\\ProductOptions");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = ZwOpenKey(&hkRegistry, KEY_READ, &ObjectAttributes);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
/*
|
|
* With this handle, query the ProductType string (for now, either
|
|
* lanmannt or winnt).
|
|
*/
|
|
RtlInitUnicodeString(&UnicodeString, L"ProductType");
|
|
|
|
Status = ZwQueryValueKey(hkRegistry,
|
|
&UnicodeString,
|
|
KeyValueFullInformation,
|
|
achProductType,
|
|
sizeof(achProductType),
|
|
&cbStringSize);
|
|
|
|
if (NT_SUCCESS(Status) &&
|
|
(((PKEY_VALUE_FULL_INFORMATION)achProductType)->DataLength != 0)) {
|
|
|
|
/*
|
|
* Now try to read this bitmap file (there is a lanmannt.bmp or
|
|
* a winnt.bmp in the windows directory).
|
|
*/
|
|
lpszBitmap = (LPWSTR)((PUCHAR)achProductType +
|
|
((PKEY_VALUE_FULL_INFORMATION)achProductType)->DataOffset);
|
|
|
|
/*
|
|
* Set the initial global wallpaper bitmap name for (Default)
|
|
* The global name is an at most 8 character name with no
|
|
* extension. It is "winnt" for workstation or "lanmannt"
|
|
* for server or server upgrade. It is followed by 256 it
|
|
* is for 256 color devices.
|
|
*
|
|
* In the case for NT-Server, we do not use the lpszBitmap
|
|
* string, since it's refered to as "ServerNT" in the registry.
|
|
*/
|
|
if (_wcsicmp(lpszBitmap, L"winnt") == 0) {
|
|
wcsncpycch(lpszWallpaper, lpszBitmap, 8);
|
|
} else {
|
|
wcsncpycch(lpszWallpaper, L"lanmannt", 8);
|
|
}
|
|
|
|
lpszWallpaper[8] = (WCHAR)0;
|
|
|
|
if ((oemInfo.BitsPixel * oemInfo.Planes) > 4) {
|
|
|
|
int iStart = wcslen(lpszWallpaper);
|
|
iStart = min(iStart, 5);
|
|
|
|
lpszWallpaper[iStart] = (WCHAR)0;
|
|
wcscat(lpszWallpaper, L"256");
|
|
}
|
|
|
|
ZwClose(hkRegistry);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Failed to get the name from the registry, so just return a known name.
|
|
*/
|
|
wcscpy(lpszWallpaper, L"lanmannt");
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* GetDeskWallpaperName
|
|
*
|
|
* History:
|
|
* 19-Dec-1994 JimA Created.
|
|
* 29-Sep-1995 ChrisWil ReWrote to return filename.
|
|
\***************************************************************************/
|
|
|
|
#define GDWPN_KEYSIZE 40
|
|
#define GDWPN_BITSIZE 256
|
|
|
|
LPWSTR GetDeskWallpaperName(
|
|
IN LPWSTR lpszFile)
|
|
{
|
|
WCHAR wszKey[GDWPN_KEYSIZE];
|
|
WCHAR wszNone[GDWPN_KEYSIZE];
|
|
LPWSTR lpszBitmap = NULL;
|
|
|
|
/*
|
|
* Load the none-string. This will be used for comparisons later.
|
|
*/
|
|
ServerLoadString(hModuleWin, STR_NONE, wszNone, sizeof(wszNone));
|
|
|
|
if ((lpszFile == NULL) ||
|
|
(lpszFile == SETWALLPAPER_DEFAULT) ||
|
|
(lpszFile == SETWALLPAPER_METRICS)) {
|
|
|
|
/*
|
|
* Allocate a buffer for the wallpaper. We will assume
|
|
* a default-size in this case.
|
|
*/
|
|
lpszBitmap = UserAllocPool(GDWPN_BITSIZE * sizeof(WCHAR), TAG_SYSTEM);
|
|
if (lpszBitmap == NULL)
|
|
return NULL;
|
|
|
|
ServerLoadString(hModuleWin, STR_DTBITMAP, wszKey, sizeof(wszKey));
|
|
|
|
FastOpenProfileUserMapping();
|
|
|
|
/*
|
|
* Get the "Wallpaper" string from WIN.INI's [Desktop] section. The
|
|
* section name is not localized, so hard code it. If the string
|
|
* returned is Empty, then set it up for a none-wallpaper.
|
|
*/
|
|
if (!FastGetProfileStringW(PMAP_DESKTOP,
|
|
wszKey,
|
|
wszNone,
|
|
lpszBitmap,
|
|
(GDWPN_BITSIZE * sizeof(WCHAR)))) {
|
|
|
|
wcscpy(lpszBitmap, wszNone);
|
|
}
|
|
|
|
FastCloseProfileUserMapping();
|
|
|
|
} else {
|
|
|
|
UINT uLen;
|
|
|
|
uLen = max((wcslen(lpszFile) + sizeof(WCHAR)),
|
|
(GDWPN_BITSIZE * sizeof(WCHAR)));
|
|
|
|
/*
|
|
* Allocate enough space to store the name passed in. Returning
|
|
* NULL will allow the wallpaper to redraw. As well, if we're
|
|
* out of memory, then no need to load a wallpaper anyway.
|
|
*/
|
|
lpszBitmap = UserAllocPool(uLen * sizeof(WCHAR), TAG_SYSTEM);
|
|
if (lpszBitmap == NULL)
|
|
return NULL;
|
|
|
|
wcscpy(lpszBitmap, lpszFile);
|
|
}
|
|
|
|
/*
|
|
* No bitmap if NULL passed in or if (NONE) in win.ini entry. We
|
|
* return NULL to force the redraw of the wallpaper in the kernel.
|
|
*/
|
|
if ((*lpszBitmap == (WCHAR)0) || (_wcsicmp(lpszBitmap, wszNone) == 0)) {
|
|
UserFreePool(lpszBitmap);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* If bitmap name set to (DEFAULT) then set it to the system bitmap.
|
|
*/
|
|
ServerLoadString(hModuleWin, STR_DEFAULT, wszKey, sizeof(wszKey));
|
|
|
|
if (_wcsicmp(lpszBitmap, wszKey) == 0)
|
|
GetDefaultWallpaperName(lpszBitmap);
|
|
|
|
return lpszBitmap;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* TestVGAColors
|
|
*
|
|
* Tests whether the log-palette is just a standard 20 palette.
|
|
*
|
|
* History:
|
|
* 29-Sep-1995 ChrisWil Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL TestVGAColors(
|
|
LPLOGPALETTE ppal)
|
|
{
|
|
int i;
|
|
int n;
|
|
int size;
|
|
COLORREF clr;
|
|
|
|
static CONST DWORD StupidColors[] = {
|
|
0x00000000, // 0 Sys Black
|
|
0x00000080, // 1 Sys Dk Red
|
|
0x00008000, // 2 Sys Dk Green
|
|
0x00008080, // 3 Sys Dk Yellow
|
|
0x00800000, // 4 Sys Dk Blue
|
|
0x00800080, // 5 Sys Dk Violet
|
|
0x00808000, // 6 Sys Dk Cyan
|
|
0x00c0c0c0, // 7 Sys Lt Grey
|
|
0x00808080, // 248 Sys Lt Gray
|
|
0x000000ff, // 249 Sys Red
|
|
0x0000ff00, // 250 Sys Green
|
|
0x0000ffff, // 251 Sys Yellow
|
|
0x00ff0000, // 252 Sys Blue
|
|
0x00ff00ff, // 253 Sys Violet
|
|
0x00ffff00, // 254 Sys Cyan
|
|
0x00ffffff, // 255 Sys White
|
|
|
|
0x000000BF, // 1 Sys Dk Red again
|
|
0x0000BF00, // 2 Sys Dk Green again
|
|
0x0000BFBF, // 3 Sys Dk Yellow again
|
|
0x00BF0000, // 4 Sys Dk Blue again
|
|
0x00BF00BF, // 5 Sys Dk Violet again
|
|
0x00BFBF00, // 6 Sys Dk Cyan again
|
|
|
|
0x000000C0, // 1 Sys Dk Red again
|
|
0x0000C000, // 2 Sys Dk Green again
|
|
0x0000C0C0, // 3 Sys Dk Yellow again
|
|
0x00C00000, // 4 Sys Dk Blue again
|
|
0x00C000C0, // 5 Sys Dk Violet again
|
|
0x00C0C000, // 6 Sys Dk Cyan again
|
|
};
|
|
|
|
size = (sizeof(StupidColors) / sizeof(StupidColors[0]));
|
|
|
|
for (i = 0; i < (int)ppal->palNumEntries; i++) {
|
|
|
|
clr = ((LPDWORD)ppal->palPalEntry)[i];
|
|
|
|
for (n = 0; n < size; n++) {
|
|
|
|
if (StupidColors[n] == clr)
|
|
break;
|
|
}
|
|
|
|
if (n == size)
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* DoHTColorAdjustment
|
|
*
|
|
* The default HT-Gamma adjustment was 2.0 on 3.5 (internal to gdi). For
|
|
* 3.51 this value was decreased to 1.0 to accomdate printing. For our
|
|
* desktop-wallpaper we are going to darken it slightly to that the image
|
|
* doesn't appear to light. For the Shell-Release we will provid a UI to
|
|
* allow users to change this for themselves.
|
|
*
|
|
*
|
|
* History:
|
|
* 11-May-1995 ChrisWil Created.
|
|
\***************************************************************************/
|
|
|
|
#define FIXED_GAMMA (WORD)13000
|
|
|
|
VOID DoHTColorAdjust(
|
|
HDC hdc)
|
|
{
|
|
COLORADJUSTMENT ca;
|
|
|
|
|
|
if (GreGetColorAdjustment(hdc, &ca)) {
|
|
|
|
ca.caRedGamma =
|
|
ca.caGreenGamma =
|
|
ca.caBlueGamma = FIXED_GAMMA;
|
|
|
|
GreSetColorAdjustment(hdc, &ca);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* ConvertToDDB
|
|
*
|
|
* Converts a DIBSection to a DDB. We do this to speed up drawings so that
|
|
* bitmap-colors don't have to go through a palette-translation match. This
|
|
* will also stretch/expand the image if the syle is set.
|
|
*
|
|
* If the new image requires a halftone-palette, the we will create one and
|
|
* set it as the new wallpaper-palette.
|
|
*
|
|
* History:
|
|
* 26-Oct-1995 ChrisWil Ported.
|
|
* 30-Oct-1995 ChrisWil Added halftoning. Rewote the stretch/expand stuff.
|
|
\***************************************************************************/
|
|
|
|
HBITMAP ConvertToDDB(
|
|
HDC hdc,
|
|
HBITMAP hbmOld,
|
|
HPALETTE hpal)
|
|
{
|
|
BITMAP bm;
|
|
HBITMAP hbmNew;
|
|
|
|
|
|
/*
|
|
* This object must be a REALDIB type bitmap.
|
|
*/
|
|
GreExtGetObjectW(hbmOld, sizeof(bm), &bm);
|
|
|
|
/*
|
|
* Create the new wallpaper-surface.
|
|
*/
|
|
if (hbmNew = GreCreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight)) {
|
|
|
|
HPALETTE hpalDst;
|
|
HPALETTE hpalSrc;
|
|
HBITMAP hbmDst;
|
|
HBITMAP hbmSrc;
|
|
UINT bpp;
|
|
BOOL fHalftone = FALSE;
|
|
|
|
/*
|
|
* Select in the surfaces.
|
|
*/
|
|
hbmDst = GreSelectBitmap(ghdcMem2, hbmNew);
|
|
hbmSrc = GreSelectBitmap(ghdcMem, hbmOld);
|
|
|
|
/*
|
|
* Determine image bits/pixel.
|
|
*/
|
|
bpp = (bm.bmPlanes * bm.bmBitsPixel);
|
|
|
|
/*
|
|
* Use the palette if given. If the image is of a greater
|
|
* resolution than the device, then we're going to go through
|
|
* a halftone-palette to get better colors.
|
|
*/
|
|
if (hpal) {
|
|
|
|
hpalDst = _SelectPalette(ghdcMem2, hpal, FALSE);
|
|
hpalSrc = _SelectPalette(ghdcMem, hpal, FALSE);
|
|
|
|
xxxRealizePalette(ghdcMem2);
|
|
|
|
/*
|
|
* Set the halftoning for the destination. This is done
|
|
* for images of greater resolution than the device.
|
|
*/
|
|
if (bpp > oemInfo.BitCount) {
|
|
fHalftone = TRUE;
|
|
DoHTColorAdjust(ghdcMem2);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the stretchbltmode. This is more necessary when doing
|
|
* halftoning. Since otherwise, the colors won't translate
|
|
* correctly.
|
|
*/
|
|
SetBestStretchMode(ghdcMem2, bpp, fHalftone);
|
|
|
|
/*
|
|
* Set the new surface bits. Use StretchBlt() so the SBMode
|
|
* will be used in color-translation.
|
|
*/
|
|
GreStretchBlt(ghdcMem2,
|
|
0,
|
|
0,
|
|
bm.bmWidth,
|
|
bm.bmHeight,
|
|
ghdcMem,
|
|
0,
|
|
0,
|
|
bm.bmWidth,
|
|
bm.bmHeight,
|
|
SRCCOPY,
|
|
0);
|
|
|
|
/*
|
|
* Restore palettes.
|
|
*/
|
|
if (hpal) {
|
|
_SelectPalette(ghdcMem2, hpalDst, FALSE);
|
|
_SelectPalette(ghdcMem, hpalSrc, FALSE);
|
|
}
|
|
|
|
/*
|
|
* Restore the surfaces.
|
|
*/
|
|
GreSelectBitmap(ghdcMem2, hbmDst);
|
|
GreSelectBitmap(ghdcMem, hbmSrc);
|
|
GreDeleteObject(hbmOld);
|
|
|
|
GreSetBitmapOwner(hbmNew, OBJECT_OWNER_PUBLIC);
|
|
|
|
} else {
|
|
hbmNew = hbmOld;
|
|
}
|
|
|
|
return hbmNew;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* CreatePaletteFromBitmap
|
|
*
|
|
* Take in a REAL dib handle and create a palette from it. This will not
|
|
* work for bitmaps created by any other means than CreateDIBSection or
|
|
* CreateDIBitmap(CBM_CREATEDIB). This is due to the fact that these are
|
|
* the only two formats who have palettes stored with their object.
|
|
*
|
|
* History:
|
|
* 29-Sep-1995 ChrisWil Created.
|
|
\***************************************************************************/
|
|
|
|
HPALETTE CreatePaletteFromBitmap(
|
|
HBITMAP hbm)
|
|
{
|
|
HPALETTE hpal;
|
|
LPLOGPALETTE ppal;
|
|
HBITMAP hbmT;
|
|
DWORD size;
|
|
int i;
|
|
|
|
|
|
/*
|
|
* Make room for temp logical palette of max size.
|
|
*/
|
|
size = sizeof(LOGPALETTE) + (MAXPAL * sizeof(PALETTEENTRY));
|
|
|
|
ppal = (LPLOGPALETTE)UserAllocPool(size, TAG_SYSTEM);
|
|
|
|
if (!ppal)
|
|
return NULL;
|
|
|
|
/*
|
|
* Retrieve the palette from the DIB(Section). The method of calling
|
|
* GreGetDIBColorTable() can only be done on sections or REAL-Dibs.
|
|
*/
|
|
hbmT = GreSelectBitmap(ghdcMem, hbm);
|
|
ppal->palVersion = 0x300;
|
|
ppal->palNumEntries = GreGetDIBColorTable(ghdcMem,
|
|
0,
|
|
MAXPAL,
|
|
(LPRGBQUAD)ppal->palPalEntry);
|
|
GreSelectBitmap(ghdcMem, hbmT);
|
|
|
|
/*
|
|
* Create a halftone-palette if their are no entries. Otherwise,
|
|
* swap the RGB values to be palentry-compatible and create us a
|
|
* palette.
|
|
*/
|
|
if (ppal->palNumEntries == 0) {
|
|
hpal = GreCreateHalftonePalette(gpDispInfo->hdcScreen);
|
|
} else {
|
|
|
|
BYTE tmpR;
|
|
|
|
/*
|
|
* Swap red/blue because a RGBQUAD and PALETTEENTRY dont get along.
|
|
*/
|
|
for (i=0; i < (int)ppal->palNumEntries; i++) {
|
|
tmpR = ppal->palPalEntry[i].peRed;
|
|
ppal->palPalEntry[i].peRed = ppal->palPalEntry[i].peBlue;
|
|
ppal->palPalEntry[i].peBlue = tmpR;
|
|
ppal->palPalEntry[i].peFlags = 0;
|
|
}
|
|
|
|
/*
|
|
* If the Bitmap only has VGA colors in it we dont want to
|
|
* use a palette. It just causes unessesary palette flashes.
|
|
*/
|
|
hpal = TestVGAColors(ppal) ? NULL : GreCreatePalette(ppal);
|
|
}
|
|
|
|
UserFreePool(ppal);
|
|
|
|
/*
|
|
* Make this palette public.
|
|
*/
|
|
if (hpal)
|
|
GreSetPaletteOwner(hpal, OBJECT_OWNER_PUBLIC);
|
|
|
|
return hpal;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* TileWallpaper
|
|
*
|
|
* History:
|
|
* 29-Jul-1991 MikeKe From win31
|
|
\***************************************************************************/
|
|
|
|
BOOL TileWallpaper(
|
|
PWND pwnd,
|
|
HDC hdc,
|
|
HBITMAP hbm,
|
|
int xO,
|
|
int yO)
|
|
{
|
|
RECT rc;
|
|
BITMAP bm;
|
|
int x;
|
|
int y;
|
|
HBITMAP hbmT = NULL;
|
|
|
|
|
|
if (pwnd != NULL) {
|
|
_GetClientRect(pwnd, &rc);
|
|
} else {
|
|
GreGetClipBox(hdc, &rc, FALSE);
|
|
}
|
|
|
|
/*
|
|
* Make sure we can read the bitmap-info, so that the loop
|
|
* counts make sense.
|
|
*/
|
|
if (GreExtGetObjectW(hbm, sizeof(BITMAP), (PBITMAP)&bm)) {
|
|
|
|
while (xO + bm.bmWidth < rc.left)
|
|
xO += bm.bmWidth;
|
|
|
|
while (yO + bm.bmHeight < rc.top)
|
|
yO += bm.bmHeight;
|
|
|
|
while (xO > rc.left)
|
|
xO -= bm.bmWidth;
|
|
|
|
while (yO > rc.top)
|
|
yO -= bm.bmHeight;
|
|
|
|
/*
|
|
* Tile the bitmap to the surface.
|
|
*/
|
|
if (hbmT = GreSelectBitmap(ghdcMem, hbm)) {
|
|
|
|
for (y = yO; y < rc.bottom; y += bm.bmHeight) {
|
|
for (x = xO; x < rc.right; x += bm.bmWidth) {
|
|
GreBitBlt(hdc,
|
|
x,
|
|
y,
|
|
bm.bmWidth,
|
|
bm.bmHeight,
|
|
ghdcMem,
|
|
0,
|
|
0,
|
|
SRCCOPY,
|
|
0);
|
|
}
|
|
}
|
|
|
|
GreSelectBitmap(ghdcMem, hbmT);
|
|
}
|
|
}
|
|
|
|
return (hbmT != NULL);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* CenterWallpaper
|
|
*
|
|
*
|
|
* History:
|
|
* 29-Jul-1991 MikeKe From win31
|
|
\***************************************************************************/
|
|
|
|
BOOL CenterWallpaper(
|
|
PWND pwnd,
|
|
HDC hdc,
|
|
HBITMAP hbm,
|
|
int x0,
|
|
int y0)
|
|
{
|
|
RECT rc;
|
|
BITMAP bm;
|
|
HBITMAP hbmT;
|
|
int iClip;
|
|
BOOL f = TRUE;
|
|
|
|
GreExtGetObjectW(hbm, sizeof(BITMAP), (PBITMAP)&bm);
|
|
|
|
rc.left = x0;
|
|
rc.top = y0;
|
|
rc.right = x0 + bm.bmWidth;
|
|
rc.bottom = y0 + bm.bmHeight;
|
|
|
|
/*
|
|
* Save the DC.
|
|
*/
|
|
GreSaveDC(hdc);
|
|
|
|
/*
|
|
* Fake up a clipping rect to only use the centered bitmap. If
|
|
* we're returned a NULLREGION, we'll just return TRUE.
|
|
*/
|
|
iClip = GreIntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
|
|
|
|
if (iClip == ERROR) {
|
|
f = FALSE;
|
|
} else if (iClip != NULLREGION) {
|
|
|
|
/*
|
|
* This used to call TileWallpaper, but this really
|
|
* slowed up the system for small dimension bitmaps.
|
|
* We really only need to blt it once for centered
|
|
* bitmaps.
|
|
*/
|
|
if (hbmT = GreSelectBitmap(ghdcMem, hbm)) {
|
|
|
|
GreBitBlt(hdc,
|
|
x0,
|
|
y0,
|
|
bm.bmWidth,
|
|
bm.bmHeight,
|
|
ghdcMem,
|
|
0,
|
|
0,
|
|
SRCCOPY,
|
|
0);
|
|
|
|
GreSelectBitmap(ghdcMem, hbmT);
|
|
|
|
} else {
|
|
f = FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Restore the original DC.
|
|
*/
|
|
GreRestoreDC(hdc, -1);
|
|
|
|
/*
|
|
* Fill the bacground (excluding the bitmap) with the desktop
|
|
* brush. Save the DC with the cliprect.
|
|
*/
|
|
GreSaveDC(hdc);
|
|
|
|
GreExcludeClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
|
|
|
|
if (pwnd != NULL) {
|
|
_GetClientRect(pwnd, &rc);
|
|
} else {
|
|
GreGetClipBox(hdc, &rc, FALSE);
|
|
}
|
|
|
|
FillRect(hdc, &rc, SYSHBR(DESKTOP));
|
|
|
|
GreRestoreDC(hdc, -1);
|
|
|
|
return f;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxDrawWallpaper
|
|
*
|
|
* Performs the drawing of the wallpaper. This can be either tiled or
|
|
* centered. This routine provides the common things like palette-handling.
|
|
* If the (fPaint) is false, then we only to palette realization and no
|
|
* drawing.
|
|
*
|
|
* History:
|
|
* 01-Oct-1995 ChrisWil Ported.
|
|
\***************************************************************************/
|
|
|
|
BOOL xxxDrawWallpaper(
|
|
PWND pwndDesk,
|
|
HDC hdc,
|
|
BOOL fPaint)
|
|
{
|
|
BOOL f;
|
|
HPALETTE hpalT;
|
|
int i;
|
|
|
|
UserAssert(ghbmWallpaper != NULL);
|
|
|
|
/*
|
|
* Select in the palette if one exists. As a wallpaper, we should only
|
|
* be able to do background-realizations.
|
|
*/
|
|
if (ghpalWallpaper) {
|
|
hpalT = _SelectPalette(hdc, ghpalWallpaper, FALSE);
|
|
i = xxxRealizePalette(hdc);
|
|
}
|
|
|
|
/*
|
|
* If we are doing drawing, then we will do the draw. Otherwise, this
|
|
* is pretty much a palette-realization.
|
|
*/
|
|
if (fPaint) {
|
|
|
|
POINT pt;
|
|
|
|
GreGetDCOrg(hdc, &pt);
|
|
GreSetViewportOrg(hdc, -pt.x, -pt.y, &pt);
|
|
|
|
if (gwWPStyle & DTF_TILE)
|
|
f = TileWallpaper(pwndDesk,
|
|
hdc,
|
|
ghbmWallpaper,
|
|
gptDesktop.x,
|
|
gptDesktop.y);
|
|
else
|
|
f = CenterWallpaper(pwndDesk,
|
|
hdc,
|
|
ghbmWallpaper,
|
|
gptDesktop.x,
|
|
gptDesktop.y);
|
|
/*
|
|
* Reset the viewport org.
|
|
*/
|
|
GreSetViewportOrg(hdc, 0, 0, &pt);
|
|
}
|
|
|
|
if (ghpalWallpaper && hpalT) {
|
|
|
|
_SelectPalette(hdc, hpalT, FALSE);
|
|
xxxRealizePalette(hdc);
|
|
|
|
/*
|
|
* On palette changes, makes sure that palettized wallpaper is
|
|
* redrawn in the desktop. If the shell window is around,
|
|
* invalidate that sucker. Otherwise, invalidate our normal desktop.
|
|
*/
|
|
if (i > 0) {
|
|
|
|
PWND pwndShell;
|
|
TL tldeskwnd;
|
|
PDESKTOP pdesk = PtiCurrent()->rpdesk;
|
|
|
|
pwndShell = (pdesk ? pdesk->pDeskInfo->spwndShell : NULL);
|
|
|
|
if (pwndShell) {
|
|
ThreadLockAlways(pwndShell, &tldeskwnd);
|
|
xxxRedrawWindow(pwndShell,
|
|
&grcWallpaper,
|
|
NULL,
|
|
RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
|
|
ThreadUnlock(&tldeskwnd);
|
|
} else {
|
|
ThreadLock(pwndDesk, &tldeskwnd);
|
|
xxxRedrawWindow(pwndDesk,
|
|
&grcWallpaper,
|
|
NULL,
|
|
RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN);
|
|
ThreadUnlock(&tldeskwnd);
|
|
}
|
|
}
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxExpandBitmap
|
|
*
|
|
* Expand this bitmap to fit the screen. This is used for tiled images
|
|
* only.
|
|
*
|
|
* History:
|
|
* 29-Sep-1995 ChrisWil Ported from Chicago.
|
|
\***************************************************************************/
|
|
|
|
HBITMAP xxxExpandBitmap(
|
|
HBITMAP hbm)
|
|
{
|
|
int nx;
|
|
int ny;
|
|
BITMAP bm;
|
|
HBITMAP hbmNew;
|
|
HBITMAP hbmD;
|
|
|
|
/*
|
|
* Get the dimensions of the scren and bitmap we'll
|
|
* be dealing with. We'll adjust the xScreen/yScreen
|
|
* to reflect the new surface size. The default adjustment
|
|
* is to stretch the image to fit the screen.
|
|
*/
|
|
GreExtGetObjectW(hbm, sizeof(bm), (PBITMAP)&bm);
|
|
|
|
nx = (SYSMET(CXSCREEN) / TILE_XMINSIZE) / bm.bmWidth;
|
|
ny = (SYSMET(CYSCREEN) / TILE_YMINSIZE) / bm.bmHeight;
|
|
|
|
if (nx == 0)
|
|
nx++;
|
|
|
|
if (ny == 0)
|
|
ny++;
|
|
|
|
if ((nx + ny) <= 2)
|
|
return hbm;
|
|
|
|
|
|
/*
|
|
* Create the surface for the new-bitmap.
|
|
*/
|
|
hbmD = GreSelectBitmap(ghdcMem, hbm);
|
|
hbmNew = GreCreateCompatibleBitmap(ghdcMem,
|
|
nx * bm.bmWidth,
|
|
ny * bm.bmHeight);
|
|
GreSelectBitmap(ghdcMem, hbmD);
|
|
|
|
if (hbmNew == NULL)
|
|
return hbm;
|
|
|
|
if (hbmD = GreSelectBitmap(ghdcMem2, hbmNew)) {
|
|
/*
|
|
* Expand the bitmap to the new surface.
|
|
*/
|
|
xxxDrawWallpaper(NULL, ghdcMem2, TRUE);
|
|
GreSelectBitmap(ghdcMem2, hbmD);
|
|
}
|
|
|
|
GreDeleteObject(hbm);
|
|
|
|
GreSetBitmapOwner(hbmNew, OBJECT_OWNER_PUBLIC);
|
|
|
|
return hbmNew;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxLoadDesktopWallpaper
|
|
*
|
|
* Load the dib (section) from the client-side. We make this callback to
|
|
* utilize code in USER32 for loading/creating a dib or section. Since,
|
|
* the wallpaper-code can be called from any-process, we can't use DIBSECTIONS
|
|
* for a wallpaper. Luckily we can use Real-DIBs for this. That way we
|
|
* can extract out a palette from the bitmap. We couldn't do this if the
|
|
* bitmap was created "compatible".
|
|
*
|
|
* History:
|
|
* 29-Sep-1995 ChrisWil Created.
|
|
\***************************************************************************/
|
|
|
|
BOOL xxxLoadDesktopWallpaper(
|
|
LPWSTR lpszFile)
|
|
{
|
|
UINT LR_flags;
|
|
int dxDesired;
|
|
int dyDesired;
|
|
BITMAP bm;
|
|
UNICODE_STRING strName;
|
|
|
|
/*
|
|
* If the bitmap is somewhat large (big bpp), then we'll deal
|
|
* with it as a real-dib. We'll also do this for 8bpp since it
|
|
* can utilize a palette. Chicago uses DIBSECTIONS since it can
|
|
* count on the one-process handling the drawing. Since, NT can
|
|
* have different processes doing the drawing, we can't use sections.
|
|
*/
|
|
LR_flags = LR_LOADFROMFILE;
|
|
|
|
if (gpsi->fPaletteDisplay || (oemInfo.BitCount >= 8))
|
|
LR_flags |= LR_CREATEREALDIB;
|
|
|
|
/*
|
|
* If we're stretching, then we will ask the loaddib code to do
|
|
* it.
|
|
*/
|
|
if (gwWPStyle & DTF_STRETCH) {
|
|
dxDesired = SYSMET(CXSCREEN);
|
|
dyDesired = SYSMET(CYSCREEN);
|
|
} else {
|
|
dxDesired = 0;
|
|
dyDesired = 0;
|
|
}
|
|
|
|
/*
|
|
* Make a callback to the client to perform the loading.
|
|
* Saves us some code.
|
|
*/
|
|
RtlInitUnicodeString(&strName, lpszFile);
|
|
|
|
ghbmWallpaper = xxxClientLoadImage(&strName,
|
|
0,
|
|
IMAGE_BITMAP,
|
|
dxDesired,
|
|
dyDesired,
|
|
LR_flags,
|
|
TRUE);
|
|
|
|
if (ghbmWallpaper == NULL)
|
|
return FALSE;
|
|
|
|
/*
|
|
* If it's a palette-display, then we will derive the global
|
|
* wallpaper palette from the bitmap.
|
|
*/
|
|
if (gpsi->fPaletteDisplay)
|
|
ghpalWallpaper = CreatePaletteFromBitmap(ghbmWallpaper);
|
|
|
|
/*
|
|
* If the DIB is a higher bitdepth than the display, convert it to
|
|
* a DDB, otherwise keep it as DIB. This way it takes the least
|
|
* amount of memory and provides a identity-translation blt.
|
|
*
|
|
*/
|
|
GreExtGetObjectW(ghbmWallpaper, sizeof(bm), &bm);
|
|
|
|
if (oemInfo.BitCount <= (bm.bmPlanes * bm.bmBitsPixel)) {
|
|
ghbmWallpaper = ConvertToDDB(gpDispInfo->hdcScreen,
|
|
ghbmWallpaper,
|
|
ghpalWallpaper);
|
|
}
|
|
|
|
/*
|
|
* Expand bitmap if we are going to tile it. Mark the bitmap
|
|
* as public, so any process can party with it. This must
|
|
* preceed the expand, since it performs a xxxDrawWallpaper
|
|
* call that can leave the section.
|
|
*/
|
|
GreSetBitmapOwner(ghbmWallpaper, OBJECT_OWNER_PUBLIC);
|
|
|
|
if (gwWPStyle & DTF_TILE)
|
|
ghbmWallpaper = xxxExpandBitmap(ghbmWallpaper);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxSetDeskWallpaper
|
|
*
|
|
* Sets the desktop-wallpaper. This deletes the old handles in the process.
|
|
*
|
|
* History:
|
|
* 29-Jul-1991 MikeKe From win31.
|
|
* 01-Oct-1995 ChrisWil Rewrote for LoadImage().
|
|
\***************************************************************************/
|
|
|
|
BOOL xxxSetDeskWallpaper(
|
|
LPWSTR lpszFile)
|
|
{
|
|
BITMAP bm;
|
|
UINT WallpaperStyle2;
|
|
PWND pwndShell;
|
|
TL tldeskwnd;
|
|
HBITMAP hbmOld = ghbmWallpaper;
|
|
PDESKTOP pdesk = PtiCurrent()->rpdesk;
|
|
BOOL fRet = FALSE;
|
|
|
|
static LPWSTR gpszWall = NULL;
|
|
|
|
PROFINTINFO apsi[] = {
|
|
{PMAP_DESKTOP, (LPWSTR)STR_TILEWALL , 0, &gwWPStyle},
|
|
{PMAP_DESKTOP, (LPWSTR)STR_DTSTYLE , 0, &WallpaperStyle2 },
|
|
{PMAP_DESKTOP, (LPWSTR)STR_DTORIGINX, 0, &gptDesktop.x },
|
|
{PMAP_DESKTOP, (LPWSTR)STR_DTORIGINY, 0, &gptDesktop.y },
|
|
{0, NULL, 0, NULL }
|
|
};
|
|
|
|
if ((lpszFile == SETWALLPAPER_METRICS) && !(gwWPStyle & DTF_STRETCH)) {
|
|
|
|
gptDesktop.x = 0;
|
|
gptDesktop.y = 0;
|
|
|
|
if (ghbmWallpaper)
|
|
goto CreateNewWallpaper;
|
|
|
|
goto Metric_Change;
|
|
}
|
|
|
|
CreateNewWallpaper:
|
|
|
|
/*
|
|
* Delete the old wallpaper and palette if the exist.
|
|
*/
|
|
if (ghpalWallpaper) {
|
|
GreDeleteObject(ghpalWallpaper);
|
|
ghpalWallpaper = NULL;
|
|
}
|
|
|
|
if (ghbmWallpaper) {
|
|
GreDeleteObject(ghbmWallpaper);
|
|
ghbmWallpaper = NULL;
|
|
}
|
|
|
|
/*
|
|
* Kill any SPBs no matter what.
|
|
* Works if we're switching from/to palettized wallpaper.
|
|
* Fixes a lot of problems because palette doesn't change, shell
|
|
* paints funny on desktop, etc.
|
|
*/
|
|
FreeAllSpbs(NULL);
|
|
|
|
/*
|
|
* Get the shell-window. This could be NULL on system
|
|
* initialization. We will use this to do palette realization.
|
|
*/
|
|
pwndShell = (pdesk ? pdesk->pDeskInfo->spwnd : NULL);
|
|
|
|
/*
|
|
* If this is a metric-change (and stretched), then we need to
|
|
* reload it. However, since we are called from the winlogon process
|
|
* during a desktop-switch, we would be mapped to the wrong Luid
|
|
* when we attempt to grab the name from GetDeskWallpaperName. This
|
|
* would use the Luid from the DEFAULT user rather than the current
|
|
* logged on user. In order to avoid this, we cache the wallpaer
|
|
* name so that on METRIC-CHANGES we use the current-user's wallpaper.
|
|
*
|
|
* NOTE: we assume that prior to any METRIC change, we have already
|
|
* setup the ghbmWallpaper and lpszCached. This is usually done
|
|
* either on logon or during user desktop-changes through conrol-Panel.
|
|
*/
|
|
if (lpszFile == SETWALLPAPER_METRICS) {
|
|
|
|
UserAssert(gpszWall != NULL);
|
|
|
|
goto LoadWallpaper;
|
|
}
|
|
|
|
/*
|
|
* Free the cached handle.
|
|
*/
|
|
if (gpszWall) {
|
|
UserFreePool(gpszWall);
|
|
gpszWall = NULL;
|
|
}
|
|
|
|
/*
|
|
* Load the wallpaper-name. If this returns FALSE, then
|
|
* the user specified (None). We will return true to force
|
|
* the repainting of the desktop.
|
|
*/
|
|
if ((gpszWall = GetDeskWallpaperName(lpszFile)) == NULL) {
|
|
fRet = TRUE;
|
|
goto SDW_Exit;
|
|
}
|
|
|
|
/*
|
|
* Retrieve the default settings from the registry.
|
|
*
|
|
* If tile is indicated, then normalize style to not include
|
|
* FIT/STRETCH which are center-only styles. Likewise, if
|
|
* we are centered, then normalize out the TILE bit.
|
|
*/
|
|
UT_FastGetProfileIntsW(apsi);
|
|
|
|
if (gwWPStyle & DTF_TILE)
|
|
WallpaperStyle2 &= ~(DTF_FIT | DTF_STRETCH);
|
|
else
|
|
gwWPStyle &= ~DTF_TILE;
|
|
|
|
gwWPStyle |= WallpaperStyle2;
|
|
|
|
/*
|
|
* Load the wallpaper. This makes a callback to the client to
|
|
* perform the bitmap-creation.
|
|
*/
|
|
|
|
LoadWallpaper:
|
|
|
|
if (xxxLoadDesktopWallpaper(gpszWall) == FALSE) {
|
|
gwWPStyle = 0;
|
|
goto SDW_Exit;
|
|
}
|
|
|
|
/*
|
|
* If we have a palette, then we need to do the correct realization and
|
|
* notification.
|
|
*/
|
|
if (ghpalWallpaper != NULL) {
|
|
|
|
/*
|
|
* Update the desktop with the new bitmap. This cleans
|
|
* out the system-palette so colors can be realized.
|
|
*/
|
|
GreRealizeDefaultPalette(gpDispInfo->hdcScreen, TRUE);
|
|
|
|
/*
|
|
* Don't broadcast if system initialization is occuring. Otherwise
|
|
* this gives the shell first-crack at realizing its colors
|
|
* correctly.
|
|
*/
|
|
if (pwndShell) {
|
|
|
|
HWND hwnd = HW(pwndShell);
|
|
|
|
ThreadLockAlways(pwndShell, &tldeskwnd);
|
|
xxxSendNotifyMessage(pwndShell, WM_PALETTECHANGED, (DWORD)hwnd, 0);
|
|
ThreadUnlock(&tldeskwnd);
|
|
}
|
|
}
|
|
|
|
Metric_Change:
|
|
|
|
/*
|
|
* Set the wallpaper-rect.
|
|
*/
|
|
grcWallpaper = gpDispInfo->rcScreen;
|
|
|
|
/*
|
|
* Are we centering the bitmap? Save the starting offset
|
|
* for a centered bitmap.
|
|
*/
|
|
if (!(gwWPStyle & (DTF_TILE | DTF_STRETCH))) {
|
|
|
|
GreExtGetObjectW(ghbmWallpaper, sizeof(bm), (PBITMAP)&bm);
|
|
|
|
if (!gptDesktop.x)
|
|
gptDesktop.x = (gpDispInfo->rcScreen.right - bm.bmWidth) / 2;
|
|
|
|
if (!gptDesktop.y)
|
|
gptDesktop.y = (gpDispInfo->rcScreen.bottom - bm.bmHeight) / 2;
|
|
|
|
grcWallpaper.left = gptDesktop.x;
|
|
grcWallpaper.top = gptDesktop.y;
|
|
grcWallpaper.right = gptDesktop.x + bm.bmWidth;
|
|
grcWallpaper.bottom = gptDesktop.y + bm.bmHeight;
|
|
}
|
|
|
|
fRet = TRUE;
|
|
|
|
SDW_Exit:
|
|
|
|
/*
|
|
* Notify the shell-window that the wallpaper changed.
|
|
*/
|
|
if ((pwndShell != NULL) &&
|
|
((hbmOld && !ghbmWallpaper) || (!hbmOld && ghbmWallpaper))) {
|
|
|
|
ThreadLockAlways(pwndShell, &tldeskwnd);
|
|
xxxSendNotifyMessage(pwndShell,
|
|
WM_SHELLNOTIFY,
|
|
SHELLNOTIFY_WALLPAPERCHANGED,
|
|
(LPARAM)ghbmWallpaper);
|
|
ThreadUnlock(&tldeskwnd);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* InternalPaintDesktop
|
|
*
|
|
*
|
|
* History:
|
|
* 29-Jul-1991 MikeKe From win31
|
|
\***************************************************************************/
|
|
|
|
BOOL InternalPaintDesktop(
|
|
PDESKWND pdeskwnd,
|
|
HDC hdc,
|
|
BOOL fPaint)
|
|
{
|
|
BOOL f;
|
|
|
|
/*
|
|
* Paint the desktop with a color or the wallpaper.
|
|
*/
|
|
if (ghbmWallpaper) {
|
|
|
|
f = xxxDrawWallpaper((PWND)pdeskwnd, hdc, fPaint);
|
|
|
|
} else {
|
|
|
|
FillRect(hdc, &gpDispInfo->rcScreen, SYSHBR(DESKTOP));
|
|
f = TRUE;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
SIZE size;
|
|
int imode;
|
|
static BOOL fInit = TRUE;
|
|
|
|
/*
|
|
* Grab the stuff from the registry
|
|
*/
|
|
if (fInit) {
|
|
GetVersionInfo();
|
|
fInit = FALSE;
|
|
}
|
|
|
|
GreGetTextExtentW(hdc, wszT, wcslen(wszT), &size, GGTE_WIN3_EXTENT);
|
|
imode = GreSetBkMode(hdc, TRANSPARENT);
|
|
GreExtTextOutW(hdc,
|
|
(gpDispInfo->rcPrimaryScreen.right - size.cx) / 2,
|
|
0,
|
|
0,
|
|
(LPRECT)NULL,
|
|
wszT,
|
|
wcslen(wszT),
|
|
(LPINT)NULL);
|
|
GreSetBkMode(hdc, imode);
|
|
}
|
|
#endif // !DEBUG
|
|
|
|
return f;
|
|
}
|