windows-nt/Source/XPSP1/NT/shell/osshell/themes/themesw/icons.c
2020-09-26 16:20:57 +08:00

357 lines
13 KiB
C

/* ICONS.C
Resident Code Segment // Tweak: make non-resident?
Initing and painting icons in preview sample
Frosting: Master Theme Selector for Windows '95
Copyright (c) 1994-1998 Microsoft Corporation. All rights reserved.
*/
// ---------------------------------------------
// Brief file history:
// Alpha:
// Beta:
// Bug fixes
// ---------
#include "windows.h"
#include "stdlib.h"
#include "frost.h"
#include "global.h"
#include "schedule.h" // IsPlatformNT()
#include "nc.h"
extern int FAR WriteBytesToBuffer(LPTSTR);
#define ICONSIZE 32
#define NUM_ICONS 4
#define MYDOC_INDEX 3 // Index to MyDocs icon subkey in fsRoot & fsCUIcons
// Keep in sync with KEYS.H!!
POINT ptIconOrigin[NUM_ICONS];
RECT rLabels[NUM_ICONS];
TCHAR szLabelText[NUM_ICONS][MAX_STRLEN+1];
#define bThemed (*lpszThemeFile)
BOOL FAR PASCAL IconsPreviewInit(void)
{
int xOrg, iter;
// icons are centered, evenly spaced, in the icon rectangle in the RC file
// you can get x origins of icons from the icon area rect
xOrg = rPreviewIcons.left + (rPreviewIcons.right - rPreviewIcons.left -
ICONSIZE) / 2;
for (iter = 0; iter < NUM_ICONS; iter++) {
ptIconOrigin[iter].x = xOrg;
}
// y origins depend on font height in theme
// load icon label texts
for (iter = 0; iter < NUM_ICONS; iter++) {
LoadString(hInstApp, STR_MYCOMPUTER+iter, (LPTSTR)(szLabelText[iter]), MAX_STRLEN);
}
return (TRUE);
}
void FAR PASCAL IconsPreviewDestroy(void)
{
}
void FAR PASCAL IconsPreviewDraw(HDC hdcDraw, LPTSTR lpszThemeFile)
{
UINT uret;
ICONMETRICS imTheme;
extern TCHAR szMetrics[];
extern TCHAR szIM[];
HFONT hIconFont, hOldFont;
HICON hTempIcon;
TEXTMETRIC tmLabel;
int yLabel, yCushion, yIconSpacing;
int iter, iTemp;
int index;
extern FROST_SUBKEY fsRoot[]; // Win95/Plus95 icon keys
extern FROST_SUBKEY fsCUIcons[]; // Win98/Plus98 icon keys
extern TCHAR c_szSoftwareClassesFmt[]; // WinNT reg path from keys.h
LPTSTR lpszIndex;
SIZE sizeText;
COLORREF rgbLabel, rgbLabelText, rgbOldText;
HBRUSH hbrLabel;
TCHAR szNTReg[MAX_PATH];
#ifdef UNICODE
CHAR szTempA[10];
#endif
//
// Inits
//
// Get the icon font; use it to figure y positions of icons and labels;
// setup DC with font; get lable brush/text color.
//
//
// get the icon font
// first get the iconmetrics struct
// if (bThemed && bCBStates[FC_ICONS]) { // icon fonts go with icons cb, not fonts
if (bThemed && bCBStates[FC_FONTS]) { // icon fonts go with _fonts_ now !!!!
uret = (UINT) GetPrivateProfileString((LPTSTR)szMetrics, (LPTSTR)szIM,
(LPTSTR)szNULL,
(LPTSTR)pValue, MAX_VALUELEN,
lpszThemeFile);
Assert(uret, TEXT("problem getting stored icon metrics for icon preview draw\n"));
// translate stored data string to ICONMETRICS bytes
WriteBytesToBuffer((LPTSTR)pValue); // char str read from and binary bytes
// written to pValue. It's OK.
// get it into global ICONMETRICS struct
#ifdef UNICODE
// ICONMETRICS are stored in ANSI format in the Theme file so we
// need to convert to UNICODE
ConvertIconMetricsToWIDE((LPICONMETRICSA)pValue, (LPICONMETRICSW)&imTheme);
#else
// Not UNICODE so no need to convert...
imTheme = *((LPICONMETRICS)pValue);
#endif
}
else {
imTheme.cbSize = sizeof(imTheme);
SystemParametersInfo(SPI_GETICONMETRICS, sizeof(imTheme),
(void far *)(LPICONMETRICS)&imTheme, FALSE);
}
// then create the font
hIconFont = CreateFontIndirect(&imTheme.lfFont);
// and use it in this DC
if (hIconFont)
hOldFont = SelectObject(hdcDraw, hIconFont);
//
// now that we have the font, we can get the y origins for the icons
// and the y extremities of the text labels
// figure label height
GetTextMetrics(hdcDraw, &tmLabel);
// yLabel = (tmLabel.tmHeight*13)/9; // very good estimate; else try 11/9
yLabel = tmLabel.tmHeight; // no, just text height will do
// and cushion between bottom of icons and their labels
yCushion = (yLabel*4)/13; // pretty good guess
// icons are centered, evenly spaced, in the icon rectangle in the RC file
yIconSpacing = ( rPreviewIcons.bottom - rPreviewIcons.top
- NUM_ICONS * (yLabel + yCushion + ICONSIZE) ) / NUM_ICONS;
Assert(yIconSpacing > 0, TEXT("neg yIconSpacing implies icon preview rect too short\n"));
ptIconOrigin[0].y = rPreviewIcons.top + yIconSpacing/2;
for (iter = 1; iter < NUM_ICONS; iter ++) {
ptIconOrigin[iter].y = ptIconOrigin[iter-1].y +
ICONSIZE + yCushion + yLabel + yIconSpacing;
}
// labels are where you now expect them
for (iter = 0; iter < NUM_ICONS; iter ++) {
rLabels[iter].top = ptIconOrigin[iter].y + ICONSIZE + yCushion;
rLabels[iter].bottom = rLabels[iter].top + yLabel;
}
//
// final init involves colors (and brush) for labels and label text
// get desktop background color
if (bThemed && bCBStates[FC_COLORS]) { // getting from selected theme
GetPrivateProfileString((LPTSTR)TEXT("Control Panel\\Colors"),
(LPTSTR)TEXT("Background"),
(LPTSTR)szNULL,
(LPTSTR)szMsg, MAX_MSGLEN,
lpszThemeFile);
// translate to color
rgbLabel = RGBStringToColor((LPTSTR)szMsg);
}
else // using cur windows settings
rgbLabel = GetSysColor(COLOR_BACKGROUND);
// then make that the nearest solid color for label background
rgbLabel = GetNearestColor(hdcDraw, rgbLabel);
// now use a HACK HACK HACK HACK brilliant method for getting text color
if ((GetRValue(rgbLabel) > 128) ||
(GetGValue(rgbLabel) > 128) ||
(GetBValue(rgbLabel) > 128) )
rgbLabelText = RGB(0,0,0); // black text on lighter label
else
rgbLabelText = RGB(255,255,255); // white text on darker label
// and then create the background brush and set the text color
hbrLabel = CreateSolidBrush(rgbLabel);
rgbOldText = SetTextColor(hdcDraw, rgbLabelText);
SetBkMode(hdcDraw, TRANSPARENT);
//
// now we can get each of the icons and draw them at the right spot
// and while you're at it draw the labels
for (iter = 0; iter < NUM_ICONS; iter ++) {
// first get filename into temp global buffer szMsg
if (bThemed && bCBStates[FC_ICONS]) { // getting from selected theme
GetPrivateProfileString((LPTSTR)fsCUIcons[iter].szSubKey,
// SPECIAL UGLY CASE FOR TRASH CAN
(LPTSTR)(iter == 2 ? TEXT("full") : FROST_DEFSTR),
(LPTSTR)szNULL,
(LPTSTR)szMsg, MAX_MSGLEN,
lpszThemeFile);
// If the key is null we might have an "old" Plus95 *.Theme file
// so let's use the Win95 keyname instead
if (!*szMsg) {
GetPrivateProfileString((LPTSTR)fsRoot[iter].szSubKey,
// SPECIAL UGLY CASE FOR TRASH CAN
(LPTSTR)(iter == 2 ? TEXT("full") : FROST_DEFSTR),
(LPTSTR)szNULL,
(LPTSTR)szMsg, MAX_MSGLEN,
lpszThemeFile);
}
// PLUS98 bug 1042
// If this is the MyDocs icon and there is no setting for
// it in the Theme file then we need to default to the
// szMyDocsDefault icon.
if ((MYDOC_INDEX == iter) && (!*szMsg)) {
lstrcpy(szMsg, MYDOC_DEFSTR);
}
// expand filename string as necessary
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
// search for file if necessary, see if found
// ConfirmFile on NULL string returns "CF_EXISTS" so have
// added "|| !*szMsg" case to this conditional to check for it
if ((ConfirmFile((LPTSTR)szMsg, TRUE) == CF_NOTFOUND) || !*szMsg) {
// if file not found, nothing applied --> keeps cur sys setting
szMsg[0] = TEXT('\0');
HandGet(HKEY_CURRENT_USER,
(LPTSTR)fsCUIcons[iter].szSubKey,
// SPECIAL UGLY CASE FOR TRASH CAN
(LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
// null gives default string
(LPTSTR)szMsg);
// If we failed to get a string from the CURRENT_USER branch
// go try the CLASSES_ROOT branch instead.
if (!*szMsg) {
HandGet(HKEY_CLASSES_ROOT,
(LPTSTR)fsRoot[iter].szSubKey,
// SPECIAL UGLY CASE FOR TRASH CAN
(LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
// null gives default string
(LPTSTR)szMsg);
}
}
}
else { // using cur windows settings
// First try getting the icon from the appropriate
// CURRENT_USER branch for this platform
szMsg[0] = TEXT('\0');
if (IsPlatformNT())
{
lstrcpy(szNTReg, c_szSoftwareClassesFmt);
lstrcat(szNTReg, fsRoot[iter].szSubKey);
HandGet(HKEY_CURRENT_USER,
(LPTSTR)szNTReg,
// SPECIAL UGLY CASE FOR TRASH CAN
(LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
// null gives default string
(LPTSTR)szMsg);
}
else // not NT
{
HandGet(HKEY_CURRENT_USER,
(LPTSTR)fsCUIcons[iter].szSubKey,
// SPECIAL UGLY CASE FOR TRASH CAN
(LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
// null gives default string
(LPTSTR)szMsg);
}
// If we got a NULL string from the CURRENT_USER branch then
// try the CLASSES_ROOT branch instead
if (!*szMsg) {
HandGet(HKEY_CLASSES_ROOT,
(LPTSTR)fsRoot[iter].szSubKey,
// SPECIAL UGLY CASE FOR TRASH CAN
(LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
// null gives default string
(LPTSTR)szMsg);
}
}
// now load the icon; may have index into file. format: "file,index"
lpszIndex = FindChar((LPTSTR)szMsg, TEXT(','));
if (*lpszIndex) { // if found a comma, then indexed icon
#ifdef UNICODE
// latoi doesn't like wide strings -- convert to ANSI before calling
wcstombs(szTempA, CharNext(lpszIndex), sizeof(szTempA));
index = latoi(szTempA);
#else
index = latoi(CharNext(lpszIndex));
#endif
*lpszIndex = 0; // got index then null term filename in szMsg
}
else { // just straight icon file or no index
index = 0;
}
// Get proper res ICON from file
ExtractPlusColorIcon(szMsg, index, &hTempIcon, 0, 0);
// draw the icon at the right spot
if (hTempIcon)
DrawIconEx(hdcDraw, ptIconOrigin[iter].x, ptIconOrigin[iter].y,
hTempIcon, ICONSIZE, ICONSIZE, 0, NULL, DI_NORMAL);
// figure the label width for the font and text string
GetTextExtentPoint32(hdcDraw, (LPTSTR)(szLabelText[iter]),
lstrlen((LPTSTR)(szLabelText[iter])),
(LPSIZE)&sizeText);
iTemp = (rPreviewIcons.right - rPreviewIcons.left - (int)(sizeText.cx)) / 2;
rLabels[iter].left = rPreviewIcons.left + iTemp
- (yLabel*3)/13; // very good estimate
rLabels[iter].right = rPreviewIcons.right - iTemp
+ (yLabel*3)/13; // very good estimate
// draw label background in solid color version of dt bkgd color
FillRect(hdcDraw, (LPRECT)&(rLabels[iter]), hbrLabel);
// draw actual text string there, too
DrawText(hdcDraw, (LPTSTR)(szLabelText[iter]),
lstrlen((LPTSTR)(szLabelText[iter])),
(LPRECT)&(rLabels[iter]),
DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE
);
// individual icon draw Cleanup
if (hTempIcon)
DestroyIcon(hTempIcon);
}
//
// cleanup
if (hbrLabel) DeleteObject(hbrLabel);
if (rgbOldText != CLR_INVALID) SetTextColor(hdcDraw, rgbOldText);
if (hIconFont) {
SelectObject(hdcDraw, hOldFont);
DeleteObject(hIconFont);
}
}