Source code of Windows XP (NT5)
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.

356 lines
13 KiB

  1. /* ICONS.C
  2. Resident Code Segment // Tweak: make non-resident?
  3. Initing and painting icons in preview sample
  4. Frosting: Master Theme Selector for Windows '95
  5. Copyright (c) 1994-1998 Microsoft Corporation. All rights reserved.
  6. */
  7. // ---------------------------------------------
  8. // Brief file history:
  9. // Alpha:
  10. // Beta:
  11. // Bug fixes
  12. // ---------
  13. #include "windows.h"
  14. #include "stdlib.h"
  15. #include "frost.h"
  16. #include "global.h"
  17. #include "schedule.h" // IsPlatformNT()
  18. #include "nc.h"
  19. extern int FAR WriteBytesToBuffer(LPTSTR);
  20. #define ICONSIZE 32
  21. #define NUM_ICONS 4
  22. #define MYDOC_INDEX 3 // Index to MyDocs icon subkey in fsRoot & fsCUIcons
  23. // Keep in sync with KEYS.H!!
  24. POINT ptIconOrigin[NUM_ICONS];
  25. RECT rLabels[NUM_ICONS];
  26. TCHAR szLabelText[NUM_ICONS][MAX_STRLEN+1];
  27. #define bThemed (*lpszThemeFile)
  28. BOOL FAR PASCAL IconsPreviewInit(void)
  29. {
  30. int xOrg, iter;
  31. // icons are centered, evenly spaced, in the icon rectangle in the RC file
  32. // you can get x origins of icons from the icon area rect
  33. xOrg = rPreviewIcons.left + (rPreviewIcons.right - rPreviewIcons.left -
  34. ICONSIZE) / 2;
  35. for (iter = 0; iter < NUM_ICONS; iter++) {
  36. ptIconOrigin[iter].x = xOrg;
  37. }
  38. // y origins depend on font height in theme
  39. // load icon label texts
  40. for (iter = 0; iter < NUM_ICONS; iter++) {
  41. LoadString(hInstApp, STR_MYCOMPUTER+iter, (LPTSTR)(szLabelText[iter]), MAX_STRLEN);
  42. }
  43. return (TRUE);
  44. }
  45. void FAR PASCAL IconsPreviewDestroy(void)
  46. {
  47. }
  48. void FAR PASCAL IconsPreviewDraw(HDC hdcDraw, LPTSTR lpszThemeFile)
  49. {
  50. UINT uret;
  51. ICONMETRICS imTheme;
  52. extern TCHAR szMetrics[];
  53. extern TCHAR szIM[];
  54. HFONT hIconFont, hOldFont;
  55. HICON hTempIcon;
  56. TEXTMETRIC tmLabel;
  57. int yLabel, yCushion, yIconSpacing;
  58. int iter, iTemp;
  59. int index;
  60. extern FROST_SUBKEY fsRoot[]; // Win95/Plus95 icon keys
  61. extern FROST_SUBKEY fsCUIcons[]; // Win98/Plus98 icon keys
  62. extern TCHAR c_szSoftwareClassesFmt[]; // WinNT reg path from keys.h
  63. LPTSTR lpszIndex;
  64. SIZE sizeText;
  65. COLORREF rgbLabel, rgbLabelText, rgbOldText;
  66. HBRUSH hbrLabel;
  67. TCHAR szNTReg[MAX_PATH];
  68. #ifdef UNICODE
  69. CHAR szTempA[10];
  70. #endif
  71. //
  72. // Inits
  73. //
  74. // Get the icon font; use it to figure y positions of icons and labels;
  75. // setup DC with font; get lable brush/text color.
  76. //
  77. //
  78. // get the icon font
  79. // first get the iconmetrics struct
  80. // if (bThemed && bCBStates[FC_ICONS]) { // icon fonts go with icons cb, not fonts
  81. if (bThemed && bCBStates[FC_FONTS]) { // icon fonts go with _fonts_ now !!!!
  82. uret = (UINT) GetPrivateProfileString((LPTSTR)szMetrics, (LPTSTR)szIM,
  83. (LPTSTR)szNULL,
  84. (LPTSTR)pValue, MAX_VALUELEN,
  85. lpszThemeFile);
  86. Assert(uret, TEXT("problem getting stored icon metrics for icon preview draw\n"));
  87. // translate stored data string to ICONMETRICS bytes
  88. WriteBytesToBuffer((LPTSTR)pValue); // char str read from and binary bytes
  89. // written to pValue. It's OK.
  90. // get it into global ICONMETRICS struct
  91. #ifdef UNICODE
  92. // ICONMETRICS are stored in ANSI format in the Theme file so we
  93. // need to convert to UNICODE
  94. ConvertIconMetricsToWIDE((LPICONMETRICSA)pValue, (LPICONMETRICSW)&imTheme);
  95. #else
  96. // Not UNICODE so no need to convert...
  97. imTheme = *((LPICONMETRICS)pValue);
  98. #endif
  99. }
  100. else {
  101. imTheme.cbSize = sizeof(imTheme);
  102. SystemParametersInfo(SPI_GETICONMETRICS, sizeof(imTheme),
  103. (void far *)(LPICONMETRICS)&imTheme, FALSE);
  104. }
  105. // then create the font
  106. hIconFont = CreateFontIndirect(&imTheme.lfFont);
  107. // and use it in this DC
  108. if (hIconFont)
  109. hOldFont = SelectObject(hdcDraw, hIconFont);
  110. //
  111. // now that we have the font, we can get the y origins for the icons
  112. // and the y extremities of the text labels
  113. // figure label height
  114. GetTextMetrics(hdcDraw, &tmLabel);
  115. // yLabel = (tmLabel.tmHeight*13)/9; // very good estimate; else try 11/9
  116. yLabel = tmLabel.tmHeight; // no, just text height will do
  117. // and cushion between bottom of icons and their labels
  118. yCushion = (yLabel*4)/13; // pretty good guess
  119. // icons are centered, evenly spaced, in the icon rectangle in the RC file
  120. yIconSpacing = ( rPreviewIcons.bottom - rPreviewIcons.top
  121. - NUM_ICONS * (yLabel + yCushion + ICONSIZE) ) / NUM_ICONS;
  122. Assert(yIconSpacing > 0, TEXT("neg yIconSpacing implies icon preview rect too short\n"));
  123. ptIconOrigin[0].y = rPreviewIcons.top + yIconSpacing/2;
  124. for (iter = 1; iter < NUM_ICONS; iter ++) {
  125. ptIconOrigin[iter].y = ptIconOrigin[iter-1].y +
  126. ICONSIZE + yCushion + yLabel + yIconSpacing;
  127. }
  128. // labels are where you now expect them
  129. for (iter = 0; iter < NUM_ICONS; iter ++) {
  130. rLabels[iter].top = ptIconOrigin[iter].y + ICONSIZE + yCushion;
  131. rLabels[iter].bottom = rLabels[iter].top + yLabel;
  132. }
  133. //
  134. // final init involves colors (and brush) for labels and label text
  135. // get desktop background color
  136. if (bThemed && bCBStates[FC_COLORS]) { // getting from selected theme
  137. GetPrivateProfileString((LPTSTR)TEXT("Control Panel\\Colors"),
  138. (LPTSTR)TEXT("Background"),
  139. (LPTSTR)szNULL,
  140. (LPTSTR)szMsg, MAX_MSGLEN,
  141. lpszThemeFile);
  142. // translate to color
  143. rgbLabel = RGBStringToColor((LPTSTR)szMsg);
  144. }
  145. else // using cur windows settings
  146. rgbLabel = GetSysColor(COLOR_BACKGROUND);
  147. // then make that the nearest solid color for label background
  148. rgbLabel = GetNearestColor(hdcDraw, rgbLabel);
  149. // now use a HACK HACK HACK HACK brilliant method for getting text color
  150. if ((GetRValue(rgbLabel) > 128) ||
  151. (GetGValue(rgbLabel) > 128) ||
  152. (GetBValue(rgbLabel) > 128) )
  153. rgbLabelText = RGB(0,0,0); // black text on lighter label
  154. else
  155. rgbLabelText = RGB(255,255,255); // white text on darker label
  156. // and then create the background brush and set the text color
  157. hbrLabel = CreateSolidBrush(rgbLabel);
  158. rgbOldText = SetTextColor(hdcDraw, rgbLabelText);
  159. SetBkMode(hdcDraw, TRANSPARENT);
  160. //
  161. // now we can get each of the icons and draw them at the right spot
  162. // and while you're at it draw the labels
  163. for (iter = 0; iter < NUM_ICONS; iter ++) {
  164. // first get filename into temp global buffer szMsg
  165. if (bThemed && bCBStates[FC_ICONS]) { // getting from selected theme
  166. GetPrivateProfileString((LPTSTR)fsCUIcons[iter].szSubKey,
  167. // SPECIAL UGLY CASE FOR TRASH CAN
  168. (LPTSTR)(iter == 2 ? TEXT("full") : FROST_DEFSTR),
  169. (LPTSTR)szNULL,
  170. (LPTSTR)szMsg, MAX_MSGLEN,
  171. lpszThemeFile);
  172. // If the key is null we might have an "old" Plus95 *.Theme file
  173. // so let's use the Win95 keyname instead
  174. if (!*szMsg) {
  175. GetPrivateProfileString((LPTSTR)fsRoot[iter].szSubKey,
  176. // SPECIAL UGLY CASE FOR TRASH CAN
  177. (LPTSTR)(iter == 2 ? TEXT("full") : FROST_DEFSTR),
  178. (LPTSTR)szNULL,
  179. (LPTSTR)szMsg, MAX_MSGLEN,
  180. lpszThemeFile);
  181. }
  182. // PLUS98 bug 1042
  183. // If this is the MyDocs icon and there is no setting for
  184. // it in the Theme file then we need to default to the
  185. // szMyDocsDefault icon.
  186. if ((MYDOC_INDEX == iter) && (!*szMsg)) {
  187. lstrcpy(szMsg, MYDOC_DEFSTR);
  188. }
  189. // expand filename string as necessary
  190. InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
  191. // search for file if necessary, see if found
  192. // ConfirmFile on NULL string returns "CF_EXISTS" so have
  193. // added "|| !*szMsg" case to this conditional to check for it
  194. if ((ConfirmFile((LPTSTR)szMsg, TRUE) == CF_NOTFOUND) || !*szMsg) {
  195. // if file not found, nothing applied --> keeps cur sys setting
  196. szMsg[0] = TEXT('\0');
  197. HandGet(HKEY_CURRENT_USER,
  198. (LPTSTR)fsCUIcons[iter].szSubKey,
  199. // SPECIAL UGLY CASE FOR TRASH CAN
  200. (LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
  201. // null gives default string
  202. (LPTSTR)szMsg);
  203. // If we failed to get a string from the CURRENT_USER branch
  204. // go try the CLASSES_ROOT branch instead.
  205. if (!*szMsg) {
  206. HandGet(HKEY_CLASSES_ROOT,
  207. (LPTSTR)fsRoot[iter].szSubKey,
  208. // SPECIAL UGLY CASE FOR TRASH CAN
  209. (LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
  210. // null gives default string
  211. (LPTSTR)szMsg);
  212. }
  213. }
  214. }
  215. else { // using cur windows settings
  216. // First try getting the icon from the appropriate
  217. // CURRENT_USER branch for this platform
  218. szMsg[0] = TEXT('\0');
  219. if (IsPlatformNT())
  220. {
  221. lstrcpy(szNTReg, c_szSoftwareClassesFmt);
  222. lstrcat(szNTReg, fsRoot[iter].szSubKey);
  223. HandGet(HKEY_CURRENT_USER,
  224. (LPTSTR)szNTReg,
  225. // SPECIAL UGLY CASE FOR TRASH CAN
  226. (LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
  227. // null gives default string
  228. (LPTSTR)szMsg);
  229. }
  230. else // not NT
  231. {
  232. HandGet(HKEY_CURRENT_USER,
  233. (LPTSTR)fsCUIcons[iter].szSubKey,
  234. // SPECIAL UGLY CASE FOR TRASH CAN
  235. (LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
  236. // null gives default string
  237. (LPTSTR)szMsg);
  238. }
  239. // If we got a NULL string from the CURRENT_USER branch then
  240. // try the CLASSES_ROOT branch instead
  241. if (!*szMsg) {
  242. HandGet(HKEY_CLASSES_ROOT,
  243. (LPTSTR)fsRoot[iter].szSubKey,
  244. // SPECIAL UGLY CASE FOR TRASH CAN
  245. (LPTSTR)(iter == 2 ? TEXT("full") : szNULL),
  246. // null gives default string
  247. (LPTSTR)szMsg);
  248. }
  249. }
  250. // now load the icon; may have index into file. format: "file,index"
  251. lpszIndex = FindChar((LPTSTR)szMsg, TEXT(','));
  252. if (*lpszIndex) { // if found a comma, then indexed icon
  253. #ifdef UNICODE
  254. // latoi doesn't like wide strings -- convert to ANSI before calling
  255. wcstombs(szTempA, CharNext(lpszIndex), sizeof(szTempA));
  256. index = latoi(szTempA);
  257. #else
  258. index = latoi(CharNext(lpszIndex));
  259. #endif
  260. *lpszIndex = 0; // got index then null term filename in szMsg
  261. }
  262. else { // just straight icon file or no index
  263. index = 0;
  264. }
  265. // Get proper res ICON from file
  266. ExtractPlusColorIcon(szMsg, index, &hTempIcon, 0, 0);
  267. // draw the icon at the right spot
  268. if (hTempIcon)
  269. DrawIconEx(hdcDraw, ptIconOrigin[iter].x, ptIconOrigin[iter].y,
  270. hTempIcon, ICONSIZE, ICONSIZE, 0, NULL, DI_NORMAL);
  271. // figure the label width for the font and text string
  272. GetTextExtentPoint32(hdcDraw, (LPTSTR)(szLabelText[iter]),
  273. lstrlen((LPTSTR)(szLabelText[iter])),
  274. (LPSIZE)&sizeText);
  275. iTemp = (rPreviewIcons.right - rPreviewIcons.left - (int)(sizeText.cx)) / 2;
  276. rLabels[iter].left = rPreviewIcons.left + iTemp
  277. - (yLabel*3)/13; // very good estimate
  278. rLabels[iter].right = rPreviewIcons.right - iTemp
  279. + (yLabel*3)/13; // very good estimate
  280. // draw label background in solid color version of dt bkgd color
  281. FillRect(hdcDraw, (LPRECT)&(rLabels[iter]), hbrLabel);
  282. // draw actual text string there, too
  283. DrawText(hdcDraw, (LPTSTR)(szLabelText[iter]),
  284. lstrlen((LPTSTR)(szLabelText[iter])),
  285. (LPRECT)&(rLabels[iter]),
  286. DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE
  287. );
  288. // individual icon draw Cleanup
  289. if (hTempIcon)
  290. DestroyIcon(hTempIcon);
  291. }
  292. //
  293. // cleanup
  294. if (hbrLabel) DeleteObject(hbrLabel);
  295. if (rgbOldText != CLR_INVALID) SetTextColor(hdcDraw, rgbOldText);
  296. if (hIconFont) {
  297. SelectObject(hdcDraw, hOldFont);
  298. DeleteObject(hIconFont);
  299. }
  300. }