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

  1. /***************************************************************************\
  2. *
  3. * INCTLPAN.C
  4. *
  5. * Copyright (c) 1985 - 1999, Microsoft Corporation
  6. *
  7. * Init Routines which are also used by Control Panel
  8. *
  9. * -- Scalable Window Frame Support
  10. *
  11. * exports from this module:
  12. * > xxxSetWindowNCMetrics -- called by LoadWindows & SystemParametersInfo
  13. *
  14. \***************************************************************************/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. __inline int
  18. MetricGetID(
  19. PUNICODE_STRING pProfileUserName,
  20. UINT idStr,
  21. int defValue
  22. )
  23. {
  24. int iRet;
  25. FastGetProfileIntFromID(
  26. pProfileUserName, PMAP_METRICS, idStr, defValue, &iRet, 0);
  27. return iRet;
  28. }
  29. static CONST WORD sysBmpStyles[OBI_COUNT][2] = {
  30. DFC_CAPTION, DFCS_CAPTIONCLOSE, // OBI_CLOSE
  31. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_PUSHED, // OBI_CLOSE_D
  32. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_HOT, // OBI_CLOSE_H
  33. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INACTIVE, // OBI_CLOSE_I
  34. DFC_CAPTION, DFCS_CAPTIONMIN, // OBI_REDUCE
  35. DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_PUSHED, // OBI_REDUCE_D
  36. DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_HOT, // OBI_REDUCE_H
  37. DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INACTIVE, // OBI_REDUCE_I
  38. DFC_CAPTION, DFCS_CAPTIONRESTORE, // OBI_RESTORE
  39. DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_PUSHED, // OBI_RESTORE_D
  40. DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_HOT, // OBI_RESTORE_H
  41. DFC_CAPTION, DFCS_CAPTIONHELP, // OBI_HELP
  42. DFC_CAPTION, DFCS_CAPTIONHELP | DFCS_PUSHED, // OBI_HELP_D
  43. DFC_CAPTION, DFCS_CAPTIONHELP | DFCS_HOT, // OBI_HELP_H
  44. DFC_CAPTION, DFCS_CAPTIONMAX, // OBI_ZOOM
  45. DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_PUSHED, // OBI_ZOOM_D
  46. DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_HOT, // OBI_ZOOM_H
  47. DFC_CAPTION, DFCS_CAPTIONMAX | DFCS_INACTIVE, // OBI_ZOOM_I
  48. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INMENU, // OBI_CLOSE_MBAR
  49. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INMENU | DFCS_PUSHED, // OBI_CLOSE_MBAR_D
  50. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INMENU | DFCS_HOT, // OBI_CLOSE_MBAR_H
  51. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INMENU | DFCS_INACTIVE, // OBI_CLOSE_MBAR_I
  52. DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INMENU, // OBI_REDUCE_MBAR
  53. DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INMENU | DFCS_PUSHED, // OBI_REDUCE_MBAR_D
  54. DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INMENU | DFCS_HOT, // OBI_REDUCE_MBAR_H
  55. DFC_CAPTION, DFCS_CAPTIONMIN | DFCS_INMENU | DFCS_INACTIVE, // OBI_REDUCE_MBAR_I
  56. DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_INMENU, // OBI_RESTORE_MBAR
  57. DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_INMENU | DFCS_PUSHED, // OBI_RESTORE_MBAR_D
  58. DFC_CAPTION, DFCS_CAPTIONRESTORE | DFCS_INMENU | DFCS_HOT, // OBI_RESTORE_MBAR_H
  59. DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON1
  60. DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON1_I
  61. DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON2
  62. DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON2_I
  63. DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON3
  64. DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON3_I
  65. DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON4
  66. DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON4_I
  67. DFC_CACHE, DFCS_CACHEICON, // OBI_CAPICON5
  68. DFC_CACHE, DFCS_CACHEICON | DFCS_INACTIVE, // OBI_CAPICON5_I
  69. DFC_CACHE, DFCS_CACHEBUTTONS, // OBI_CAPBTNS
  70. DFC_CACHE, DFCS_CACHEBUTTONS | DFCS_INACTIVE, // OBI_CAPBTNS_I
  71. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INSMALL, // OBI_CLOSE_PAL
  72. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INSMALL | DFCS_PUSHED, // OBI_CLOSE_PAL_D
  73. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INSMALL | DFCS_HOT, // OBI_CLOSE_PAL_H
  74. DFC_CAPTION, DFCS_CAPTIONCLOSE | DFCS_INSMALL | DFCS_INACTIVE,// OBI_CLOSE_PAL_I
  75. DFC_SCROLL, DFCS_SCROLLSIZEGRIP, // OBI_NCGRIP
  76. DFC_SCROLL, DFCS_SCROLLUP, // OBI_UPARROW
  77. DFC_SCROLL, DFCS_SCROLLUP | DFCS_PUSHED | DFCS_FLAT, // OBI_UPARROW_D
  78. DFC_SCROLL, DFCS_SCROLLUP | DFCS_HOT, // OBI_UPARROW_H
  79. DFC_SCROLL, DFCS_SCROLLUP | DFCS_INACTIVE, // OBI_UPARROW_I
  80. DFC_SCROLL, DFCS_SCROLLDOWN, // OBI_DNARROW
  81. DFC_SCROLL, DFCS_SCROLLDOWN | DFCS_PUSHED | DFCS_FLAT, // OBI_DNARROW_D
  82. DFC_SCROLL, DFCS_SCROLLDOWN | DFCS_HOT, // OBI_DNARROW_H
  83. DFC_SCROLL, DFCS_SCROLLDOWN | DFCS_INACTIVE, // OBI_DNARROW_I
  84. DFC_SCROLL, DFCS_SCROLLRIGHT, // OBI_RGARROW
  85. DFC_SCROLL, DFCS_SCROLLRIGHT | DFCS_PUSHED | DFCS_FLAT, // OBI_RGARROW_D
  86. DFC_SCROLL, DFCS_SCROLLRIGHT | DFCS_HOT, // OBI_RGARROW_H
  87. DFC_SCROLL, DFCS_SCROLLRIGHT | DFCS_INACTIVE, // OBI_RGARROW_I
  88. DFC_SCROLL, DFCS_SCROLLLEFT, // OBI_LFARROW
  89. DFC_SCROLL, DFCS_SCROLLLEFT | DFCS_PUSHED | DFCS_FLAT, // OBI_LFARROW_D
  90. DFC_SCROLL, DFCS_SCROLLLEFT | DFCS_HOT, // OBI_LFARROW_H
  91. DFC_SCROLL, DFCS_SCROLLLEFT | DFCS_INACTIVE, // OBI_LFARROW_I
  92. DFC_MENU, DFCS_MENUARROW, // OBI_MENUARROW
  93. DFC_MENU, DFCS_MENUCHECK, // OBI_MENUCHECK
  94. DFC_MENU, DFCS_MENUBULLET, // OBI_MENUBULLET
  95. DFC_MENU, DFCS_MENUARROWUP, // OBI_MENUARROWUP
  96. DFC_MENU, DFCS_MENUARROWUP | DFCS_HOT, // OBI_MENUARROWUP_H
  97. DFC_MENU, DFCS_MENUARROWUP | DFCS_INACTIVE, // OBI_MENUARROWUP_I
  98. DFC_MENU, DFCS_MENUARROWDOWN, // OBI_MENUARROWDOWN
  99. DFC_MENU, DFCS_MENUARROWDOWN | DFCS_HOT, // OBI_MENUARROWDOWN_H
  100. DFC_MENU, DFCS_MENUARROWDOWN | DFCS_INACTIVE, // OBI_MENUARROWDOWN_I
  101. DFC_BUTTON, DFCS_BUTTONRADIOMASK, // OBI_RADIOMASK
  102. DFC_BUTTON, DFCS_BUTTONCHECK, // OBI_CHECK
  103. DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_CHECKED, // OBI_CHECK_C
  104. DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_PUSHED, // OBI_CHECK_D
  105. DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_PUSHED, // OBI_CHECK_CD
  106. DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_INACTIVE, // OBI_CHECK_CDI
  107. DFC_BUTTON, DFCS_BUTTONRADIOIMAGE, // OBI_RADIO
  108. DFC_BUTTON, DFCS_BUTTONRADIOIMAGE | DFCS_CHECKED, // OBI_RADIO_C
  109. DFC_BUTTON, DFCS_BUTTONRADIOIMAGE | DFCS_PUSHED, // OBI_RADIO_D
  110. DFC_BUTTON, DFCS_BUTTONRADIOIMAGE | DFCS_CHECKED | DFCS_PUSHED, // OBI_RADIO_CD
  111. DFC_BUTTON, DFCS_BUTTONRADIOIMAGE | DFCS_CHECKED | DFCS_INACTIVE, // OBI_RADIO_CDI
  112. DFC_BUTTON, DFCS_BUTTON3STATE, // OBI_3STATE
  113. DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_CHECKED, // OBI_3STATE_C
  114. DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_PUSHED, // OBI_3STATE_D
  115. DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_PUSHED, // OBI_3STATE_CD
  116. DFC_BUTTON, DFCS_BUTTON3STATE | DFCS_CHECKED | DFCS_INACTIVE, // OBI_3STATE_CDI
  117. DFC_POPUPMENU, DFCS_CAPTIONCLOSE | DFCS_INMENU, // OBI_CLOSE_POPUP
  118. DFC_POPUPMENU, DFCS_CAPTIONRESTORE | DFCS_INMENU, // OBI_RESTORE_POPUP
  119. DFC_POPUPMENU, DFCS_CAPTIONMAX | DFCS_INMENU, // OBI_ZOOM_POPUP
  120. DFC_POPUPMENU, DFCS_CAPTIONMIN | DFCS_INMENU, // OBI_REDUCE_POPUP
  121. DFC_SCROLL, DFCS_SCROLLSIZEGRIPRIGHT, // OBI_NCGRIP_L
  122. DFC_MENU, DFCS_MENUARROWRIGHT // OBI_MENUARROW_L
  123. };
  124. #define DIVISOR 72
  125. #define DU_BTNWIDTH 50 // D.U. of minimum button width in a message box
  126. UINT xxxMB_FindLongestString(HDC hdc);
  127. #ifdef LATER
  128. /***************************************************************************\
  129. \***************************************************************************/
  130. WCHAR NibbleToChar(
  131. BYTE x)
  132. {
  133. WCHAR static N2C[] =
  134. {
  135. '0', '1', '2', '3', '4', '5', '6', '7',
  136. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
  137. };
  138. return N2C[x];
  139. }
  140. BYTE CharToNibble(
  141. WCHAR ch)
  142. {
  143. BYTE x = (BYTE)ch;
  144. return x >= '0' && x <= '9' ?
  145. x - '0' :
  146. ((10 + x - 'A' ) & 0x0f);
  147. }
  148. BOOL TextToBinary(
  149. LPBYTE pbyte,
  150. LPWSTR pwstr,
  151. int length)
  152. {
  153. BYTE checksum = 0;
  154. while (TRUE) {
  155. BYTE byte;
  156. byte = (CharToNibble(pwstr[0]) << 4) | CharToNibble(pwstr[1]);
  157. if (length == 0) {
  158. return checksum == byte;
  159. }
  160. checksum += byte;
  161. *pbyte = byte;
  162. pwstr += 2;
  163. length--;
  164. pbyte++;
  165. }
  166. }
  167. void BinaryToText(
  168. LPWSTR pwstr,
  169. LPBYTE pbyte,
  170. int length)
  171. {
  172. BYTE checksum = 0;
  173. while (length > 0) {
  174. checksum += *pbyte;
  175. pwstr[0] = NibbleToChar((BYTE)((*pbyte >> 4) & 0x0f));
  176. pwstr[1] = NibbleToChar((BYTE)(*pbyte & 0x0f));
  177. pbyte++;
  178. pwstr += 2;
  179. length--;
  180. }
  181. pwstr[0] = NibbleToChar((BYTE)((checksum >> 4) & 0x0f));
  182. pwstr[1] = NibbleToChar((BYTE)(checksum & 0x0f));
  183. pwstr[2] = '\0';
  184. }
  185. /***************************************************************************\
  186. \***************************************************************************/
  187. // these are the exported apis. The User* versions are for server use only
  188. // I didn't get them to work since no one calls them yet.
  189. BOOL GetPrivateProfileStruct(
  190. LPWSTR szSection,
  191. LPWSTR szKey,
  192. LPWSTR lpStruct,
  193. DWORD uSizeStruct,
  194. LPWSTR szFile)
  195. {
  196. WCHAR szBuf[256];
  197. BOOL fAlloc = FALSE;
  198. LPSTR lpBuf, lpBufTemp;
  199. int nLen;
  200. BOOL fError = FALSE;
  201. nLen = uSizeStruct * 4 + 10;
  202. if (nLen > (WORD)sizeof(szBuf)) {
  203. fAlloc = TRUE;
  204. lpBuf = (LPSTR)UserAllocPoolWithQuota(nLen, TAG_PROFILE);
  205. if (lpBuf == NULL)
  206. return FALSE;
  207. } else {
  208. lpBuf = (LPSTR)szBuf;
  209. }
  210. if (szFile && *szFile) {
  211. nLen = GetPrivateProfileString(szSection, szKey, NULL, lpBuf, nLen, szFile);
  212. } else {
  213. nLen = GetProfileString(szSection, szKey, NULL, lpBuf, nLen);
  214. }
  215. if (nLen == (int)(uSizeStruct * 4 + 4)) {
  216. /*
  217. * decode the string
  218. */
  219. fError = TextToBinary(lpStruct, lpBufTemp, uSizeStruct);
  220. }
  221. if (fAlloc)
  222. UserFreePool(lpBuf);
  223. return fError;
  224. }
  225. BOOL WritePrivateProfileStruct(
  226. LPWSTR szSection,
  227. LPWSTR szKey,
  228. LPWSTR lpStruct,
  229. WORD uSizeStruct,
  230. LPWSTR szFile)
  231. {
  232. LPWSTR lpBuf;
  233. BOOL bRet;
  234. BOOL fAlloc;
  235. WCHAR szBuf[256];
  236. BYTE checksum=0;
  237. int allocsize = (uSizeStruct * 2 + 3) * sizeof(WCHAR);
  238. /* NULL lpStruct erases the the key */
  239. if (lpStruct == NULL) {
  240. if (szFile && *szFile) {
  241. return WritePrivateProfileString(szSection, szKey, (LPSTR)NULL, szFile);
  242. } else {
  243. return WriteProfileString(szSection, szKey, (LPSTR)NULL);
  244. }
  245. }
  246. fAlloc = (allocsize > sizeof(szBuf));
  247. if (fAlloc) {
  248. lpBuf = (LPSTR)UserAllocPoolWithQuota(allocsize, TAG_PROFILE);
  249. if (!lpBuf)
  250. return FALSE;
  251. } else {
  252. lpBuf = (LPSTR)szBuf;
  253. }
  254. BinaryToText(lpBuf, lpStruct, uSizeStruct);
  255. if (szFile && *szFile) {
  256. bRet = WritePrivateProfileString(szSection, szKey, lpBuf, szFile);
  257. } else {
  258. bRet = WriteProfileString(szSection, szKey, lpBuf);
  259. }
  260. if (fAlloc)
  261. UserFreePool(lpBuf);
  262. return bRet;
  263. }
  264. #endif
  265. /***************************************************************************\
  266. *
  267. * GetFrameControlMetrics
  268. *
  269. * (cx = 0) is a code meaning cy is the obi of the "shared" bitmap
  270. *
  271. \***************************************************************************/
  272. int GetFrameControlMetrics(
  273. UINT obi,
  274. int cxMax )
  275. {
  276. int cx, cy;
  277. UINT wType = sysBmpStyles[obi][0];
  278. UINT wState = sysBmpStyles[obi][1];
  279. POEMBITMAPINFO pOem = gpsi->oembmi + obi;
  280. switch (wType) {
  281. case DFC_SCROLL:
  282. if (wState & DFCS_SCROLLSIZEGRIP) {
  283. cx = SYSMET(CXVSCROLL);
  284. cy = SYSMET(CYHSCROLL);
  285. break;
  286. } else if (wState & DFCS_SCROLLHORZ) {
  287. cx = SYSMET(CXHSCROLL);
  288. cy = SYSMET(CYHSCROLL);
  289. } else {
  290. cx = SYSMET(CXVSCROLL);
  291. cy = SYSMET(CYVSCROLL);
  292. }
  293. break;
  294. case DFC_MENU:
  295. case DFC_POPUPMENU:
  296. if (wState & (DFCS_MENUARROWUP | DFCS_MENUARROWDOWN)) {
  297. cy = gcyMenuScrollArrow;
  298. } else {
  299. /*
  300. * Add on proper space for space above underscore.
  301. * the 0xFFFE and -1 are to insure an ODD height
  302. */
  303. cy = ((gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYBORDER)) & 0xFFFE) - 1;
  304. }
  305. cx = cy;
  306. break;
  307. case DFC_CAPTION:
  308. if (wState & DFCS_INSMALL) {
  309. cx = SYSMET(CXSMSIZE);
  310. cy = SYSMET(CYSMSIZE);
  311. } else if (wState & DFCS_INMENU) {
  312. if ((SYSMET(CXSIZE) == SYSMET(CXMENUSIZE)) &&
  313. (SYSMET(CYSIZE) == SYSMET(CYMENUSIZE))) {
  314. cx = 0;
  315. cy = obi - DOBI_MBAR;
  316. break;
  317. } else {
  318. cx = SYSMET(CXMENUSIZE);
  319. cy = SYSMET(CYMENUSIZE);
  320. }
  321. } else {
  322. cx = SYSMET(CXSIZE);
  323. cy = SYSMET(CYSIZE);
  324. }
  325. cx -= SYSMET(CXEDGE);
  326. cy -= 2 * SYSMET(CYEDGE);
  327. break;
  328. case DFC_CACHE:
  329. if (wState & DFCS_CACHEBUTTONS) {
  330. cx = SYSMET(CXSIZE) * 4;
  331. cy = SYSMET(CYSIZE);
  332. } else
  333. cx = cy = SYSMET(CYSIZE);
  334. break;
  335. case DFC_BUTTON:
  336. if (((wState & 0x00FF) & DFCS_BUTTON3STATE) && !(wState & DFCS_CHECKED)) {
  337. cx = 0;
  338. cy = obi - DOBI_3STATE;
  339. } else {
  340. /*
  341. * Scale button size with screen DPI so we look OK on high
  342. * resolution monitors.
  343. */
  344. cx = cy = (gpsi->dmLogPixels / 8) + 1;
  345. }
  346. break;
  347. }
  348. pOem->cx = cx;
  349. pOem->cy = cy;
  350. return((cx > cxMax) ? cx : cxMax);
  351. }
  352. /***************************************************************************\
  353. *
  354. * PackFrameControls
  355. *
  356. * Given the dimensions that GetFrameControlMetrics has calculated, this
  357. * arranges all the system bitmaps to fit within a bitmap of the given width
  358. *
  359. \***************************************************************************/
  360. int PackFrameControls(int cxMax, BOOL fRecord) {
  361. UINT obi;
  362. int cy = 0;
  363. int x = 0;
  364. int y = 0;
  365. POEMBITMAPINFO pOem = gpsi->oembmi;
  366. for (obi = 0; obi < OBI_COUNT; obi++, pOem++) {
  367. if (pOem->cx) {
  368. if ((x + pOem->cx) > cxMax) {
  369. y += cy;
  370. cy = 0;
  371. x = 0;
  372. }
  373. if (fRecord) {
  374. pOem->x = x;
  375. pOem->y = y;
  376. }
  377. if (cy < pOem->cy)
  378. cy = pOem->cy;
  379. x += pOem->cx;
  380. }
  381. }
  382. return(y + cy);
  383. }
  384. void DrawCaptionButtons(
  385. int x,
  386. int y
  387. )
  388. {
  389. x += SYSMET(CXEDGE);
  390. y += SYSMET(CYEDGE);
  391. BitBltSysBmp(HDCBITS(), x, y, OBI_REDUCE);
  392. x += SYSMET(CXSIZE) - SYSMET(CXEDGE);
  393. BitBltSysBmp(HDCBITS(), x, y, OBI_ZOOM);
  394. x += SYSMET(CXSIZE);
  395. BitBltSysBmp(HDCBITS(), x, y, OBI_CLOSE);
  396. x += SYSMET(CXSIZE);
  397. BitBltSysBmp(HDCBITS(), x, y, OBI_HELP);
  398. }
  399. /***************************************************************************\
  400. * CreateCaptionStrip
  401. *
  402. *
  403. \***************************************************************************/
  404. HBITMAP CreateCaptionStrip(VOID)
  405. {
  406. HBITMAP hbm;
  407. hbm = GreCreateCompatibleBitmap(gpDispInfo->hdcScreen,
  408. SYSMET(CXVIRTUALSCREEN),
  409. (SYSMET(CYCAPTION) - 1) * 2);
  410. if (hbm)
  411. GreSetBitmapOwner(hbm, OBJECT_OWNER_PUBLIC);
  412. return hbm;
  413. }
  414. /***************************************************************************\
  415. *
  416. * CreateBitmapStrip
  417. *
  418. * This routine sets up either the color or monochrome strip bitmap -- a
  419. * large horizontal bitmap which contains all of the system bitmaps. By
  420. * having all of these bitmaps in one long bitmap, we can have that one
  421. * bitmap always selected in, speeding up paint time by not having to do
  422. * a SelectBitmap() everytime we need to Blt one of the system bitmaps.
  423. *
  424. \***************************************************************************/
  425. BOOL CreateBitmapStrip(VOID)
  426. {
  427. int cxBmp = 0;
  428. int cyBmp = 0;
  429. int iCache = 0;
  430. int cy[5];
  431. HBITMAP hOldBitmap;
  432. HBITMAP hNewBmp;
  433. UINT iType;
  434. RECT rc;
  435. UINT wBmpType;
  436. UINT wBmpStyle;
  437. POEMBITMAPINFO pOem;
  438. /*
  439. * Each OBI_ must have an entry in sysBmpStyles
  440. */
  441. UserAssert(OBI_COUNT == sizeof(sysBmpStyles) / sizeof(*sysBmpStyles));
  442. UserAssert(OBI_COUNT == sizeof(gpsi->oembmi) / sizeof(*(gpsi->oembmi)));
  443. /*
  444. * load all the bitmap dimensions into the OEMBITMAPINFO array oemInfo.bm
  445. */
  446. for (iType = 0; iType < OBI_COUNT; iType++)
  447. cxBmp = GetFrameControlMetrics(iType, cxBmp);
  448. for (iType = 0; iType < 5; iType++)
  449. cy[iType] = PackFrameControls(cxBmp * (iType + 1), FALSE) * (iType + 1);
  450. cyBmp = min(cy[0], min(cy[1], min(cy[2], min(cy[3], cy[4]))));
  451. for (iType = 0; cyBmp != cy[iType]; iType++);
  452. cxBmp *= iType + 1;
  453. cyBmp = PackFrameControls(cxBmp, TRUE);
  454. hNewBmp = GreCreateCompatibleBitmap(gpDispInfo->hdcScreen, cxBmp, cyBmp);
  455. if (hNewBmp == NULL) {
  456. RIPMSG0(RIP_WARNING, "CreateBitmapStrip: failed to create bitmap");
  457. return FALSE;
  458. }
  459. GreSetBitmapOwner(hNewBmp, OBJECT_OWNER_PUBLIC);
  460. /*
  461. * Select in Bitmap Strip -- then delete old one if it exists.
  462. */
  463. hOldBitmap = GreSelectBitmap(HDCBITS(), hNewBmp);
  464. if (ghbmBits) {
  465. #if DBG
  466. /*
  467. * Don't RIP if we're out of memory.
  468. */
  469. if (hOldBitmap != NULL && ghbmBits != hOldBitmap) {
  470. RIPMSG0(RIP_WARNING, "ghbmBits != hOldBitmap");
  471. }
  472. #endif
  473. GreDeleteObject(ghbmCaption);
  474. GreDeleteObject(hOldBitmap);
  475. }
  476. ghbmBits = hNewBmp;
  477. ghbmCaption = CreateCaptionStrip();
  478. if (ghbmCaption == NULL) {
  479. RIPMSG0(RIP_WARNING, "CreateBitmapStrip: failed to create bitmap for caption");
  480. return FALSE;
  481. }
  482. /*
  483. * Draw individual bitmaps into the strip bitmap and record the offsets.
  484. */
  485. for (pOem = gpsi->oembmi, iType = 0; iType < OBI_COUNT; iType++, pOem++) {
  486. if (!pOem->cx) {
  487. *pOem = gpsi->oembmi[pOem->cy];
  488. } else {
  489. rc.left = pOem->x;
  490. rc.top = pOem->y;
  491. rc.right = rc.left + pOem->cx;
  492. rc.bottom = rc.top + pOem->cy;
  493. wBmpType = sysBmpStyles[iType][0];
  494. wBmpStyle = sysBmpStyles[iType][1];
  495. if (wBmpType == DFC_CACHE) {
  496. if (wBmpStyle & DFCS_CACHEBUTTONS) {
  497. HBRUSH hbr;
  498. if (TestALPHA(GRADIENTCAPTIONS)) {
  499. hbr = (wBmpStyle & DFCS_INACTIVE) ? SYSHBR(GRADIENTINACTIVECAPTION) : SYSHBR(GRADIENTACTIVECAPTION);
  500. } else {
  501. hbr = (wBmpStyle & DFCS_INACTIVE) ? SYSHBR(INACTIVECAPTION) : SYSHBR(ACTIVECAPTION);
  502. }
  503. FillRect(HDCBITS(), &rc, hbr);
  504. DrawCaptionButtons(rc.left, rc.top);
  505. } else if (!(wBmpStyle & DFCS_INACTIVE)) {
  506. /*
  507. * Setup Caption Cache Entry
  508. */
  509. UserAssert(iCache < CCACHEDCAPTIONS);
  510. if (gcachedCaptions[iCache].spcursor) {
  511. Unlock(&(gcachedCaptions[iCache].spcursor));
  512. }
  513. gcachedCaptions[iCache++].pOem = pOem;
  514. }
  515. } else {
  516. DrawFrameControl(HDCBITS(), &rc, wBmpType, wBmpStyle);
  517. }
  518. }
  519. }
  520. /*
  521. * Setup other frame metric dependent values.
  522. */
  523. SYSMET(CXMENUCHECK) = gpsi->oembmi[OBI_MENUCHECK].cx;
  524. SYSMET(CYMENUCHECK) = gpsi->oembmi[OBI_MENUCHECK].cy;
  525. return TRUE;
  526. }
  527. void
  528. SetNCMetrics(
  529. LPNONCLIENTMETRICS lpnc)
  530. {
  531. int nMin;
  532. /*
  533. * Scroll metrics
  534. */
  535. SYSMET(CXVSCROLL) = SYSMET(CYHSCROLL) = (int) lpnc->iScrollWidth;
  536. SYSMET(CYVSCROLL) = SYSMET(CXHSCROLL) = (int) lpnc->iScrollHeight;
  537. SYSMET(CYVTHUMB) = SYSMET(CXHTHUMB) = (int) lpnc->iScrollHeight;
  538. /*
  539. * Caption metrics
  540. */
  541. SYSMET(CXSIZE) = (int) lpnc->iCaptionWidth;
  542. SYSMET(CYSIZE) = (int) lpnc->iCaptionHeight;
  543. SYSMET(CYCAPTION) = SYSMET(CYSIZE) + SYSMET(CYBORDER);
  544. /*
  545. * Keep small icon square?
  546. * ?? Should we allow rectangles?
  547. */
  548. SYSMET(CXSMICON) = (SYSMET(CXSIZE) - SYSMET(CXEDGE)) & ~1;
  549. SYSMET(CYSMICON) = (SYSMET(CYSIZE) - SYSMET(CYEDGE)) & ~1;
  550. nMin = min(SYSMET(CXSMICON), SYSMET(CYSMICON));
  551. SYSMET(CXSMICON) = nMin;
  552. SYSMET(CYSMICON) = nMin;
  553. /*
  554. * Small Caption metrics
  555. */
  556. SYSMET(CXSMSIZE) = (int) lpnc->iSmCaptionWidth;
  557. SYSMET(CYSMSIZE) = (int) lpnc->iSmCaptionHeight;
  558. SYSMET(CYSMCAPTION) = SYSMET(CYSMSIZE) + SYSMET(CYBORDER);
  559. /*
  560. * Menu metrics
  561. */
  562. SYSMET(CXMENUSIZE) = (int) lpnc->iMenuWidth;
  563. SYSMET(CYMENUSIZE) = (int) lpnc->iMenuHeight;
  564. SYSMET(CYMENU) = SYSMET(CYMENUSIZE) + SYSMET(CYBORDER);
  565. /*
  566. * Border metrics
  567. */
  568. gpsi->gclBorder = (int) lpnc->iBorderWidth;
  569. SYSMET(CXFRAME) = SYSMET(CXEDGE) + (gpsi->gclBorder+1)*SYSMET(CXBORDER);
  570. SYSMET(CYFRAME) = SYSMET(CYEDGE) + (gpsi->gclBorder+1)*SYSMET(CYBORDER);
  571. /*
  572. * Minimium tracking size is
  573. * Across: Space for small icon, 4 chars & space + 3 buttons + borders
  574. * Down: Space for caption + borders
  575. * Yes, we use CYSIZE. This is because the width of any small icon
  576. * is the same as the height, and the height is CYSIZE.
  577. */
  578. SYSMET(CXMINTRACK) = SYSMET(CYSIZE) + (gcxCaptionFontChar * 4) + 2 * SYSMET(CXEDGE) +
  579. (SYSMET(CXSIZE) * 3) + (SYSMET(CXSIZEFRAME) * 2);
  580. SYSMET(CYMINTRACK) = SYSMET(CYCAPTION) + (SYSMET(CYSIZEFRAME) * 2);
  581. /*
  582. * Max track size
  583. * Yeah, max track is bigger than maximized. The reason why is the DOS
  584. * box. It has a normal sizing border plus the sunken edge around the
  585. * client. We need to make this big enough to allow the dos box to grow.
  586. * When it hits its max size, it maximizes automatically.
  587. */
  588. SYSMET(CXMAXTRACK) = SYSMET(CXVIRTUALSCREEN) + (2 * (SYSMET(CXSIZEFRAME) + SYSMET(CXEDGE)));
  589. SYSMET(CYMAXTRACK) = SYSMET(CYVIRTUALSCREEN) + (2 * (SYSMET(CYSIZEFRAME) + SYSMET(CYEDGE)));
  590. SYSMET(CXMIN) = SYSMET(CXMINTRACK);
  591. SYSMET(CYMIN) = SYSMET(CYMINTRACK);
  592. SYSMET(CYMINIMIZED) = 2*SYSMET(CYFIXEDFRAME) + SYSMET(CYSIZE);
  593. /*
  594. * Desktop stuff--working area
  595. */
  596. bSetDevDragWidth(gpDispInfo->hDev,
  597. gpsi->gclBorder + BORDER_EXTRA);
  598. SetDesktopMetrics();
  599. }
  600. /***************************************************************************\
  601. *
  602. * CreateFontFromWinIni() -
  603. *
  604. * If lplf is NULL, we do a first time, default initialization.
  605. * Otherwise, lplf is a pointer to the logfont we will use.
  606. *
  607. \***************************************************************************/
  608. HFONT CreateFontFromWinIni(
  609. PUNICODE_STRING pProfileUserName,
  610. LPLOGFONTW lplf,
  611. UINT idFont)
  612. {
  613. LOGFONTW lf;
  614. HFONT hFont;
  615. if (lplf == NULL) {
  616. static CONST WCHAR szDefFont[] = TEXT("MS Shell Dlg");
  617. /*
  618. * Fill logfont w/ 0 so we can check if values were filled in.
  619. */
  620. lplf = &lf;
  621. RtlZeroMemory(&lf, sizeof(lf));
  622. lf.lfCharSet = gSystemCPCharSet;
  623. FastGetProfileValue(pProfileUserName,PMAP_METRICS, (LPWSTR)UIntToPtr( idFont ), NULL, (LPBYTE)&lf, sizeof(lf), 0);
  624. /*
  625. * Default font is MS Shell Dlg
  626. */
  627. if (! lf.lfFaceName[0]) {
  628. RtlCopyMemory(lf.lfFaceName, szDefFont, sizeof(szDefFont));
  629. }
  630. /*
  631. * Warning! these values are different then Win 95. They did not have a True Type
  632. * font so they would round up when they asked for a 6 pt font. We have to ask
  633. * for an 8 point font ICONFONT to be the same.
  634. */
  635. if (!lf.lfHeight) {
  636. switch (idFont) {
  637. case STR_SMCAPTIONFONT:
  638. case STR_MINFONT:
  639. case STR_ICONFONT:
  640. default:
  641. lf.lfHeight = 8;
  642. break;
  643. }
  644. }
  645. /*
  646. * We need to convert the point size properly. GDI expects a
  647. * height in pixels, not points.
  648. */
  649. if (lf.lfHeight > 0) {
  650. lf.lfHeight = -MultDiv(lf.lfHeight, gpsi->dmLogPixels, 72);
  651. }
  652. if (! lf.lfWeight) {
  653. switch (idFont) {
  654. case STR_CAPTIONFONT:
  655. case STR_MINFONT:
  656. lf.lfWeight = FW_BOLD;
  657. break;
  658. default:
  659. lf.lfWeight = FW_NORMAL;
  660. break;
  661. }
  662. }
  663. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  664. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  665. lf.lfQuality = DEFAULT_QUALITY;
  666. }
  667. hFont = GreCreateFontIndirectW(lplf);
  668. if (hFont) {
  669. LOGFONTW lfT;
  670. GreExtGetObjectW(hFont, sizeof(LOGFONTW), &lfT);
  671. if (lfT.lfHeight != lplf->lfHeight) {
  672. /*
  673. * Couldn't find a font with the height that we
  674. * wanted so use the system font instead.
  675. */
  676. GreDeleteObject(hFont);
  677. hFont = NULL;
  678. } else {
  679. GreMarkUndeletableFont(hFont);
  680. GreSetLFONTOwner((HLFONT)hFont, OBJECT_OWNER_PUBLIC);
  681. }
  682. }
  683. if (!hFont) {
  684. /*
  685. * We've tried to create the font from the app-supplied description.
  686. * If failure, return NULL so that we don't change the previous
  687. * font.
  688. */
  689. if (lplf)
  690. hFont = NULL;
  691. else
  692. hFont = ghFontSys;
  693. }
  694. return hFont;
  695. }
  696. /***************************************************************************\
  697. *
  698. \***************************************************************************/
  699. BOOL UserSetFont(
  700. PUNICODE_STRING pProfileUserName,
  701. LPLOGFONTW lplf,
  702. UINT idFont,
  703. HFONT* phfont)
  704. {
  705. HFONT hNewFont;
  706. if (hNewFont = CreateFontFromWinIni(pProfileUserName, lplf, idFont)) {
  707. if (*phfont != NULL && *phfont != ghFontSys) {
  708. GreMarkDeletableFont(*phfont);
  709. GreDeleteObject(*phfont);
  710. }
  711. *phfont = hNewFont;
  712. return TRUE;
  713. }
  714. return FALSE;
  715. }
  716. /***************************************************************************\
  717. *
  718. * xxxSetNCFonts() -
  719. *
  720. * Creates fonts to be used in the frame components:
  721. * Caption
  722. * Small caption
  723. * Menu
  724. * Minimized
  725. * Icon
  726. *
  727. * 01-21-98 [SamerA] Renamed to xxxSetNCFonts since it may leave the
  728. * critical section when a client LPK is installed.
  729. \***************************************************************************/
  730. BOOL xxxSetNCFonts(
  731. PUNICODE_STRING pProfileUserName,
  732. LPNONCLIENTMETRICS lpnc)
  733. {
  734. HFONT hOldFont;
  735. TEXTMETRIC tm;
  736. LOGFONTW lf;
  737. LPLOGFONTW lplf = (lpnc) ? &lf : 0;
  738. /*
  739. * Caption font
  740. */
  741. if (lplf) {
  742. *lplf = lpnc->lfCaptionFont;
  743. }
  744. if (!UserSetFont(pProfileUserName,lplf, STR_CAPTIONFONT, &gpsi->hCaptionFont)) {
  745. RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for gpsi->hCaptionFont");
  746. return FALSE;
  747. }
  748. hOldFont = GreSelectFont(HDCBITS(), gpsi->hCaptionFont);
  749. gcxCaptionFontChar = GetCharDimensions(
  750. HDCBITS(), NULL, &gcyCaptionFontChar);
  751. #ifdef LAME_BUTTON
  752. /*
  753. * Lame! button font
  754. */
  755. {
  756. LOGFONTW lfLame;
  757. WCHAR szLameButtonKey[60];
  758. SIZE btnSize;
  759. if (ghLameFont != NULL) {
  760. GreMarkDeletableFont(ghLameFont);
  761. GreDeleteObject(ghLameFont);
  762. }
  763. GreExtGetObjectW(gpsi->hCaptionFont, sizeof(LOGFONTW), &lfLame);
  764. lfLame.lfUnderline = 1;
  765. lfLame.lfWeight = FW_THIN;
  766. ghLameFont = GreCreateFontIndirectW(&lfLame);
  767. if (ghLameFont == NULL) {
  768. RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for ghLameFont");
  769. return FALSE;
  770. } else {
  771. GreMarkUndeletableFont(ghLameFont);
  772. GreSetLFONTOwner((HLFONT)ghLameFont, OBJECT_OWNER_PUBLIC);
  773. }
  774. ServerLoadString(hModuleWin, STR_LAMEBUTTONTEXT, szLameButtonKey, ARRAY_SIZE(szLameButtonKey));
  775. FastGetProfileStringW(pProfileUserName,
  776. PMAP_DESKTOP,
  777. szLameButtonKey,
  778. TEXT("Comments?"),
  779. gpsi->gwszLame,
  780. 50,
  781. 0);
  782. GreSelectFont(HDCBITS(), ghLameFont);
  783. GreGetTextExtentW(HDCBITS(),
  784. gpsi->gwszLame,
  785. wcslen(gpsi->gwszLame),
  786. &btnSize,
  787. GGTE_WIN3_EXTENT);
  788. gpsi->ncxLame = btnSize.cx;
  789. }
  790. #endif // LAME_BUTTON
  791. /*
  792. * Small caption font
  793. */
  794. if (lplf) {
  795. *lplf = lpnc->lfSmCaptionFont;
  796. }
  797. if (!UserSetFont(pProfileUserName,lplf, STR_SMCAPTIONFONT, &ghSmCaptionFont)) {
  798. RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for ghSmCaptionFont");
  799. return FALSE;
  800. }
  801. GreSelectFont(HDCBITS(), ghSmCaptionFont);
  802. gcxSmCaptionFontChar = GetCharDimensions(
  803. HDCBITS(), NULL, &gcySmCaptionFontChar);
  804. /*
  805. * Menu font
  806. */
  807. if (lplf) {
  808. *lplf = lpnc->lfMenuFont;
  809. }
  810. if (!UserSetFont(pProfileUserName,lplf, STR_MENUFONT, &ghMenuFont)) {
  811. RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for ghMenuFont");
  812. return FALSE;
  813. }
  814. /*
  815. * if ghMenuFont is selected in cached animation DC, select the new one.
  816. */
  817. if (gMenuState.hdcAni != NULL) {
  818. GreSelectFont(gMenuState.hdcAni, ghMenuFont);
  819. }
  820. GreSelectFont(HDCBITS(), ghMenuFont);
  821. gcxMenuFontChar = GetCharDimensions(
  822. HDCBITS(), &tm, &gcyMenuFontChar);
  823. gcxMenuFontOverhang = tm.tmOverhang;
  824. gcyMenuFontExternLeading = tm.tmExternalLeading;
  825. gcyMenuScrollArrow = gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYEDGE);
  826. gcyMenuFontAscent = tm.tmAscent;
  827. /*
  828. * We only use gcyMenuFontAscent in mndraw.c once, and in U.S. we
  829. * always add on CYBORDER! So calculate gcyMenuFontAscent+CYBORDER
  830. * once only.
  831. * Legacy NT4: For Korean version, don't add it on; the underline would
  832. * be too low.
  833. * NT5: according to #254327, Korean version now sees underline is
  834. * too close to menu strings. Korean hack is pulled out so.
  835. */
  836. gcyMenuFontAscent += SYSMET(CYBORDER);
  837. /*
  838. * Default menu item font: bolder version of menu font
  839. */
  840. /*
  841. * Create default menu font by bolding hMenuFont. If this doesn't
  842. * work, then fall back to using simulation.
  843. */
  844. if (ghMenuFontDef != NULL && ghMenuFontDef != ghFontSys) {
  845. GreMarkDeletableFont(ghMenuFontDef);
  846. GreDeleteObject(ghMenuFontDef);
  847. ghMenuFontDef = NULL;
  848. }
  849. GreExtGetObjectW(ghMenuFont, sizeof(LOGFONTW), &lf);
  850. if (lf.lfWeight < FW_BOLD) {
  851. lf.lfWeight += 200;
  852. ghMenuFontDef = GreCreateFontIndirectW(&lf);
  853. if (ghMenuFontDef) {
  854. GreMarkUndeletableFont(ghMenuFontDef);
  855. GreSetLFONTOwner((HLFONT)ghMenuFontDef, OBJECT_OWNER_PUBLIC);
  856. }
  857. }
  858. /*
  859. * Status Bar font
  860. */
  861. if (lplf) {
  862. *lplf = lpnc->lfStatusFont;
  863. }
  864. if (!UserSetFont(pProfileUserName,lplf, STR_STATUSFONT, &ghStatusFont)) {
  865. RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for ghStatusFont");
  866. return FALSE;
  867. }
  868. /*
  869. * Message Box font
  870. */
  871. if (lplf) {
  872. *lplf = lpnc->lfMessageFont;
  873. }
  874. if (!UserSetFont(pProfileUserName,lplf, STR_MESSAGEFONT, &gpsi->hMsgFont)) {
  875. RIPMSG0(RIP_WARNING, "xxxSetNCFonts failed for gpsi->hMsgFont");
  876. return FALSE;
  877. }
  878. GreSelectFont(HDCBITS(), gpsi->hMsgFont);
  879. gpsi->cxMsgFontChar = GetCharDimensions(
  880. HDCBITS(), NULL, &gpsi->cyMsgFontChar);
  881. /*
  882. * Recalculate length of the widest MessageBox button
  883. * Make sure the width is no less than DU_BTNWIDTH dialog units MCostea #170582
  884. */
  885. gpsi->wMaxBtnSize = max((UINT)XPixFromXDU(DU_BTNWIDTH, gpsi->cxMsgFontChar),
  886. xxxMB_FindLongestString(HDCBITS()));
  887. GreSelectFont(HDCBITS(), hOldFont);
  888. return TRUE;
  889. }
  890. BOOL
  891. SetIconFonts(
  892. PUNICODE_STRING pProfileUserName,
  893. LPICONMETRICS lpicon)
  894. {
  895. LOGFONTW lf;
  896. LPLOGFONTW lplf = 0;
  897. if (lpicon) {
  898. lplf = &lf;
  899. lf = lpicon->lfFont;
  900. }
  901. return UserSetFont(pProfileUserName, lplf, STR_ICONFONT, &ghIconFont);
  902. }
  903. /***************************************************************************\
  904. * GetWindowMetrics
  905. *
  906. * Retrieve the current NC metrics.
  907. *
  908. *
  909. \***************************************************************************/
  910. VOID GetWindowNCMetrics(
  911. LPNONCLIENTMETRICS lpnc)
  912. {
  913. lpnc->cbSize = sizeof(NONCLIENTMETRICS);
  914. lpnc->iBorderWidth = gpsi->gclBorder;
  915. lpnc->iScrollWidth = SYSMET(CXVSCROLL);
  916. lpnc->iScrollHeight = SYSMET(CYVSCROLL);
  917. lpnc->iCaptionWidth = SYSMET(CXSIZE);
  918. lpnc->iCaptionHeight = SYSMET(CYSIZE);
  919. lpnc->iSmCaptionWidth = SYSMET(CXSMSIZE);
  920. lpnc->iSmCaptionHeight = SYSMET(CYSMSIZE);
  921. lpnc->iMenuWidth = SYSMET(CXMENUSIZE);
  922. lpnc->iMenuHeight = SYSMET(CYMENUSIZE);
  923. /*
  924. * Get the font info.
  925. */
  926. GreExtGetObjectW(gpsi->hCaptionFont,
  927. sizeof(LOGFONTW),
  928. &(lpnc->lfCaptionFont));
  929. GreExtGetObjectW(ghSmCaptionFont,
  930. sizeof(LOGFONTW),
  931. &(lpnc->lfSmCaptionFont));
  932. GreExtGetObjectW(ghMenuFont,
  933. sizeof(LOGFONTW),
  934. &(lpnc->lfMenuFont));
  935. GreExtGetObjectW(ghStatusFont,
  936. sizeof(LOGFONTW),
  937. &(lpnc->lfStatusFont));
  938. GreExtGetObjectW(gpsi->hMsgFont,
  939. sizeof(LOGFONTW),
  940. &(lpnc->lfMessageFont));
  941. }
  942. /***************************************************************************\
  943. *
  944. * xxxSetWindowNCMetrics() -
  945. *
  946. * creates system fonts and bitmaps and sets the system metrics based on the
  947. * values of the given FRAMEMETRICS struct. If NULL is passed in, the
  948. * default values (found in WIN.INI) are used instead.
  949. *
  950. * 01-21-98 [SamerA] Renamed to xxxSetWindowNCMetrics since it may leave the
  951. * critical section if an LPK is installed.
  952. \***************************************************************************/
  953. BOOL xxxSetWindowNCMetrics(
  954. PUNICODE_STRING pProfileUserName,
  955. LPNONCLIENTMETRICS lpnc,
  956. BOOL fSizeChange,
  957. int clNewBorder)
  958. {
  959. NONCLIENTMETRICS nc;
  960. int cxEdge4;
  961. if (fSizeChange) {
  962. if (!xxxSetNCFonts(pProfileUserName, lpnc)) {
  963. RIPMSG0(RIP_WARNING, "xxxSetWindowNCMetrics failed in xxxSetNCFonts");
  964. return FALSE;
  965. }
  966. if (lpnc == NULL) {
  967. if (clNewBorder < 0)
  968. nc.iBorderWidth = MetricGetID(pProfileUserName,STR_BORDERWIDTH, 1);
  969. else
  970. nc.iBorderWidth = clNewBorder;
  971. nc.iScrollWidth = MetricGetID(pProfileUserName,STR_SCROLLWIDTH, 16 );
  972. nc.iScrollHeight = MetricGetID(pProfileUserName,STR_SCROLLHEIGHT, 16 );
  973. nc.iCaptionWidth = MetricGetID(pProfileUserName,STR_CAPTIONWIDTH, 18 );
  974. nc.iCaptionHeight = MetricGetID(pProfileUserName,STR_CAPTIONHEIGHT, 18 );
  975. nc.iSmCaptionWidth = MetricGetID(pProfileUserName,STR_SMCAPTIONWIDTH, 13 );
  976. nc.iSmCaptionHeight = MetricGetID(pProfileUserName,STR_SMCAPTIONHEIGHT, 13 );
  977. nc.iMenuWidth = MetricGetID(pProfileUserName,STR_MENUWIDTH, 18 );
  978. nc.iMenuHeight = MetricGetID(pProfileUserName,STR_MENUHEIGHT, 18 );
  979. lpnc = &nc;
  980. }
  981. /*
  982. * SANITY CHECK for metric values
  983. */
  984. cxEdge4 = 4 * SYSMET(CXEDGE);
  985. /*
  986. * Border
  987. */
  988. lpnc->iBorderWidth = max(lpnc->iBorderWidth, 1);
  989. lpnc->iBorderWidth = min(lpnc->iBorderWidth, 50);
  990. /*
  991. * Scrollbar
  992. */
  993. lpnc->iScrollWidth = max(lpnc->iScrollWidth, cxEdge4);
  994. lpnc->iScrollHeight = max(lpnc->iScrollHeight, 4 * SYSMET(CYEDGE));
  995. /*
  996. * Caption -- Buttons must be wide enough to draw edges, and text
  997. * area must be tall enough to fit caption font with a border above
  998. * and below. If we have to reset the caption height, should we
  999. * reset the button width as well?
  1000. */
  1001. lpnc->iCaptionWidth = max(lpnc->iCaptionWidth, cxEdge4);
  1002. lpnc->iCaptionHeight = max(lpnc->iCaptionHeight, gcyCaptionFontChar + SYSMET(CYEDGE));
  1003. /*
  1004. * Small caption -- Buttons must be wide enough to draw edges, and
  1005. * text area must be tall enough to fit small caption font with a
  1006. * border above and below. Again, if we have to reset the height,
  1007. * reset the width as well?
  1008. */
  1009. lpnc->iSmCaptionWidth = max(lpnc->iSmCaptionWidth, cxEdge4);
  1010. lpnc->iSmCaptionHeight = max(lpnc->iSmCaptionHeight, gcySmCaptionFontChar + SYSMET(CYEDGE));
  1011. /*
  1012. * Menu -- Buttons must be wide enough to draw edges, and text
  1013. * area must be tall enough to fit menu font with underscore.
  1014. */
  1015. lpnc->iMenuWidth = max(lpnc->iMenuWidth, cxEdge4);
  1016. lpnc->iMenuHeight = max(lpnc->iMenuHeight, gcyMenuFontChar + gcyMenuFontExternLeading + SYSMET(CYEDGE));
  1017. /*
  1018. * SET UP SYSTEM METRIC VALUES
  1019. */
  1020. SetNCMetrics(lpnc);
  1021. }
  1022. if (!CreateBitmapStrip()) {
  1023. RIPMSG0(RIP_WARNING, "CreateBitmapStrip failed");
  1024. return FALSE;
  1025. }
  1026. return TRUE;
  1027. }
  1028. VOID SetMinMetrics(
  1029. PUNICODE_STRING pProfileUserName,
  1030. LPMINIMIZEDMETRICS lpmin)
  1031. {
  1032. MINIMIZEDMETRICS min;
  1033. if (!lpmin) {
  1034. /*
  1035. * Minimized
  1036. */
  1037. min.iWidth = MetricGetID(pProfileUserName,STR_MINWIDTH, 154);
  1038. min.iHorzGap = MetricGetID(pProfileUserName,STR_MINHORZGAP, 0);
  1039. min.iVertGap = MetricGetID(pProfileUserName,STR_MINVERTGAP, 0);
  1040. min.iArrange = MetricGetID(pProfileUserName,STR_MINARRANGE, ARW_BOTTOMLEFT | ARW_RIGHT);
  1041. lpmin = &min;
  1042. }
  1043. /*
  1044. * SANITY CHECK for metric values
  1045. */
  1046. /*
  1047. * Minimized window -- Text area must be >= 0, as must gap between
  1048. * windows horizontally and vertically.
  1049. */
  1050. lpmin->iWidth = max(lpmin->iWidth, 0);
  1051. lpmin->iHorzGap = max(lpmin->iHorzGap, 0);
  1052. lpmin->iVertGap = max(lpmin->iVertGap, 0);
  1053. lpmin->iArrange &= ARW_VALID;
  1054. /*
  1055. * Minimized size
  1056. */
  1057. SYSMET(CXMINIMIZED) = 2*SYSMET(CXFIXEDFRAME) + (int) lpmin->iWidth;
  1058. SYSMET(CYMINIMIZED) = 2*SYSMET(CYFIXEDFRAME) + SYSMET(CYSIZE);
  1059. SYSMET(CXMINSPACING) = SYSMET(CXMINIMIZED) + (int) lpmin->iHorzGap;
  1060. SYSMET(CYMINSPACING) = SYSMET(CYMINIMIZED) + (int) lpmin->iVertGap;
  1061. SYSMET(ARRANGE) = (int) lpmin->iArrange;
  1062. }
  1063. BOOL SetIconMetrics(
  1064. PUNICODE_STRING pProfileUserName,
  1065. LPICONMETRICS lpicon)
  1066. {
  1067. ICONMETRICS icon;
  1068. if (!SetIconFonts(pProfileUserName,lpicon)) {
  1069. RIPMSG0(RIP_WARNING, "SetIconMetrics failed in SetIconFonts");
  1070. return FALSE;
  1071. }
  1072. if (!lpicon) {
  1073. icon.iTitleWrap = MetricGetID(pProfileUserName,
  1074. STR_ICONTITLEWRAP, TRUE);
  1075. icon.iHorzSpacing = MetricGetID(pProfileUserName,
  1076. STR_ICONHORZSPACING,
  1077. (GreGetDeviceCaps(HDCBITS(), LOGPIXELSX) * 75) / 96);
  1078. icon.iVertSpacing = MetricGetID(pProfileUserName,
  1079. STR_ICONVERTSPACING,
  1080. (GreGetDeviceCaps(HDCBITS(), LOGPIXELSY) * 75) / 96);
  1081. lpicon = &icon;
  1082. }
  1083. /*
  1084. * SANITY CHECK for metric values
  1085. */
  1086. lpicon->iHorzSpacing = max(lpicon->iHorzSpacing, (int)SYSMET(CXICON));
  1087. lpicon->iVertSpacing = max(lpicon->iVertSpacing, (int)SYSMET(CYICON));
  1088. SYSMET(CXICONSPACING) = (int) lpicon->iHorzSpacing;
  1089. SYSMET(CYICONSPACING) = (int) lpicon->iVertSpacing;
  1090. SET_OR_CLEAR_PUDF(PUDF_ICONTITLEWRAP, lpicon->iTitleWrap);
  1091. return TRUE;
  1092. }
  1093. /***************************************************************************\
  1094. * xxxMB_FindLongestString
  1095. *
  1096. * History:
  1097. * 10-23-90 DarrinM Ported from Win 3.0 sources.
  1098. * 01-21-98 SamerA Renamed to xxx since it may leave the crit sec if
  1099. * a client LPK is installed.
  1100. \***************************************************************************/
  1101. UINT xxxMB_FindLongestString(HDC hdc)
  1102. {
  1103. UINT wRetVal;
  1104. int i, iMaxLen = 0, iNewMaxLen;
  1105. LPWSTR pszCurStr, szMaxStr;
  1106. SIZE sizeOneChar;
  1107. SIZE sizeMaxStr;
  1108. PTHREADINFO ptiCurrent = PtiCurrentShared();
  1109. /*
  1110. * Be sure that MBStrings are already loaded.
  1111. */
  1112. UserAssert(gpsi->MBStrings[0].szName[0] != TEXT('\0'));
  1113. /*
  1114. * We are assuming that the longest string is the widest one,
  1115. * which is not always true.
  1116. * What we really have to do is call PSMGetTextExtent for each string
  1117. * and get the max width.
  1118. * This behavior get rectified by workaround for bug #170582
  1119. * in CheckMsgFontDimensions(). Mhamid.
  1120. */
  1121. for (i = 0; i < MAX_SEB_STYLES; i++) {
  1122. pszCurStr = GETGPSIMBPSTR(i);
  1123. if ((iNewMaxLen = wcslen(pszCurStr)) > iMaxLen) {
  1124. iMaxLen = iNewMaxLen;
  1125. szMaxStr = pszCurStr;
  1126. }
  1127. }
  1128. /*
  1129. * Find the longest string
  1130. */
  1131. if (CALL_LPK(ptiCurrent)) {
  1132. xxxClientGetTextExtentPointW(hdc, (PWSTR)szOneChar, 1, &sizeOneChar);
  1133. } else {
  1134. GreGetTextExtentW(hdc, (PWSTR)szOneChar, 1, &sizeOneChar, GGTE_WIN3_EXTENT);
  1135. }
  1136. xxxPSMGetTextExtent(hdc, szMaxStr, iMaxLen, &sizeMaxStr);
  1137. wRetVal = (UINT)(sizeMaxStr.cx + (sizeOneChar.cx * 2));
  1138. return wRetVal;
  1139. }