Leaked source code of windows server 2003
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

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