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.
1346 lines
45 KiB
1346 lines
45 KiB
/***************************************************************************\
|
|
*
|
|
* INCTLPAN.C
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* Init Routines which are also used by Control Panel
|
|
*
|
|
* -- Scalable Window Frame Support
|
|
*
|
|
* exports from this module:
|
|
* > xxxSetWindowNCMetrics -- called by LoadWindows & SystemParametersInfo
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
__inline int
|
|
MetricGetID(
|
|
PUNICODE_STRING pProfileUserName,
|
|
UINT idStr,
|
|
int defValue
|
|
)
|
|
{
|
|
int iRet;
|
|
FastGetProfileIntFromID(
|
|
pProfileUserName, PMAP_METRICS, idStr, defValue, &iRet, 0);
|
|
return iRet;
|
|
}
|
|
|
|
static CONST WORD sysBmpStyles[OBI_COUNT][2] = {
|
|
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE, // OBI_CLOSE
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_PUSHED, // OBI_CLOSE_D
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_HOT, // OBI_CLOSE_H
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INACTIVE, // OBI_CLOSE_I
|
|
DFC_CAPTION, DFCS_CAPTIONMIN, // OBI_REDUCE
|
|
DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_PUSHED, // OBI_REDUCE_D
|
|
DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_HOT, // OBI_REDUCE_H
|
|
DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INACTIVE, // OBI_REDUCE_I
|
|
DFC_CAPTION, DFCS_CAPTIONRESTORE, // OBI_RESTORE
|
|
DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_PUSHED, // OBI_RESTORE_D
|
|
DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_HOT, // OBI_RESTORE_H
|
|
DFC_CAPTION, DFCS_CAPTIONHELP, // OBI_HELP
|
|
DFC_CAPTION, DFCS_CAPTIONHELP | DFCS_PUSHED, // OBI_HELP_D
|
|
DFC_CAPTION, DFCS_CAPTIONHELP | DFCS_HOT, // OBI_HELP_H
|
|
DFC_CAPTION, DFCS_CAPTIONMAX, // OBI_ZOOM
|
|
DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_PUSHED, // OBI_ZOOM_D
|
|
DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_HOT, // OBI_ZOOM_H
|
|
DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_INACTIVE, // OBI_ZOOM_I
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INMENU, // OBI_CLOSE_MBAR
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INMENU | DFCS_PUSHED, // OBI_CLOSE_MBAR_D
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INMENU | DFCS_HOT, // OBI_CLOSE_MBAR_H
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INMENU | DFCS_INACTIVE, // OBI_CLOSE_MBAR_I
|
|
DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INMENU, // OBI_REDUCE_MBAR
|
|
DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INMENU | DFCS_PUSHED, // OBI_REDUCE_MBAR_D
|
|
DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INMENU | DFCS_HOT, // OBI_REDUCE_MBAR_H
|
|
DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INMENU | DFCS_INACTIVE, // OBI_REDUCE_MBAR_I
|
|
DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_INMENU, // OBI_RESTORE_MBAR
|
|
DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_INMENU | DFCS_PUSHED, // OBI_RESTORE_MBAR_D
|
|
DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_INMENU | DFCS_HOT, // OBI_RESTORE_MBAR_H
|
|
DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON1
|
|
DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON1_I
|
|
DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON2
|
|
DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON2_I
|
|
DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON3
|
|
DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON3_I
|
|
DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON4
|
|
DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON4_I
|
|
DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON5
|
|
DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON5_I
|
|
DFC_CACHE, DFCS_CACHEBUTTONS, // OBI_CAPBTNS
|
|
DFC_CACHE, DFCS_CACHEBUTTONS | DFCS_INACTIVE, // OBI_CAPBTNS_I
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INSMALL, // OBI_CLOSE_PAL
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INSMALL | DFCS_PUSHED, // OBI_CLOSE_PAL_D
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INSMALL | DFCS_HOT, // OBI_CLOSE_PAL_H
|
|
DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INSMALL | DFCS_INACTIVE,// OBI_CLOSE_PAL_I
|
|
DFC_SCROLL, DFCS_SCROLLSIZEGRIP, // OBI_NCGRIP
|
|
DFC_SCROLL, DFCS_SCROLLUP, // OBI_UPARROW
|
|
DFC_SCROLL, DFCS_SCROLLUP | DFCS_PUSHED | DFCS_FLAT, // OBI_UPARROW_D
|
|
DFC_SCROLL, DFCS_SCROLLUP | DFCS_HOT, // OBI_UPARROW_H
|
|
DFC_SCROLL, DFCS_SCROLLUP | DFCS_INACTIVE, // OBI_UPARROW_I
|
|
DFC_SCROLL, DFCS_SCROLLDOWN, // OBI_DNARROW
|
|
DFC_SCROLL, DFCS_SCROLLDOWN | DFCS_PUSHED | DFCS_FLAT, // OBI_DNARROW_D
|
|
DFC_SCROLL, DFCS_SCROLLDOWN | DFCS_HOT, // OBI_DNARROW_H
|
|
DFC_SCROLL, DFCS_SCROLLDOWN | DFCS_INACTIVE, // OBI_DNARROW_I
|
|
DFC_SCROLL, DFCS_SCROLLRIGHT, // OBI_RGARROW
|
|
DFC_SCROLL, DFCS_SCROLLRIGHT | DFCS_PUSHED | DFCS_FLAT, // OBI_RGARROW_D
|
|
DFC_SCROLL, DFCS_SCROLLRIGHT | DFCS_HOT, // OBI_RGARROW_H
|
|
DFC_SCROLL, DFCS_SCROLLRIGHT | DFCS_INACTIVE, // OBI_RGARROW_I
|
|
DFC_SCROLL, DFCS_SCROLLLEFT, // OBI_LFARROW
|
|
DFC_SCROLL, DFCS_SCROLLLEFT | DFCS_PUSHED | DFCS_FLAT, // OBI_LFARROW_D
|
|
DFC_SCROLL, DFCS_SCROLLLEFT | DFCS_HOT, // OBI_LFARROW_H
|
|
DFC_SCROLL, DFCS_SCROLLLEFT | DFCS_INACTIVE, // OBI_LFARROW_I
|
|
DFC_MENU, DFCS_MENUARROW, // OBI_MENUARROW
|
|
DFC_MENU, DFCS_MENUCHECK, // OBI_MENUCHECK
|
|
DFC_MENU, DFCS_MENUBULLET, // OBI_MENUBULLET
|
|
DFC_MENU, DFCS_MENUARROWUP, // OBI_MENUARROWUP
|
|
DFC_MENU, DFCS_MENUARROWUP | DFCS_HOT, // OBI_MENUARROWUP_H
|
|
DFC_MENU, DFCS_MENUARROWUP | DFCS_INACTIVE, // OBI_MENUARROWUP_I
|
|
DFC_MENU, DFCS_MENUARROWDOWN, // OBI_MENUARROWDOWN
|
|
DFC_MENU, DFCS_MENUARROWDOWN | DFCS_HOT, // OBI_MENUARROWDOWN_H
|
|
DFC_MENU, DFCS_MENUARROWDOWN | DFCS_INACTIVE, // OBI_MENUARROWDOWN_I
|
|
DFC_BUTTON, DFCS_BUTTONRADIOMASK, // OBI_RADIOMASK
|
|
DFC_BUTTON, DFCS_BUTTONCHECK, // OBI_CHECK
|
|
DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_CHECKED, // OBI_CHECK_C
|
|
DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_PUSHED, // OBI_CHECK_D
|
|
DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_PUSHED, // OBI_CHECK_CD
|
|
DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_INACTIVE, // OBI_CHECK_CDI
|
|
DFC_BUTTON, DFCS_BUTTONRADIOIMAGE, // OBI_RADIO
|
|
DFC_BUTTON, DFCS_BUTTONRADIOIMAGE | DFCS_CHECKED, // OBI_RADIO_C
|
|
DFC_BUTTON, DFCS_BUTTONRADIOIMAGE | DFCS_PUSHED, // OBI_RADIO_D
|
|
DFC_BUTTON, DFCS_BUTTONRADIOIMAGE | DFCS_CHECKED | DFCS_PUSHED, // OBI_RADIO_CD
|
|
DFC_BUTTON, DFCS_BUTTONRADIOIMAGE | DFCS_CHECKED | DFCS_INACTIVE, // OBI_RADIO_CDI
|
|
DFC_BUTTON, DFCS_BUTTON3STATE, // OBI_3STATE
|
|
DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_CHECKED, // OBI_3STATE_C
|
|
DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_PUSHED, // OBI_3STATE_D
|
|
DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_PUSHED, // OBI_3STATE_CD
|
|
DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_INACTIVE, // OBI_3STATE_CDI
|
|
DFC_POPUPMENU, DFCS_CAPTIONCLOSE | DFCS_INMENU, // OBI_CLOSE_POPUP
|
|
DFC_POPUPMENU, DFCS_CAPTIONRESTORE | DFCS_INMENU, // OBI_RESTORE_POPUP
|
|
DFC_POPUPMENU, DFCS_CAPTIONMAX | DFCS_INMENU, // OBI_ZOOM_POPUP
|
|
DFC_POPUPMENU, DFCS_CAPTIONMIN | DFCS_INMENU, // OBI_REDUCE_POPUP
|
|
DFC_SCROLL, DFCS_SCROLLSIZEGRIPRIGHT, // OBI_NCGRIP_L
|
|
DFC_MENU, DFCS_MENUARROWRIGHT // OBI_MENUARROW_L
|
|
};
|
|
|
|
#define DIVISOR 72
|
|
#define DU_BTNWIDTH 50 // D.U. of minimum button width in a message box
|
|
|
|
UINT xxxMB_FindLongestString(HDC hdc);
|
|
|
|
#ifdef LATER
|
|
/***************************************************************************\
|
|
\***************************************************************************/
|
|
|
|
WCHAR NibbleToChar(
|
|
BYTE x)
|
|
{
|
|
WCHAR static N2C[] =
|
|
{
|
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
|
|
};
|
|
|
|
return N2C[x];
|
|
}
|
|
|
|
BYTE CharToNibble(
|
|
WCHAR ch)
|
|
{
|
|
BYTE x = (BYTE)ch;
|
|
|
|
return x >= '0' && x <= '9' ?
|
|
x - '0' :
|
|
((10 + x - 'A' ) & 0x0f);
|
|
}
|
|
|
|
BOOL TextToBinary(
|
|
LPBYTE pbyte,
|
|
LPWSTR pwstr,
|
|
int length)
|
|
{
|
|
BYTE checksum = 0;
|
|
|
|
while (TRUE) {
|
|
BYTE byte;
|
|
|
|
byte = (CharToNibble(pwstr[0]) << 4) | CharToNibble(pwstr[1]);
|
|
|
|
if (length == 0) {
|
|
return checksum == byte;
|
|
}
|
|
|
|
checksum += byte;
|
|
*pbyte = byte;
|
|
|
|
pwstr += 2;
|
|
length--;
|
|
pbyte++;
|
|
}
|
|
}
|
|
|
|
void BinaryToText(
|
|
LPWSTR pwstr,
|
|
LPBYTE pbyte,
|
|
int length)
|
|
{
|
|
BYTE checksum = 0;
|
|
|
|
while (length > 0) {
|
|
checksum += *pbyte;
|
|
|
|
pwstr[0] = NibbleToChar((BYTE)((*pbyte >> 4) & 0x0f));
|
|
pwstr[1] = NibbleToChar((BYTE)(*pbyte & 0x0f));
|
|
|
|
pbyte++;
|
|
pwstr += 2;
|
|
length--;
|
|
}
|
|
|
|
pwstr[0] = NibbleToChar((BYTE)((checksum >> 4) & 0x0f));
|
|
pwstr[1] = NibbleToChar((BYTE)(checksum & 0x0f));
|
|
pwstr[2] = '\0';
|
|
}
|
|
|
|
/***************************************************************************\
|
|
\***************************************************************************/
|
|
|
|
// these are the exported apis. The User* versions are for server use only
|
|
// I didn't get them to work since no one calls them yet.
|
|
|
|
BOOL GetPrivateProfileStruct(
|
|
LPWSTR szSection,
|
|
LPWSTR szKey,
|
|
LPWSTR lpStruct,
|
|
DWORD uSizeStruct,
|
|
LPWSTR szFile)
|
|
{
|
|
WCHAR szBuf[256];
|
|
BOOL fAlloc = FALSE;
|
|
LPSTR lpBuf, lpBufTemp;
|
|
int nLen;
|
|
BOOL fError = FALSE;
|
|
|
|
nLen = uSizeStruct * 4 + 10;
|
|
if (nLen > (WORD)sizeof(szBuf)) {
|
|
fAlloc = TRUE;
|
|
lpBuf = (LPSTR)UserAllocPoolWithQuota(nLen, TAG_PROFILE);
|
|
if (lpBuf == NULL)
|
|
return FALSE;
|
|
} else {
|
|
lpBuf = (LPSTR)szBuf;
|
|
}
|
|
|
|
if (szFile && *szFile) {
|
|
nLen = GetPrivateProfileString(szSection, szKey, NULL, lpBuf, nLen, szFile);
|
|
} else {
|
|
nLen = GetProfileString(szSection, szKey, NULL, lpBuf, nLen);
|
|
}
|
|
|
|
if (nLen == (int)(uSizeStruct * 4 + 4)) {
|
|
/*
|
|
* decode the string
|
|
*/
|
|
fError = TextToBinary(lpStruct, lpBufTemp, uSizeStruct);
|
|
}
|
|
|
|
if (fAlloc)
|
|
UserFreePool(lpBuf);
|
|
|
|
return fError;
|
|
}
|
|
|
|
BOOL WritePrivateProfileStruct(
|
|
LPWSTR szSection,
|
|
LPWSTR szKey,
|
|
LPWSTR lpStruct,
|
|
WORD uSizeStruct,
|
|
LPWSTR szFile)
|
|
{
|
|
LPWSTR lpBuf;
|
|
BOOL bRet;
|
|
BOOL fAlloc;
|
|
WCHAR szBuf[256];
|
|
BYTE checksum=0;
|
|
int allocsize = (uSizeStruct * 2 + 3) * sizeof(WCHAR);
|
|
|
|
/* NULL lpStruct erases the the key */
|
|
|
|
if (lpStruct == NULL) {
|
|
if (szFile && *szFile) {
|
|
return WritePrivateProfileString(szSection, szKey, (LPSTR)NULL, szFile);
|
|
} else {
|
|
return WriteProfileString(szSection, szKey, (LPSTR)NULL);
|
|
}
|
|
}
|
|
|
|
fAlloc = (allocsize > sizeof(szBuf));
|
|
if (fAlloc) {
|
|
lpBuf = (LPSTR)UserAllocPoolWithQuota(allocsize, TAG_PROFILE);
|
|
if (!lpBuf)
|
|
return FALSE;
|
|
} else {
|
|
lpBuf = (LPSTR)szBuf;
|
|
}
|
|
|
|
BinaryToText(lpBuf, lpStruct, uSizeStruct);
|
|
|
|
if (szFile && *szFile) {
|
|
bRet = WritePrivateProfileString(szSection, szKey, lpBuf, szFile);
|
|
} else {
|
|
bRet = WriteProfileString(szSection, szKey, lpBuf);
|
|
}
|
|
|
|
if (fAlloc)
|
|
UserFreePool(lpBuf);
|
|
|
|
return bRet;
|
|
}
|
|
#endif
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* GetFrameControlMetrics
|
|
*
|
|
* (cx = 0) is a code meaning cy is the obi of the "shared" bitmap
|
|
*
|
|
\***************************************************************************/
|
|
int GetFrameControlMetrics(
|
|
UINT obi,
|
|
int cxMax )
|
|
{
|
|
int cx, cy;
|
|
UINT wType = sysBmpStyles[obi][0];
|
|
UINT wState = sysBmpStyles[obi][1];
|
|
POEMBITMAPINFO pOem = gpsi->oembmi + obi;
|
|
|
|
switch (wType) {
|
|
case DFC_SCROLL:
|
|
if (wState & DFCS_SCROLLSIZEGRIP) {
|
|
cx = SYSMET(CXVSCROLL);
|
|
cy = SYSMET(CYHSCROLL);
|
|
break;
|
|
} else if (wState & DFCS_SCROLLHORZ) {
|
|
cx = SYSMET(CXHSCROLL);
|
|
cy = SYSMET(CYHSCROLL);
|
|
} else {
|
|
cx = SYSMET(CXVSCROLL);
|
|
cy = SYSMET(CYVSCROLL);
|
|
}
|
|
break;
|
|
|
|
case DFC_MENU:
|
|
case DFC_POPUPMENU:
|
|
if (wState & (DFCS_MENUARROWUP | DFCS_MENUARROWDOWN)) {
|
|
cy = gcyMenuScrollArrow;
|
|
} else {
|
|
/*
|
|
* Add on proper space for space above underscore.
|
|
* the 0xFFFE and -1 are to insure an ODD height
|
|
*/
|
|
cy = ((gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYBORDER)) & 0xFFFE) - 1;
|
|
}
|
|
cx = cy;
|
|
break;
|
|
|
|
case DFC_CAPTION:
|
|
if (wState & DFCS_INSMALL) {
|
|
cx = SYSMET(CXSMSIZE);
|
|
cy = SYSMET(CYSMSIZE);
|
|
} else if (wState & DFCS_INMENU) {
|
|
if ((SYSMET(CXSIZE) == SYSMET(CXMENUSIZE)) &&
|
|
(SYSMET(CYSIZE) == SYSMET(CYMENUSIZE))) {
|
|
cx = 0;
|
|
cy = obi - DOBI_MBAR;
|
|
break;
|
|
} else {
|
|
cx = SYSMET(CXMENUSIZE);
|
|
cy = SYSMET(CYMENUSIZE);
|
|
}
|
|
} else {
|
|
cx = SYSMET(CXSIZE);
|
|
cy = SYSMET(CYSIZE);
|
|
}
|
|
|
|
cx -= SYSMET(CXEDGE);
|
|
cy -= 2 * SYSMET(CYEDGE);
|
|
break;
|
|
|
|
case DFC_CACHE:
|
|
if (wState & DFCS_CACHEBUTTONS) {
|
|
cx = SYSMET(CXSIZE) * 4;
|
|
cy = SYSMET(CYSIZE);
|
|
} else
|
|
cx = cy = SYSMET(CYSIZE);
|
|
break;
|
|
|
|
case DFC_BUTTON:
|
|
if (((wState & 0x00FF) & DFCS_BUTTON3STATE) && !(wState & DFCS_CHECKED)) {
|
|
cx = 0;
|
|
cy = obi - DOBI_3STATE;
|
|
} else {
|
|
/*
|
|
* Scale button size with screen DPI so we look OK on high
|
|
* resolution monitors.
|
|
*/
|
|
cx = cy = (gpsi->dmLogPixels / 8) + 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pOem->cx = cx;
|
|
pOem->cy = cy;
|
|
|
|
return((cx > cxMax) ? cx : cxMax);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* PackFrameControls
|
|
*
|
|
* Given the dimensions that GetFrameControlMetrics has calculated, this
|
|
* arranges all the system bitmaps to fit within a bitmap of the given width
|
|
*
|
|
\***************************************************************************/
|
|
|
|
int PackFrameControls(int cxMax, BOOL fRecord) {
|
|
UINT obi;
|
|
int cy = 0;
|
|
int x = 0;
|
|
int y = 0;
|
|
|
|
|
|
POEMBITMAPINFO pOem = gpsi->oembmi;
|
|
|
|
for (obi = 0; obi < OBI_COUNT; obi++, pOem++) {
|
|
if (pOem->cx) {
|
|
if ((x + pOem->cx) > cxMax) {
|
|
y += cy;
|
|
cy = 0;
|
|
x = 0;
|
|
}
|
|
|
|
if (fRecord) {
|
|
pOem->x = x;
|
|
pOem->y = y;
|
|
}
|
|
|
|
if (cy < pOem->cy)
|
|
cy = pOem->cy;
|
|
|
|
x += pOem->cx;
|
|
}
|
|
}
|
|
|
|
return(y + cy);
|
|
}
|
|
|
|
|
|
void DrawCaptionButtons(
|
|
int x,
|
|
int y
|
|
)
|
|
{
|
|
x += SYSMET(CXEDGE);
|
|
y += SYSMET(CYEDGE);
|
|
|
|
BitBltSysBmp(HDCBITS(), x, y, OBI_REDUCE);
|
|
x += SYSMET(CXSIZE) - SYSMET(CXEDGE);
|
|
BitBltSysBmp(HDCBITS(), x, y, OBI_ZOOM);
|
|
x += SYSMET(CXSIZE);
|
|
BitBltSysBmp(HDCBITS(), x, y, OBI_CLOSE);
|
|
x += SYSMET(CXSIZE);
|
|
BitBltSysBmp(HDCBITS(), x, y, OBI_HELP);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* CreateCaptionStrip
|
|
*
|
|
*
|
|
\***************************************************************************/
|
|
HBITMAP CreateCaptionStrip(VOID)
|
|
{
|
|
HBITMAP hbm;
|
|
|
|
hbm = GreCreateCompatibleBitmap(gpDispInfo->hdcScreen,
|
|
SYSMET(CXVIRTUALSCREEN),
|
|
(SYSMET(CYCAPTION) - 1) * 2);
|
|
|
|
if (hbm)
|
|
GreSetBitmapOwner(hbm, OBJECT_OWNER_PUBLIC);
|
|
|
|
return hbm;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* CreateBitmapStrip
|
|
*
|
|
* This routine sets up either the color or monochrome strip bitmap -- a
|
|
* large horizontal bitmap which contains all of the system bitmaps. By
|
|
* having all of these bitmaps in one long bitmap, we can have that one
|
|
* bitmap always selected in, speeding up paint time by not having to do
|
|
* a SelectBitmap() everytime we need to Blt one of the system bitmaps.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL CreateBitmapStrip(VOID)
|
|
{
|
|
int cxBmp = 0;
|
|
int cyBmp = 0;
|
|
int iCache = 0;
|
|
int cy[5];
|
|
HBITMAP hOldBitmap;
|
|
HBITMAP hNewBmp;
|
|
UINT iType;
|
|
RECT rc;
|
|
UINT wBmpType;
|
|
UINT wBmpStyle;
|
|
POEMBITMAPINFO pOem;
|
|
|
|
/*
|
|
* Each OBI_ must have an entry in sysBmpStyles
|
|
*/
|
|
UserAssert(OBI_COUNT == sizeof(sysBmpStyles) / sizeof(*sysBmpStyles));
|
|
UserAssert(OBI_COUNT == sizeof(gpsi->oembmi) / sizeof(*(gpsi->oembmi)));
|
|
|
|
/*
|
|
* load all the bitmap dimensions into the OEMBITMAPINFO array oemInfo.bm
|
|
*/
|
|
for (iType = 0; iType < OBI_COUNT; iType++)
|
|
cxBmp = GetFrameControlMetrics(iType, cxBmp);
|
|
|
|
for (iType = 0; iType < 5; iType++)
|
|
cy[iType] = PackFrameControls(cxBmp * (iType + 1), FALSE) * (iType + 1);
|
|
|
|
cyBmp = min(cy[0], min(cy[1], min(cy[2], min(cy[3], cy[4]))));
|
|
for (iType = 0; cyBmp != cy[iType]; iType++);
|
|
|
|
cxBmp *= iType + 1;
|
|
cyBmp = PackFrameControls(cxBmp, TRUE);
|
|
|
|
hNewBmp = GreCreateCompatibleBitmap(gpDispInfo->hdcScreen, cxBmp, cyBmp);
|
|
|
|
if (hNewBmp == NULL) {
|
|
RIPMSG0(RIP_WARNING, "CreateBitmapStrip: failed to create bitmap");
|
|
return FALSE;
|
|
}
|
|
|
|
GreSetBitmapOwner(hNewBmp, OBJECT_OWNER_PUBLIC);
|
|
|
|
/*
|
|
* Select in Bitmap Strip -- then delete old one if it exists.
|
|
*/
|
|
hOldBitmap = GreSelectBitmap(HDCBITS(), hNewBmp);
|
|
|
|
if (ghbmBits) {
|
|
#if DBG
|
|
/*
|
|
* Don't RIP if we're out of memory.
|
|
*/
|
|
if (hOldBitmap != NULL && ghbmBits != hOldBitmap) {
|
|
RIPMSG0(RIP_WARNING, "ghbmBits != hOldBitmap");
|
|
}
|
|
#endif
|
|
GreDeleteObject(ghbmCaption);
|
|
GreDeleteObject(hOldBitmap);
|
|
}
|
|
|
|
ghbmBits = hNewBmp;
|
|
|
|
ghbmCaption = CreateCaptionStrip();
|
|
|
|
if (ghbmCaption == NULL) {
|
|
RIPMSG0(RIP_WARNING, "CreateBitmapStrip: failed to create bitmap for caption");
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Draw individual bitmaps into the strip bitmap and record the offsets.
|
|
*/
|
|
for (pOem = gpsi->oembmi, iType = 0; iType < OBI_COUNT; iType++, pOem++) {
|
|
if (!pOem->cx) {
|
|
*pOem = gpsi->oembmi[pOem->cy];
|
|
} else {
|
|
rc.left = pOem->x;
|
|
rc.top = pOem->y;
|
|
rc.right = rc.left + pOem->cx;
|
|
rc.bottom = rc.top + pOem->cy;
|
|
|
|
wBmpType = sysBmpStyles[iType][0];
|
|
wBmpStyle = sysBmpStyles[iType][1];
|
|
|
|
if (wBmpType == DFC_CACHE) {
|
|
if (wBmpStyle & DFCS_CACHEBUTTONS) {
|
|
HBRUSH hbr;
|
|
if (TestALPHA(GRADIENTCAPTIONS)) {
|
|
hbr = (wBmpStyle & DFCS_INACTIVE) ? SYSHBR(GRADIENTINACTIVECAPTION) : SYSHBR(GRADIENTACTIVECAPTION);
|
|
} else {
|
|
hbr = (wBmpStyle & DFCS_INACTIVE) ? SYSHBR(INACTIVECAPTION) : SYSHBR(ACTIVECAPTION);
|
|
}
|
|
FillRect(HDCBITS(), &rc, hbr);
|
|
DrawCaptionButtons(rc.left, rc.top);
|
|
} else if (!(wBmpStyle & DFCS_INACTIVE)) {
|
|
/*
|
|
* Setup Caption Cache Entry
|
|
*/
|
|
UserAssert(iCache < CCACHEDCAPTIONS);
|
|
if (gcachedCaptions[iCache].spcursor) {
|
|
Unlock(&(gcachedCaptions[iCache].spcursor));
|
|
}
|
|
gcachedCaptions[iCache++].pOem = pOem;
|
|
}
|
|
} else {
|
|
DrawFrameControl(HDCBITS(), &rc, wBmpType, wBmpStyle);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Setup other frame metric dependent values.
|
|
*/
|
|
SYSMET(CXMENUCHECK) = gpsi->oembmi[OBI_MENUCHECK].cx;
|
|
SYSMET(CYMENUCHECK) = gpsi->oembmi[OBI_MENUCHECK].cy;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
SetNCMetrics(
|
|
LPNONCLIENTMETRICS lpnc)
|
|
{
|
|
int nMin;
|
|
|
|
/*
|
|
* Scroll metrics
|
|
*/
|
|
SYSMET(CXVSCROLL) = SYSMET(CYHSCROLL) = (int) lpnc->iScrollWidth;
|
|
SYSMET(CYVSCROLL) = SYSMET(CXHSCROLL) = (int) lpnc->iScrollHeight;
|
|
SYSMET(CYVTHUMB) = SYSMET(CXHTHUMB) = (int) lpnc->iScrollHeight;
|
|
|
|
/*
|
|
* Caption metrics
|
|
*/
|
|
SYSMET(CXSIZE) = (int) lpnc->iCaptionWidth;
|
|
SYSMET(CYSIZE) = (int) lpnc->iCaptionHeight;
|
|
SYSMET(CYCAPTION) = SYSMET(CYSIZE) + SYSMET(CYBORDER);
|
|
|
|
/*
|
|
* Keep small icon square?
|
|
* ?? Should we allow rectangles?
|
|
*/
|
|
SYSMET(CXSMICON) = (SYSMET(CXSIZE) - SYSMET(CXEDGE)) & ~1;
|
|
SYSMET(CYSMICON) = (SYSMET(CYSIZE) - SYSMET(CYEDGE)) & ~1;
|
|
nMin = min(SYSMET(CXSMICON), SYSMET(CYSMICON));
|
|
SYSMET(CXSMICON) = nMin;
|
|
SYSMET(CYSMICON) = nMin;
|
|
|
|
/*
|
|
* Small Caption metrics
|
|
*/
|
|
SYSMET(CXSMSIZE) = (int) lpnc->iSmCaptionWidth;
|
|
SYSMET(CYSMSIZE) = (int) lpnc->iSmCaptionHeight;
|
|
SYSMET(CYSMCAPTION) = SYSMET(CYSMSIZE) + SYSMET(CYBORDER);
|
|
|
|
/*
|
|
* Menu metrics
|
|
*/
|
|
SYSMET(CXMENUSIZE) = (int) lpnc->iMenuWidth;
|
|
SYSMET(CYMENUSIZE) = (int) lpnc->iMenuHeight;
|
|
SYSMET(CYMENU) = SYSMET(CYMENUSIZE) + SYSMET(CYBORDER);
|
|
|
|
/*
|
|
* Border metrics
|
|
*/
|
|
gpsi->gclBorder = (int) lpnc->iBorderWidth;
|
|
|
|
SYSMET(CXFRAME) = SYSMET(CXEDGE) + (gpsi->gclBorder+1)*SYSMET(CXBORDER);
|
|
SYSMET(CYFRAME) = SYSMET(CYEDGE) + (gpsi->gclBorder+1)*SYSMET(CYBORDER);
|
|
|
|
/*
|
|
* Minimium tracking size is
|
|
* Across: Space for small icon, 4 chars & space + 3 buttons + borders
|
|
* Down: Space for caption + borders
|
|
* Yes, we use CYSIZE. This is because the width of any small icon
|
|
* is the same as the height, and the height is CYSIZE.
|
|
*/
|
|
SYSMET(CXMINTRACK) = SYSMET(CYSIZE) + (gcxCaptionFontChar * 4) + 2 * SYSMET(CXEDGE) +
|
|
(SYSMET(CXSIZE) * 3) + (SYSMET(CXSIZEFRAME) * 2);
|
|
SYSMET(CYMINTRACK) = SYSMET(CYCAPTION) + (SYSMET(CYSIZEFRAME) * 2);
|
|
|
|
/*
|
|
* Max track size
|
|
* Yeah, max track is bigger than maximized. The reason why is the DOS
|
|
* box. It has a normal sizing border plus the sunken edge around the
|
|
* client. We need to make this big enough to allow the dos box to grow.
|
|
* When it hits its max size, it maximizes automatically.
|
|
*/
|
|
SYSMET(CXMAXTRACK) = SYSMET(CXVIRTUALSCREEN) + (2 * (SYSMET(CXSIZEFRAME) + SYSMET(CXEDGE)));
|
|
SYSMET(CYMAXTRACK) = SYSMET(CYVIRTUALSCREEN) + (2 * (SYSMET(CYSIZEFRAME) + SYSMET(CYEDGE)));
|
|
|
|
SYSMET(CXMIN) = SYSMET(CXMINTRACK);
|
|
SYSMET(CYMIN) = SYSMET(CYMINTRACK);
|
|
|
|
SYSMET(CYMINIMIZED) = 2*SYSMET(CYFIXEDFRAME) + SYSMET(CYSIZE);
|
|
|
|
/*
|
|
* Desktop stuff--working area
|
|
*/
|
|
bSetDevDragWidth(gpDispInfo->hDev,
|
|
gpsi->gclBorder + BORDER_EXTRA);
|
|
|
|
SetDesktopMetrics();
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* CreateFontFromWinIni() -
|
|
*
|
|
* If lplf is NULL, we do a first time, default initialization.
|
|
* Otherwise, lplf is a pointer to the logfont we will use.
|
|
*
|
|
\***************************************************************************/
|
|
HFONT CreateFontFromWinIni(
|
|
PUNICODE_STRING pProfileUserName,
|
|
LPLOGFONTW lplf,
|
|
UINT idFont)
|
|
{
|
|
LOGFONTW lf;
|
|
HFONT hFont;
|
|
|
|
if (lplf == NULL) {
|
|
static CONST WCHAR szDefFont[] = TEXT("MS Shell Dlg");
|
|
/*
|
|
* Fill logfont w/ 0 so we can check if values were filled in.
|
|
*/
|
|
lplf = &lf;
|
|
RtlZeroMemory(&lf, sizeof(lf));
|
|
lf.lfCharSet = gSystemCPCharSet;
|
|
|
|
FastGetProfileValue(pProfileUserName,PMAP_METRICS, (LPWSTR)UIntToPtr( idFont ), NULL, (LPBYTE)&lf, sizeof(lf), 0);
|
|
|
|
/*
|
|
* Default font is MS Shell Dlg
|
|
*/
|
|
if (! lf.lfFaceName[0]) {
|
|
RtlCopyMemory(lf.lfFaceName, szDefFont, sizeof(szDefFont));
|
|
}
|
|
|
|
/*
|
|
* Warning! these values are different then Win 95. They did not have a True Type
|
|
* font so they would round up when they asked for a 6 pt font. We have to ask
|
|
* for an 8 point font ICONFONT to be the same.
|
|
*/
|
|
if (!lf.lfHeight) {
|
|
switch (idFont) {
|
|
case STR_SMCAPTIONFONT:
|
|
case STR_MINFONT:
|
|
case STR_ICONFONT:
|
|
default:
|
|
lf.lfHeight = 8;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We need to convert the point size properly. GDI expects a
|
|
* height in pixels, not points.
|
|
*/
|
|
if (lf.lfHeight > 0) {
|
|
lf.lfHeight = -MultDiv(lf.lfHeight, gpsi->dmLogPixels, 72);
|
|
}
|
|
|
|
if (! lf.lfWeight) {
|
|
switch (idFont) {
|
|
case STR_CAPTIONFONT:
|
|
case STR_MINFONT:
|
|
lf.lfWeight = FW_BOLD;
|
|
break;
|
|
|
|
default:
|
|
lf.lfWeight = FW_NORMAL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
|
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
|
lf.lfQuality = DEFAULT_QUALITY;
|
|
}
|
|
|
|
|
|
hFont = GreCreateFontIndirectW(lplf);
|
|
|
|
if (hFont) {
|
|
LOGFONTW lfT;
|
|
|
|
GreExtGetObjectW(hFont, sizeof(LOGFONTW), &lfT);
|
|
if (lfT.lfHeight != lplf->lfHeight) {
|
|
/*
|
|
* Couldn't find a font with the height that we
|
|
* wanted so use the system font instead.
|
|
*/
|
|
GreDeleteObject(hFont);
|
|
hFont = NULL;
|
|
} else {
|
|
GreMarkUndeletableFont(hFont);
|
|
GreSetLFONTOwner((HLFONT)hFont, OBJECT_OWNER_PUBLIC);
|
|
}
|
|
}
|
|
|
|
if (!hFont) {
|
|
/*
|
|
* We've tried to create the font from the app-supplied description.
|
|
* If failure, return NULL so that we don't change the previous
|
|
* font.
|
|
*/
|
|
if (lplf)
|
|
hFont = NULL;
|
|
else
|
|
hFont = ghFontSys;
|
|
}
|
|
|
|
return hFont;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL UserSetFont(
|
|
PUNICODE_STRING pProfileUserName,
|
|
LPLOGFONTW lplf,
|
|
UINT idFont,
|
|
HFONT* phfont)
|
|
{
|
|
HFONT hNewFont;
|
|
|
|
if (hNewFont = CreateFontFromWinIni(pProfileUserName, lplf, idFont)) {
|
|
if (*phfont != NULL && *phfont != ghFontSys) {
|
|
GreMarkDeletableFont(*phfont);
|
|
GreDeleteObject(*phfont);
|
|
}
|
|
|
|
*phfont = hNewFont;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* xxxSetNCFonts() -
|
|
*
|
|
* Creates fonts to be used in the frame components:
|
|
* Caption
|
|
* Small caption
|
|
* Menu
|
|
* Minimized
|
|
* Icon
|
|
*
|
|
* 01-21-98 [SamerA] Renamed to xxxSetNCFonts since it may leave the
|
|
* critical section when a client LPK is installed.
|
|
\***************************************************************************/
|
|
BOOL xxxSetNCFonts(
|
|
PUNICODE_STRING pProfileUserName,
|
|
LPNONCLIENTMETRICS lpnc)
|
|
{
|
|
HFONT hOldFont;
|
|
TEXTMETRIC tm;
|
|
LOGFONTW lf;
|
|
LPLOGFONTW lplf = (lpnc) ? &lf : 0;
|
|
|
|
/*
|
|
* Caption font
|
|
*/
|
|
if (lplf) {
|
|
*lplf = lpnc->lfCaptionFont;
|
|
}
|
|
|
|
if (!UserSetFont(pProfileUserName,lplf, STR_CAPTIONFONT, &gpsi->hCaptionFont)) {
|
|
RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for gpsi->hCaptionFont");
|
|
return FALSE;
|
|
}
|
|
|
|
hOldFont = GreSelectFont(HDCBITS(), gpsi->hCaptionFont);
|
|
gcxCaptionFontChar = GetCharDimensions(
|
|
HDCBITS(), NULL, &gcyCaptionFontChar);
|
|
|
|
#ifdef LAME_BUTTON
|
|
/*
|
|
* Lame! button font
|
|
*/
|
|
{
|
|
LOGFONTW lfLame;
|
|
WCHAR szLameButtonKey[60];
|
|
SIZE btnSize;
|
|
|
|
if (ghLameFont != NULL) {
|
|
GreMarkDeletableFont(ghLameFont);
|
|
GreDeleteObject(ghLameFont);
|
|
}
|
|
|
|
GreExtGetObjectW(gpsi->hCaptionFont, sizeof(LOGFONTW), &lfLame);
|
|
|
|
lfLame.lfUnderline = 1;
|
|
lfLame.lfWeight = FW_THIN;
|
|
|
|
ghLameFont = GreCreateFontIndirectW(&lfLame);
|
|
if (ghLameFont == NULL) {
|
|
RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for ghLameFont");
|
|
return FALSE;
|
|
} else {
|
|
GreMarkUndeletableFont(ghLameFont);
|
|
GreSetLFONTOwner((HLFONT)ghLameFont, OBJECT_OWNER_PUBLIC);
|
|
}
|
|
|
|
ServerLoadString(hModuleWin, STR_LAMEBUTTONTEXT, szLameButtonKey, ARRAY_SIZE(szLameButtonKey));
|
|
|
|
FastGetProfileStringW(pProfileUserName,
|
|
PMAP_DESKTOP,
|
|
szLameButtonKey,
|
|
TEXT("Comments?"),
|
|
gpsi->gwszLame,
|
|
50,
|
|
0);
|
|
|
|
GreSelectFont(HDCBITS(), ghLameFont);
|
|
|
|
GreGetTextExtentW(HDCBITS(),
|
|
gpsi->gwszLame,
|
|
wcslen(gpsi->gwszLame),
|
|
&btnSize,
|
|
GGTE_WIN3_EXTENT);
|
|
|
|
gpsi->ncxLame = btnSize.cx;
|
|
}
|
|
#endif // LAME_BUTTON
|
|
|
|
/*
|
|
* Small caption font
|
|
*/
|
|
if (lplf) {
|
|
*lplf = lpnc->lfSmCaptionFont;
|
|
}
|
|
|
|
if (!UserSetFont(pProfileUserName,lplf, STR_SMCAPTIONFONT, &ghSmCaptionFont)) {
|
|
RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for ghSmCaptionFont");
|
|
return FALSE;
|
|
}
|
|
|
|
GreSelectFont(HDCBITS(), ghSmCaptionFont);
|
|
gcxSmCaptionFontChar = GetCharDimensions(
|
|
HDCBITS(), NULL, &gcySmCaptionFontChar);
|
|
|
|
/*
|
|
* Menu font
|
|
*/
|
|
if (lplf) {
|
|
*lplf = lpnc->lfMenuFont;
|
|
}
|
|
|
|
if (!UserSetFont(pProfileUserName,lplf, STR_MENUFONT, &ghMenuFont)) {
|
|
RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for ghMenuFont");
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* if ghMenuFont is selected in cached animation DC, select the new one.
|
|
*/
|
|
if (gMenuState.hdcAni != NULL) {
|
|
GreSelectFont(gMenuState.hdcAni, ghMenuFont);
|
|
}
|
|
|
|
GreSelectFont(HDCBITS(), ghMenuFont);
|
|
gcxMenuFontChar = GetCharDimensions(
|
|
HDCBITS(), &tm, &gcyMenuFontChar);
|
|
gcxMenuFontOverhang = tm.tmOverhang;
|
|
|
|
gcyMenuFontExternLeading = tm.tmExternalLeading;
|
|
gcyMenuScrollArrow = gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYEDGE);
|
|
gcyMenuFontAscent = tm.tmAscent;
|
|
|
|
/*
|
|
* We only use gcyMenuFontAscent in mndraw.c once, and in U.S. we
|
|
* always add on CYBORDER! So calculate gcyMenuFontAscent+CYBORDER
|
|
* once only.
|
|
* Legacy NT4: For Korean version, don't add it on; the underline would
|
|
* be too low.
|
|
* NT5: according to #254327, Korean version now sees underline is
|
|
* too close to menu strings. Korean hack is pulled out so.
|
|
*/
|
|
gcyMenuFontAscent += SYSMET(CYBORDER);
|
|
|
|
/*
|
|
* Default menu item font: bolder version of menu font
|
|
*/
|
|
|
|
/*
|
|
* Create default menu font by bolding hMenuFont. If this doesn't
|
|
* work, then fall back to using simulation.
|
|
*/
|
|
if (ghMenuFontDef != NULL && ghMenuFontDef != ghFontSys) {
|
|
GreMarkDeletableFont(ghMenuFontDef);
|
|
GreDeleteObject(ghMenuFontDef);
|
|
ghMenuFontDef = NULL;
|
|
}
|
|
|
|
GreExtGetObjectW(ghMenuFont, sizeof(LOGFONTW), &lf);
|
|
if (lf.lfWeight < FW_BOLD) {
|
|
lf.lfWeight += 200;
|
|
|
|
ghMenuFontDef = GreCreateFontIndirectW(&lf);
|
|
if (ghMenuFontDef) {
|
|
GreMarkUndeletableFont(ghMenuFontDef);
|
|
GreSetLFONTOwner((HLFONT)ghMenuFontDef, OBJECT_OWNER_PUBLIC);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Status Bar font
|
|
*/
|
|
if (lplf) {
|
|
*lplf = lpnc->lfStatusFont;
|
|
}
|
|
|
|
if (!UserSetFont(pProfileUserName,lplf, STR_STATUSFONT, &ghStatusFont)) {
|
|
RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for ghStatusFont");
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Message Box font
|
|
*/
|
|
if (lplf) {
|
|
*lplf = lpnc->lfMessageFont;
|
|
}
|
|
|
|
if (!UserSetFont(pProfileUserName,lplf, STR_MESSAGEFONT, &gpsi->hMsgFont)) {
|
|
RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for gpsi->hMsgFont");
|
|
return FALSE;
|
|
}
|
|
|
|
GreSelectFont(HDCBITS(), gpsi->hMsgFont);
|
|
gpsi->cxMsgFontChar = GetCharDimensions(
|
|
HDCBITS(), NULL, &gpsi->cyMsgFontChar);
|
|
|
|
/*
|
|
* Recalculate length of the widest MessageBox button
|
|
* Make sure the width is no less than DU_BTNWIDTH dialog units MCostea #170582
|
|
*/
|
|
gpsi->wMaxBtnSize = max((UINT)XPixFromXDU(DU_BTNWIDTH, gpsi->cxMsgFontChar),
|
|
xxxMB_FindLongestString(HDCBITS()));
|
|
GreSelectFont(HDCBITS(), hOldFont);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SetIconFonts(
|
|
PUNICODE_STRING pProfileUserName,
|
|
LPICONMETRICS lpicon)
|
|
{
|
|
LOGFONTW lf;
|
|
LPLOGFONTW lplf = 0;
|
|
|
|
if (lpicon) {
|
|
lplf = &lf;
|
|
lf = lpicon->lfFont;
|
|
}
|
|
|
|
return UserSetFont(pProfileUserName, lplf, STR_ICONFONT, &ghIconFont);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* GetWindowMetrics
|
|
*
|
|
* Retrieve the current NC metrics.
|
|
*
|
|
*
|
|
\***************************************************************************/
|
|
|
|
VOID GetWindowNCMetrics(
|
|
LPNONCLIENTMETRICS lpnc)
|
|
{
|
|
lpnc->cbSize = sizeof(NONCLIENTMETRICS);
|
|
lpnc->iBorderWidth = gpsi->gclBorder;
|
|
lpnc->iScrollWidth = SYSMET(CXVSCROLL);
|
|
lpnc->iScrollHeight = SYSMET(CYVSCROLL);
|
|
lpnc->iCaptionWidth = SYSMET(CXSIZE);
|
|
lpnc->iCaptionHeight = SYSMET(CYSIZE);
|
|
lpnc->iSmCaptionWidth = SYSMET(CXSMSIZE);
|
|
lpnc->iSmCaptionHeight = SYSMET(CYSMSIZE);
|
|
lpnc->iMenuWidth = SYSMET(CXMENUSIZE);
|
|
lpnc->iMenuHeight = SYSMET(CYMENUSIZE);
|
|
|
|
/*
|
|
* Get the font info.
|
|
*/
|
|
GreExtGetObjectW(gpsi->hCaptionFont,
|
|
sizeof(LOGFONTW),
|
|
&(lpnc->lfCaptionFont));
|
|
|
|
GreExtGetObjectW(ghSmCaptionFont,
|
|
sizeof(LOGFONTW),
|
|
&(lpnc->lfSmCaptionFont));
|
|
|
|
GreExtGetObjectW(ghMenuFont,
|
|
sizeof(LOGFONTW),
|
|
&(lpnc->lfMenuFont));
|
|
|
|
GreExtGetObjectW(ghStatusFont,
|
|
sizeof(LOGFONTW),
|
|
&(lpnc->lfStatusFont));
|
|
|
|
GreExtGetObjectW(gpsi->hMsgFont,
|
|
sizeof(LOGFONTW),
|
|
&(lpnc->lfMessageFont));
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* xxxSetWindowNCMetrics() -
|
|
*
|
|
* creates system fonts and bitmaps and sets the system metrics based on the
|
|
* values of the given FRAMEMETRICS struct. If NULL is passed in, the
|
|
* default values (found in WIN.INI) are used instead.
|
|
*
|
|
* 01-21-98 [SamerA] Renamed to xxxSetWindowNCMetrics since it may leave the
|
|
* critical section if an LPK is installed.
|
|
\***************************************************************************/
|
|
|
|
BOOL xxxSetWindowNCMetrics(
|
|
PUNICODE_STRING pProfileUserName,
|
|
LPNONCLIENTMETRICS lpnc,
|
|
BOOL fSizeChange,
|
|
int clNewBorder)
|
|
{
|
|
NONCLIENTMETRICS nc;
|
|
int cxEdge4;
|
|
|
|
if (fSizeChange) {
|
|
if (!xxxSetNCFonts(pProfileUserName, lpnc)) {
|
|
RIPMSG0(RIP_WARNING, "xxxSetWindowNCMetrics failed in xxxSetNCFonts");
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpnc == NULL) {
|
|
if (clNewBorder < 0)
|
|
nc.iBorderWidth = MetricGetID(pProfileUserName,STR_BORDERWIDTH, 1);
|
|
else
|
|
nc.iBorderWidth = clNewBorder;
|
|
|
|
nc.iScrollWidth = MetricGetID(pProfileUserName,STR_SCROLLWIDTH, 16 );
|
|
nc.iScrollHeight = MetricGetID(pProfileUserName,STR_SCROLLHEIGHT, 16 );
|
|
nc.iCaptionWidth = MetricGetID(pProfileUserName,STR_CAPTIONWIDTH, 18 );
|
|
nc.iCaptionHeight = MetricGetID(pProfileUserName,STR_CAPTIONHEIGHT, 18 );
|
|
nc.iSmCaptionWidth = MetricGetID(pProfileUserName,STR_SMCAPTIONWIDTH, 13 );
|
|
nc.iSmCaptionHeight = MetricGetID(pProfileUserName,STR_SMCAPTIONHEIGHT, 13 );
|
|
nc.iMenuWidth = MetricGetID(pProfileUserName,STR_MENUWIDTH, 18 );
|
|
nc.iMenuHeight = MetricGetID(pProfileUserName,STR_MENUHEIGHT, 18 );
|
|
|
|
lpnc = &nc;
|
|
}
|
|
|
|
/*
|
|
* SANITY CHECK for metric values
|
|
*/
|
|
cxEdge4 = 4 * SYSMET(CXEDGE);
|
|
|
|
/*
|
|
* Border
|
|
*/
|
|
lpnc->iBorderWidth = max(lpnc->iBorderWidth, 1);
|
|
lpnc->iBorderWidth = min(lpnc->iBorderWidth, 50);
|
|
|
|
/*
|
|
* Scrollbar
|
|
*/
|
|
lpnc->iScrollWidth = max(lpnc->iScrollWidth, cxEdge4);
|
|
lpnc->iScrollHeight = max(lpnc->iScrollHeight, 4 * SYSMET(CYEDGE));
|
|
|
|
/*
|
|
* Caption -- Buttons must be wide enough to draw edges, and text
|
|
* area must be tall enough to fit caption font with a border above
|
|
* and below. If we have to reset the caption height, should we
|
|
* reset the button width as well?
|
|
*/
|
|
lpnc->iCaptionWidth = max(lpnc->iCaptionWidth, cxEdge4);
|
|
lpnc->iCaptionHeight = max(lpnc->iCaptionHeight, gcyCaptionFontChar + SYSMET(CYEDGE));
|
|
|
|
/*
|
|
* Small caption -- Buttons must be wide enough to draw edges, and
|
|
* text area must be tall enough to fit small caption font with a
|
|
* border above and below. Again, if we have to reset the height,
|
|
* reset the width as well?
|
|
*/
|
|
lpnc->iSmCaptionWidth = max(lpnc->iSmCaptionWidth, cxEdge4);
|
|
lpnc->iSmCaptionHeight = max(lpnc->iSmCaptionHeight, gcySmCaptionFontChar + SYSMET(CYEDGE));
|
|
|
|
/*
|
|
* Menu -- Buttons must be wide enough to draw edges, and text
|
|
* area must be tall enough to fit menu font with underscore.
|
|
*/
|
|
lpnc->iMenuWidth = max(lpnc->iMenuWidth, cxEdge4);
|
|
lpnc->iMenuHeight = max(lpnc->iMenuHeight, gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYEDGE));
|
|
|
|
/*
|
|
* SET UP SYSTEM METRIC VALUES
|
|
*/
|
|
SetNCMetrics(lpnc);
|
|
}
|
|
|
|
if (!CreateBitmapStrip()) {
|
|
RIPMSG0(RIP_WARNING, "CreateBitmapStrip failed");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID SetMinMetrics(
|
|
PUNICODE_STRING pProfileUserName,
|
|
LPMINIMIZEDMETRICS lpmin)
|
|
{
|
|
MINIMIZEDMETRICS min;
|
|
|
|
if (!lpmin) {
|
|
|
|
/*
|
|
* Minimized
|
|
*/
|
|
min.iWidth = MetricGetID(pProfileUserName,STR_MINWIDTH, 154);
|
|
min.iHorzGap = MetricGetID(pProfileUserName,STR_MINHORZGAP, 0);
|
|
min.iVertGap = MetricGetID(pProfileUserName,STR_MINVERTGAP, 0);
|
|
min.iArrange = MetricGetID(pProfileUserName,STR_MINARRANGE, ARW_BOTTOMLEFT | ARW_RIGHT);
|
|
lpmin = &min;
|
|
}
|
|
|
|
/*
|
|
* SANITY CHECK for metric values
|
|
*/
|
|
|
|
/*
|
|
* Minimized window -- Text area must be >= 0, as must gap between
|
|
* windows horizontally and vertically.
|
|
*/
|
|
lpmin->iWidth = max(lpmin->iWidth, 0);
|
|
lpmin->iHorzGap = max(lpmin->iHorzGap, 0);
|
|
lpmin->iVertGap = max(lpmin->iVertGap, 0);
|
|
lpmin->iArrange &= ARW_VALID;
|
|
|
|
/*
|
|
* Minimized size
|
|
*/
|
|
SYSMET(CXMINIMIZED) = 2*SYSMET(CXFIXEDFRAME) + (int) lpmin->iWidth;
|
|
SYSMET(CYMINIMIZED) = 2*SYSMET(CYFIXEDFRAME) + SYSMET(CYSIZE);
|
|
|
|
SYSMET(CXMINSPACING) = SYSMET(CXMINIMIZED) + (int) lpmin->iHorzGap;
|
|
SYSMET(CYMINSPACING) = SYSMET(CYMINIMIZED) + (int) lpmin->iVertGap;
|
|
|
|
SYSMET(ARRANGE) = (int) lpmin->iArrange;
|
|
}
|
|
|
|
BOOL SetIconMetrics(
|
|
PUNICODE_STRING pProfileUserName,
|
|
LPICONMETRICS lpicon)
|
|
{
|
|
ICONMETRICS icon;
|
|
|
|
if (!SetIconFonts(pProfileUserName,lpicon)) {
|
|
RIPMSG0(RIP_WARNING, "SetIconMetrics failed in SetIconFonts");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!lpicon) {
|
|
|
|
icon.iTitleWrap = MetricGetID(pProfileUserName,
|
|
STR_ICONTITLEWRAP, TRUE);
|
|
|
|
icon.iHorzSpacing = MetricGetID(pProfileUserName,
|
|
STR_ICONHORZSPACING,
|
|
(GreGetDeviceCaps(HDCBITS(), LOGPIXELSX) * 75) / 96);
|
|
|
|
icon.iVertSpacing = MetricGetID(pProfileUserName,
|
|
STR_ICONVERTSPACING,
|
|
(GreGetDeviceCaps(HDCBITS(), LOGPIXELSY) * 75) / 96);
|
|
|
|
lpicon = &icon;
|
|
}
|
|
|
|
/*
|
|
* SANITY CHECK for metric values
|
|
*/
|
|
lpicon->iHorzSpacing = max(lpicon->iHorzSpacing, (int)SYSMET(CXICON));
|
|
lpicon->iVertSpacing = max(lpicon->iVertSpacing, (int)SYSMET(CYICON));
|
|
|
|
SYSMET(CXICONSPACING) = (int) lpicon->iHorzSpacing;
|
|
SYSMET(CYICONSPACING) = (int) lpicon->iVertSpacing;
|
|
SET_OR_CLEAR_PUDF(PUDF_ICONTITLEWRAP, lpicon->iTitleWrap);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxMB_FindLongestString
|
|
*
|
|
* History:
|
|
* 10-23-90 DarrinM Ported from Win 3.0 sources.
|
|
* 01-21-98 SamerA Renamed to xxx since it may leave the crit sec if
|
|
* a client LPK is installed.
|
|
\***************************************************************************/
|
|
|
|
UINT xxxMB_FindLongestString(HDC hdc)
|
|
{
|
|
UINT wRetVal;
|
|
int i, iMaxLen = 0, iNewMaxLen;
|
|
LPWSTR pszCurStr, szMaxStr;
|
|
SIZE sizeOneChar;
|
|
SIZE sizeMaxStr;
|
|
PTHREADINFO ptiCurrent = PtiCurrentShared();
|
|
|
|
/*
|
|
* Be sure that MBStrings are already loaded.
|
|
*/
|
|
UserAssert(gpsi->MBStrings[0].szName[0] != TEXT('\0'));
|
|
|
|
/*
|
|
* We are assuming that the longest string is the widest one,
|
|
* which is not always true.
|
|
* What we really have to do is call PSMGetTextExtent for each string
|
|
* and get the max width.
|
|
* This behavior get rectified by workaround for bug #170582
|
|
* in CheckMsgFontDimensions(). Mhamid.
|
|
*/
|
|
|
|
|
|
for (i = 0; i < MAX_SEB_STYLES; i++) {
|
|
pszCurStr = GETGPSIMBPSTR(i);
|
|
if ((iNewMaxLen = wcslen(pszCurStr)) > iMaxLen) {
|
|
iMaxLen = iNewMaxLen;
|
|
szMaxStr = pszCurStr;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Find the longest string
|
|
*/
|
|
if (CALL_LPK(ptiCurrent)) {
|
|
xxxClientGetTextExtentPointW(hdc, (PWSTR)szOneChar, 1, &sizeOneChar);
|
|
} else {
|
|
GreGetTextExtentW(hdc, (PWSTR)szOneChar, 1, &sizeOneChar, GGTE_WIN3_EXTENT);
|
|
}
|
|
xxxPSMGetTextExtent(hdc, szMaxStr, iMaxLen, &sizeMaxStr);
|
|
wRetVal = (UINT)(sizeMaxStr.cx + (sizeOneChar.cx * 2));
|
|
|
|
return wRetVal;
|
|
}
|