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