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.

968 lines
28 KiB

  1. #include "precomp.h"
  2. #include "adjustui.h"
  3. #pragma warning(disable: 4244) // disable loss of data warning since we do so
  4. // much casting in this file
  5. #pragma pack(push, 2)
  6. typedef struct tagDLGTEMPLATEEX {
  7. WORD dlgVer;
  8. WORD signature;
  9. DWORD helpID;
  10. DWORD exStyle;
  11. DWORD style;
  12. WORD cDlgItems;
  13. short x;
  14. short y;
  15. short cx;
  16. short cy;
  17. } DLGTEMPLATEEX, *PDLGTEMPLATEEX;
  18. typedef const DLGTEMPLATEEX* PCDLGTEMPLATEEX;
  19. typedef struct {
  20. DWORD helpID;
  21. DWORD exStyle;
  22. DWORD style;
  23. short x;
  24. short y;
  25. short cx;
  26. short cy;
  27. WORD id;
  28. WORD reserved;
  29. } DLGITEMTEMPLATEEX, *PDLGITEMTEMPLATEEX;
  30. typedef const DLGITEMTEMPLATEEX* PCDLGITEMTEMPLATEEX;
  31. #pragma pack(pop)
  32. // globals for banner
  33. HBITMAP g_hBannerBmp = NULL;
  34. HFONT g_hFont = NULL;
  35. static HWND s_hBannerWnd = NULL;
  36. static WNDPROC s_lpfnBannerTextCtrlProc = NULL;
  37. static HWND s_hBannerText = NULL;
  38. TCHAR s_szBannerText[MAX_PATH];
  39. static WNDPROC s_lpfnPSWndProc = NULL;
  40. // PrepareDlgTemplate and ChangeDlgTemplateFont helpers
  41. BOOL getBitmapDimensions(HINSTANCE hinstBmp, UINT nID, PSIZE psizeBmp);
  42. BOOL mapPixelsToDlgUnits(const LOGFONT *plf, PSIZE psize);
  43. BOOL createStaticControl(PCSTATICCTRL pCtrl, BOOL fEx, PVOID *ppvDIT, PDWORD pcbDIT);
  44. HRESULT getDlgTemplateSize(LPCVOID pvDlg, LPDWORD pcbDlg);
  45. BOOL loadDialogTemplate (HINSTANCE hinstDlg, UINT nID, PVOID *ppvDT, PDWORD pcbDT);
  46. PBYTE skipDlgString(PBYTE pb);
  47. PBYTE alignDWORD(PBYTE pb);
  48. // IsTahomaFontExist helpers
  49. int CALLBACK enumFontFamExProc(ENUMLOGFONTEX *, NEWTEXTMETRICEX *, int, LPARAM lParam);
  50. // PropSheetProc helpers
  51. void initializeBannerTextCtrlFont(HWND hWnd, INT nId);
  52. BOOL CALLBACK bannerTextCtrlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  53. void paintBmpInHdcRect(HBITMAP hBmp, HDC hDC, RECT rect);
  54. void handleEraseBkgndMsg(HWND hDlg, HDC hDC);
  55. BOOL CALLBACK propertySheetWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  56. HRESULT PrepareDlgTemplate(PCMODIFYDLGTEMPLATE pmdt, LPCVOID pvDlg, PVOID *ppvDT, LPDWORD pcbDlg)
  57. {
  58. LOGFONT lf;
  59. SIZE sizeBmpOffset;
  60. PCDLGTEMPLATEEX pdt2;
  61. LPCDLGTEMPLATE pdt; // for some weird reason there is no PCDLGTEMPLATE
  62. PDLGITEMTEMPLATEEX pdit2;
  63. PDLGITEMTEMPLATE pdit;
  64. PBYTE pb;
  65. HRESULT hr;
  66. DWORD cbDlg;
  67. WORD cDlgItems,
  68. cbCreateParams;
  69. BOOL fEx,
  70. fResult;
  71. USES_CONVERSION;
  72. //----- Initialization and parameter validation -----
  73. if (pmdt == NULL)
  74. return E_INVALIDARG;
  75. if (pmdt->hinst == NULL)
  76. return E_INVALIDARG;
  77. if (pmdt->scBmpCtrl.nCtrlType == CTRL_BITMAP && pmdt->scBmpCtrl.nID == 0)
  78. return E_INVALIDARG;
  79. if (pvDlg == NULL)
  80. return E_INVALIDARG;
  81. if (ppvDT == NULL)
  82. return E_POINTER;
  83. *ppvDT = NULL;
  84. if (pcbDlg == NULL)
  85. return E_INVALIDARG;
  86. *pcbDlg = 0;
  87. hr = getDlgTemplateSize(pvDlg, &cbDlg);
  88. if (FAILED(hr))
  89. return hr;
  90. ZeroMemory(&lf, sizeof(lf));
  91. //----- Resource allocation -----
  92. *ppvDT = CoTaskMemAlloc(cbDlg * 2);
  93. if (*ppvDT == NULL)
  94. return E_OUTOFMEMORY;
  95. ZeroMemory(*ppvDT, cbDlg * 2);
  96. hr = S_OK;
  97. //----- Parse through Dialog Template -----
  98. UINT nStyleOffset, nDlgItemsOffset,
  99. nWidthOffset, nHeightOffset;
  100. pdt = NULL;
  101. pdt2 = (PCDLGTEMPLATEEX)pvDlg; // assume extended style
  102. if (pdt2->signature == 0xFFFF) {
  103. if (pdt2->dlgVer != 1)
  104. return E_UNEXPECTED; // Chicago sanity check
  105. nStyleOffset = (PBYTE)&pdt2->style - (PBYTE)pdt2;
  106. nDlgItemsOffset = (PBYTE)&pdt2->cDlgItems - (PBYTE)pdt2;
  107. nWidthOffset = (PBYTE)&pdt2->cx - (PBYTE)pdt2;
  108. nHeightOffset = (PBYTE)&pdt2->cy - (PBYTE)pdt2;
  109. pb = (PBYTE)(pdt2 + 1);
  110. fEx = TRUE;
  111. }
  112. else {
  113. pdt = (LPCDLGTEMPLATE)pvDlg;
  114. pdt2 = NULL;
  115. nStyleOffset = (PBYTE)&pdt->style - (PBYTE)pdt;
  116. nDlgItemsOffset = (PBYTE)&pdt->cdit - (PBYTE)pdt;
  117. nWidthOffset = (PBYTE)&pdt->cx - (PBYTE)pdt;
  118. nHeightOffset = (PBYTE)&pdt->cy - (PBYTE)pdt;
  119. pb = (PBYTE)(pdt + 1);
  120. fEx = FALSE;
  121. }
  122. // skip over menu, window class and window text
  123. pb = skipDlgString(pb);
  124. pb = skipDlgString(pb);
  125. pb = skipDlgString(pb);
  126. // skip over font info: point size and typeface name
  127. if (((*(PDWORD)((PBYTE)pvDlg + nStyleOffset)) & DS_SETFONT) != 0) {
  128. if (fEx) {
  129. lf.lfHeight = *(PWORD)pb; pb += sizeof(WORD);
  130. lf.lfWeight = *(PWORD)pb; pb += sizeof(WORD);
  131. lf.lfItalic = (BYTE)*(PWORD)pb; pb += sizeof(WORD);
  132. }
  133. else {
  134. lf.lfHeight = *(PWORD)pb; pb += sizeof(WORD);
  135. }
  136. StrCpyN(lf.lfFaceName, W2CT((LPCWSTR)pb), LF_FACESIZE);
  137. pb = skipDlgString(pb);
  138. }
  139. // finally, adjust to DWORD boundary
  140. pb = alignDWORD(pb);
  141. //----- Make new sence out of Dialog Template -----
  142. SIZE sizeIncrease;
  143. DWORD cbDlgTemplate;
  144. cbDlgTemplate = pb - (PBYTE)pvDlg;
  145. CopyMemory(*ppvDT, pvDlg, cbDlgTemplate);
  146. fResult = getBitmapDimensions(pmdt->hinst, pmdt->scBmpCtrl.nID, &sizeBmpOffset);
  147. if (!fResult) {
  148. hr = E_FAIL;
  149. goto Exit;
  150. }
  151. // ok, they are in dialog units now, kinda, really ;-)
  152. fResult = mapPixelsToDlgUnits(&lf, &sizeBmpOffset);
  153. if (!fResult) {
  154. hr = E_FAIL;
  155. goto Exit;
  156. }
  157. sizeIncrease.cx = sizeIncrease.cy = 0;
  158. if (pmdt->sizeCtrlsOffset.cx != 0)
  159. sizeIncrease.cx = pmdt->scBmpCtrl.rect.left + sizeBmpOffset.cx + pmdt->sizeCtrlsOffset.cx;
  160. if (pmdt->sizeCtrlsOffset.cy != 0)
  161. sizeIncrease.cy = pmdt->scBmpCtrl.rect.top + sizeBmpOffset.cy + pmdt->sizeCtrlsOffset.cy;
  162. *(PWORD)((PBYTE)*ppvDT + nDlgItemsOffset) += 2;
  163. *(PWORD)((PBYTE)*ppvDT + nWidthOffset) += (WORD)sizeIncrease.cx;
  164. *(PWORD)((PBYTE)*ppvDT + nHeightOffset) += (WORD)sizeIncrease.cy;
  165. //----- Add control with the bitmap -----
  166. PVOID pvCtrl;
  167. DWORD cbCtrl;
  168. DWORD cbCtrlsOffset;
  169. fResult = createStaticControl(&pmdt->scBmpCtrl, fEx, &pvCtrl, &cbCtrl);
  170. if (!fResult) {
  171. hr = E_FAIL;
  172. goto Exit;
  173. }
  174. CopyMemory((PBYTE)*ppvDT + cbDlgTemplate, pvCtrl, cbCtrl);
  175. cbCtrlsOffset = cbCtrl;
  176. ASSERT(pvCtrl != NULL);
  177. CoTaskMemFree(pvCtrl);
  178. //----- Add static text control -----
  179. STATICCTRL scTextCtrl;
  180. scTextCtrl = pmdt->scTextCtrl;
  181. scTextCtrl.rect.left = 7;
  182. scTextCtrl.rect.top = (sizeBmpOffset.cy / 2) - 11;
  183. scTextCtrl.rect.right = sizeBmpOffset.cx - 7;
  184. scTextCtrl.rect.bottom = scTextCtrl.rect.top + 18;
  185. fResult = createStaticControl(&scTextCtrl, fEx, &pvCtrl, &cbCtrl);
  186. if (!fResult) {
  187. hr = E_FAIL;
  188. goto Exit;
  189. }
  190. CopyMemory((PBYTE)*ppvDT + cbDlgTemplate + cbCtrlsOffset, pvCtrl, cbCtrl);
  191. cbCtrlsOffset += cbCtrl;
  192. ASSERT(pvCtrl != NULL);
  193. CoTaskMemFree(pvCtrl);
  194. //----- Parse through Dialog Item Templates -----
  195. cDlgItems = *(PWORD)((PBYTE)pvDlg + nDlgItemsOffset);
  196. if (cDlgItems > 0) {
  197. ASSERT(cbDlg > cbDlgTemplate);
  198. CopyMemory((PBYTE)*ppvDT + cbDlgTemplate + cbCtrlsOffset, pb, cbDlg - cbDlgTemplate);
  199. pb = (PBYTE)*ppvDT + cbDlgTemplate + cbCtrlsOffset;
  200. while (cDlgItems-- > 0) {
  201. pdit = NULL; pdit2 = NULL;
  202. if (fEx) {
  203. pdit2 = (PDLGITEMTEMPLATEEX)pb;
  204. if (pmdt->sizeCtrlsOffset.cx != 0)
  205. pdit2->x += (WORD)sizeIncrease.cx;
  206. if (pmdt->sizeCtrlsOffset.cy != 0)
  207. pdit2->y += (WORD)sizeIncrease.cy;
  208. }
  209. else {
  210. pdit = (PDLGITEMTEMPLATE)pb;
  211. if (pmdt->sizeCtrlsOffset.cx != 0)
  212. pdit->x += (WORD)sizeIncrease.cx;
  213. if (pmdt->sizeCtrlsOffset.cy != 0)
  214. pdit->y += (WORD)sizeIncrease.cy;
  215. }
  216. pb += fEx ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE);
  217. // skip over window class and window text
  218. pb = skipDlgString(pb);
  219. pb = skipDlgString(pb);
  220. // skip create parameters
  221. cbCreateParams = *((PWORD)pb);
  222. if (fEx)
  223. pb += sizeof(WORD) + cbCreateParams;
  224. else
  225. pb += cbCreateParams > 0 ? cbCreateParams : sizeof(WORD);
  226. // point at the next dialog item
  227. pb = alignDWORD(pb);
  228. }
  229. }
  230. *pcbDlg = cbDlg + cbCtrlsOffset;
  231. Exit:
  232. if (FAILED(hr)) {
  233. CoTaskMemFree(*ppvDT);
  234. *ppvDT = NULL;
  235. }
  236. return hr;
  237. }
  238. HRESULT SetDlgTemplateFont(HINSTANCE hInst, UINT nDlgID, const LOGFONT *plf, PVOID *ppvDT)
  239. {
  240. PCDLGTEMPLATEEX pdt2;
  241. LPCDLGTEMPLATE pdt; // for some weird reason there is no PCDLGTEMPLATE
  242. PBYTE pb;
  243. HRESULT hr;
  244. PVOID pvDlg;
  245. DWORD cbDlg;
  246. BOOL fEx,
  247. fResult;
  248. USES_CONVERSION;
  249. //----- Initialization and parameter validation -----
  250. if (plf == NULL || *plf->lfFaceName == TEXT('\0'))
  251. return E_INVALIDARG;
  252. if (plf->lfHeight == 0)
  253. return E_INVALIDARG;
  254. if (ppvDT == NULL)
  255. return E_POINTER;
  256. *ppvDT = NULL;
  257. //----- Resource allocation -----
  258. fResult = loadDialogTemplate(hInst, nDlgID, &pvDlg, &cbDlg);
  259. if (!fResult)
  260. return E_FAIL;
  261. *ppvDT = CoTaskMemAlloc(cbDlg * 2);
  262. if (*ppvDT == NULL)
  263. return E_OUTOFMEMORY;
  264. ZeroMemory(*ppvDT, cbDlg * 2);
  265. hr = S_OK;
  266. //----- Parse through Dialog Template -----
  267. PBYTE pbDest;
  268. DWORD cbSize;
  269. UINT nStyleOffset;
  270. pdt = NULL;
  271. pdt2 = (PCDLGTEMPLATEEX)pvDlg; // assume extended style
  272. if (pdt2->signature == 0xFFFF) {
  273. if (pdt2->dlgVer != 1)
  274. return E_UNEXPECTED; // Chicago sanity check
  275. nStyleOffset = (PBYTE)&pdt2->style - (PBYTE)pdt2;
  276. pb = (PBYTE)(pdt2 + 1);
  277. fEx = TRUE;
  278. }
  279. else {
  280. pdt = (LPCDLGTEMPLATE)pvDlg;
  281. pdt2 = NULL;
  282. nStyleOffset = (PBYTE)&pdt->style - (PBYTE)pdt;
  283. pb = (PBYTE)(pdt + 1);
  284. fEx = FALSE;
  285. }
  286. // skip over menu, window class and window text
  287. pb = skipDlgString(pb);
  288. pb = skipDlgString(pb);
  289. pb = skipDlgString(pb);
  290. cbSize = pb - (PBYTE)pvDlg;
  291. CopyMemory(*ppvDT, pvDlg, cbSize);
  292. pbDest = (PBYTE)*ppvDT + cbSize;
  293. // change font info: point size and typeface name
  294. if (((*(PDWORD)((PBYTE)pvDlg + nStyleOffset)) & DS_SETFONT) != 0) {
  295. UINT nLen;
  296. if (fEx) {
  297. *(PWORD)pbDest = (int)plf->lfHeight;
  298. pb += 3 * sizeof(WORD);
  299. pbDest += 3 * sizeof(WORD);
  300. }
  301. else {
  302. *(PWORD)pbDest = (int)plf->lfHeight;
  303. pb += sizeof(WORD);
  304. pbDest += sizeof(WORD);
  305. }
  306. nLen = StrLen(plf->lfFaceName);
  307. CopyMemory(pbDest, T2CW(plf->lfFaceName), (nLen + 1)*sizeof(WCHAR));
  308. pb = skipDlgString(pb); // don't know the length of the old font
  309. //pbDest += (nLen + 1) * sizeof(WCHAR); // know the length of the new font already
  310. pbDest = skipDlgString(pbDest);
  311. }
  312. // finally, adjust to DWORD boundary
  313. pb = alignDWORD(pb);
  314. pbDest = alignDWORD(pbDest);
  315. // copy rest of the template
  316. CopyMemory(pbDest, pb, cbDlg - (pb - (PBYTE)pvDlg));
  317. return hr;
  318. }
  319. BOOL IsTahomaFontExist(HWND hWnd)
  320. {
  321. static fFontExist = FALSE;
  322. static fFontChecked = FALSE;
  323. LOGFONT lf;
  324. HDC hDC;
  325. if (!fFontChecked)
  326. {
  327. hDC = GetDC(hWnd);
  328. ZeroMemory(&lf, sizeof(lf));
  329. lf.lfCharSet = DEFAULT_CHARSET;
  330. StrCpy(lf.lfFaceName, TEXT("Tahoma"));
  331. EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)enumFontFamExProc, (LPARAM)&fFontExist, 0);
  332. ReleaseDC(hWnd, hDC);
  333. fFontChecked = TRUE;
  334. }
  335. return fFontExist;
  336. }
  337. int CALLBACK PropSheetProc(HWND hDlg, UINT uMsg, LPARAM lParam)
  338. {
  339. MODIFYDLGTEMPLATE mdt;
  340. LPVOID pvDlg;
  341. DWORD cbDlg;
  342. if (uMsg == PSCB_PRECREATE)
  343. {
  344. ZeroMemory(&mdt, sizeof(mdt));
  345. mdt.hinst = g_rvInfo.hInst;
  346. mdt.sizeCtrlsOffset.cy = -9;
  347. // bitmap control parameters
  348. mdt.scBmpCtrl.nCtrlType = CTRL_BITMAP;
  349. mdt.scBmpCtrl.nID = IDB_WIZARD;
  350. mdt.scBmpCtrl.nCtrlID = IDC_BANNERBMPCTRL;
  351. // text control parameters
  352. mdt.scTextCtrl.nCtrlType = CTRL_TEXT;
  353. mdt.scTextCtrl.nCtrlID = IDC_BANNERTXTCTRL;
  354. if (FAILED(PrepareDlgTemplate(&mdt, (LPCVOID)lParam, &pvDlg, &cbDlg)))
  355. return 1;
  356. // replace the old template
  357. CopyMemory((LPVOID)lParam, pvDlg, cbDlg);
  358. CoTaskMemFree(pvDlg);
  359. // take out the context help button
  360. if( lParam )
  361. {
  362. DLGTEMPLATE *pDlgTemplate;
  363. DLGTEMPLATEEX *pDlgTemplateEx;
  364. pDlgTemplateEx = (DLGTEMPLATEEX *)lParam;
  365. if (pDlgTemplateEx->signature == 0xFFFF)
  366. {
  367. if (pDlgTemplateEx->dlgVer == 1)
  368. pDlgTemplateEx->style &= ~DS_CONTEXTHELP;
  369. }
  370. else
  371. {
  372. pDlgTemplate = (DLGTEMPLATE *)lParam;
  373. pDlgTemplate->style &= ~DS_CONTEXTHELP;
  374. }
  375. }
  376. }
  377. else if (uMsg == PSCB_INITIALIZED)
  378. {
  379. // BUGBUG: (a-saship) for some reason the bitmap is not loaded within the static control,
  380. // hence force it to display the bitmap.
  381. s_hBannerWnd = GetDlgItem(hDlg, IDC_BANNERBMPCTRL);
  382. if (s_hBannerWnd)
  383. {
  384. g_hBannerBmp = LoadBitmap(g_rvInfo.hInst, MAKEINTRESOURCE(IDB_WIZARD));
  385. if (g_hBannerBmp)
  386. SendMessage(s_hBannerWnd, STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) g_hBannerBmp);
  387. }
  388. // initialize the text control to set the required font style and subclass it
  389. // so that it paints itself.
  390. s_hBannerText = GetDlgItem(hDlg, IDC_BANNERTXTCTRL);
  391. if (s_hBannerText)
  392. {
  393. initializeBannerTextCtrlFont(hDlg, IDC_BANNERTXTCTRL);
  394. //subclass the text control
  395. if(s_lpfnBannerTextCtrlProc == NULL)
  396. s_lpfnBannerTextCtrlProc = (WNDPROC)GetWindowLongPtr(s_hBannerText, GWLP_WNDPROC);
  397. SetWindowLongPtr(s_hBannerText, GWLP_WNDPROC, (LONG_PTR)bannerTextCtrlProc);
  398. }
  399. // subclass propertysheet window to draw the border and bitmap
  400. if(s_lpfnPSWndProc == NULL)
  401. s_lpfnPSWndProc = (WNDPROC)GetWindowLongPtr(hDlg, GWLP_WNDPROC);
  402. SetWindowLongPtr(hDlg, GWLP_WNDPROC, (LONG_PTR)propertySheetWndProc);
  403. }
  404. return 0;
  405. }
  406. void SetBannerText(HWND hDlg)
  407. {
  408. GetWindowText(hDlg, s_szBannerText, countof(s_szBannerText));
  409. InvalidateRect(s_hBannerWnd, NULL, TRUE);
  410. InvalidateRect(s_hBannerText, NULL, TRUE);
  411. }
  412. void ChangeBannerText(HWND hDlg)
  413. {
  414. SetWindowText(hDlg, s_szBannerText);
  415. InvalidateRect(s_hBannerWnd, NULL, TRUE);
  416. InvalidateRect(s_hBannerText, NULL, TRUE);
  417. }
  418. /////////////////////////////////////////////////////////////////////////////
  419. // Implementation helpers routines (private)
  420. //----- PrepareDlgTemplate and ChangeDlgTemplateFont helpers -----
  421. BOOL getBitmapDimensions(HINSTANCE hinstBmp, UINT nID, PSIZE psizeBmp)
  422. {
  423. BITMAP bm;
  424. HBITMAP hbmp;
  425. int iResult;
  426. if (hinstBmp == NULL)
  427. return FALSE;
  428. if (psizeBmp == NULL)
  429. return FALSE;
  430. psizeBmp->cx = psizeBmp->cy = 0;
  431. hbmp = (HBITMAP)LoadImage(hinstBmp, MAKEINTRESOURCE(nID), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_SHARED);
  432. if (hbmp == NULL)
  433. return FALSE;
  434. iResult = GetObject(hbmp, sizeof(bm), &bm);
  435. DeleteObject(hbmp);
  436. if (iResult == 0)
  437. return FALSE;
  438. psizeBmp->cx = bm.bmWidth;
  439. psizeBmp->cy = bm.bmHeight;
  440. return TRUE;
  441. }
  442. // BUGBUG: (andrewgu) Big, big bummer!
  443. // the limitation to this whole approach is that there is no easy way to convert pixels into
  444. // dlg units of not yet existent dialog. i looked at the code in user32 and there is way too
  445. // much stuff to try to duplicate here. for now i'm going to use rude and cruel method of
  446. // multipling it by 2/3 which is good enough for english systems (no matter big fonts or not).
  447. // will see if international or accessibility folks complain.
  448. BOOL mapPixelsToDlgUnits(const LOGFONT *plf, PSIZE psize)
  449. {
  450. if (plf == NULL)
  451. return FALSE;
  452. if (psize == NULL)
  453. return FALSE;
  454. psize->cx = MulDiv(psize->cx, 2, 3);
  455. psize->cy = MulDiv(psize->cy, 2, 3);
  456. return TRUE;
  457. }
  458. BOOL createStaticControl(PCSTATICCTRL pCtrl, BOOL fEx, PVOID *ppvDIT, PDWORD pcbDIT)
  459. {
  460. PDLGITEMTEMPLATEEX pdit2;
  461. PDLGITEMTEMPLATE pdit;
  462. DWORD dwStyle,
  463. cbCtrl;
  464. PBYTE pb;
  465. if (pCtrl == NULL)
  466. return FALSE;
  467. if ((pCtrl->nCtrlType != CTRL_BITMAP && pCtrl->nCtrlType != CTRL_TEXT) ||
  468. (pCtrl->nCtrlType == CTRL_BITMAP && pCtrl->nID == 0))
  469. return FALSE;
  470. if (ppvDIT == NULL)
  471. return FALSE;
  472. *ppvDIT = NULL;
  473. if (pcbDIT == NULL)
  474. return FALSE;
  475. *pcbDIT = 0;
  476. // REVIEW: (andrewgu) 4 * sizeof(DWORD) is for the extra stuff
  477. cbCtrl = sizeof(DLGITEMTEMPLATEEX) + 4 * sizeof(DWORD);
  478. dwStyle = pCtrl->dwStyle;
  479. if (dwStyle == 0)
  480. dwStyle = WS_VISIBLE | WS_CHILD | WS_GROUP;
  481. if (pCtrl->nCtrlType == CTRL_BITMAP)
  482. dwStyle |= SS_BITMAP;
  483. else if (pCtrl->nCtrlType == CTRL_TEXT)
  484. dwStyle |= SS_LEFT;
  485. *ppvDIT = CoTaskMemAlloc(cbCtrl);
  486. if (*ppvDIT == NULL)
  487. return FALSE;
  488. ZeroMemory(*ppvDIT, cbCtrl);
  489. pdit = NULL; pdit2 = NULL;
  490. if (fEx) {
  491. pdit2 = (PDLGITEMTEMPLATEEX)*ppvDIT;
  492. pdit2->helpID = 0xFFFFFFFF;
  493. pdit2->exStyle = 0;
  494. pdit2->style = dwStyle;
  495. pdit2->x = (short)pCtrl->rect.left;
  496. pdit2->y = (short)pCtrl->rect.top;
  497. pdit2->cx = (short)(pCtrl->rect.right - pCtrl->rect.left);
  498. pdit2->cy = (short)(pCtrl->rect.bottom - pCtrl->rect.top);
  499. pdit2->id = (short)pCtrl->nCtrlID;
  500. pb = (PBYTE)*ppvDIT + sizeof(DLGITEMTEMPLATEEX);
  501. }
  502. else {
  503. pdit = (PDLGITEMTEMPLATE)*ppvDIT;
  504. pdit->style = dwStyle;
  505. pdit->dwExtendedStyle = 0;
  506. pdit->x = (short)pCtrl->rect.left;
  507. pdit->y = (short)pCtrl->rect.top;
  508. pdit->cx = (short)(pCtrl->rect.right - pCtrl->rect.left);
  509. pdit->cy = (short)(pCtrl->rect.bottom - pCtrl->rect.top);
  510. pdit->id = (short)pCtrl->nCtrlID;
  511. pb = (PBYTE)*ppvDIT + sizeof(DLGITEMTEMPLATE);
  512. }
  513. // class
  514. *(PWORD)pb = 0xFFFF;
  515. pb += sizeof(WORD);
  516. *(PWORD)pb = 0x0082; // static
  517. pb += sizeof(WORD);
  518. // window text
  519. if(pCtrl->nCtrlType == CTRL_BITMAP) {
  520. *(PWORD)pb = 0xFFFF;
  521. pb += sizeof(WORD);
  522. *(PWORD)pb = (WORD)pCtrl->nID;
  523. pb += sizeof(WORD);
  524. }
  525. else
  526. // skip over one WORD, it's zero initialized already
  527. pb += sizeof(WORD);
  528. // empty create parameters
  529. pb += sizeof(WORD);
  530. pb = alignDWORD(pb);
  531. *pcbDIT = (UINT)(pb - (PBYTE)*ppvDIT);
  532. return TRUE;
  533. }
  534. HRESULT getDlgTemplateSize(LPCVOID pvDlg, LPDWORD pcbDlg)
  535. {
  536. PCDLGTEMPLATEEX pdt2;
  537. LPCDLGTEMPLATE pdt; // for some weird reason there is no PCDLGTEMPLATE
  538. PBYTE pb;
  539. WORD cDlgItems,
  540. cbCreateParams;
  541. BOOL fEx;
  542. //----- Initialization and parameter validation -----
  543. if (pvDlg == NULL)
  544. return E_INVALIDARG;
  545. if (pcbDlg == NULL)
  546. return E_INVALIDARG;
  547. *pcbDlg = 0;
  548. //----- Parse through Dialog Template -----
  549. UINT nStyleOffset, nDlgItemsOffset;
  550. pdt = NULL;
  551. pdt2 = (PCDLGTEMPLATEEX)pvDlg; // assume extended style
  552. if (pdt2->signature == 0xFFFF) {
  553. if (pdt2->dlgVer != 1)
  554. return E_UNEXPECTED; // Chicago sanity check
  555. nStyleOffset = (PBYTE)&pdt2->style - (PBYTE)pdt2;
  556. nDlgItemsOffset = (PBYTE)&pdt2->cDlgItems - (PBYTE)pdt2;
  557. pb = (PBYTE)(pdt2 + 1);
  558. fEx = TRUE;
  559. }
  560. else {
  561. pdt = (LPCDLGTEMPLATE)pvDlg;
  562. pdt2 = NULL;
  563. nStyleOffset = (PBYTE)&pdt->style - (PBYTE)pdt;
  564. nDlgItemsOffset = (PBYTE)&pdt->cdit - (PBYTE)pdt;
  565. pb = (PBYTE)(pdt + 1);
  566. fEx = FALSE;
  567. }
  568. // skip over menu, window class and window text
  569. pb = skipDlgString(pb);
  570. pb = skipDlgString(pb);
  571. pb = skipDlgString(pb);
  572. // skip over font info: point size and typeface name
  573. if (((*(PDWORD)((PBYTE)pvDlg + nStyleOffset)) & DS_SETFONT) != 0) {
  574. pb += fEx ? sizeof(WORD) * 3 : sizeof(WORD);
  575. pb = skipDlgString(pb);
  576. }
  577. // finally, adjust to DWORD boundary
  578. pb = alignDWORD(pb);
  579. //----- Parse through Dialog Item Templates -----
  580. cDlgItems = *(PWORD)((PBYTE)pvDlg + nDlgItemsOffset);
  581. if (cDlgItems > 0) {
  582. while (cDlgItems-- > 0) {
  583. pb += fEx ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE);
  584. // skip over window class and window text
  585. pb = skipDlgString(pb);
  586. pb = skipDlgString(pb);
  587. // skip create parameters
  588. cbCreateParams = *((PWORD)pb);
  589. if (fEx)
  590. pb += sizeof(WORD) + cbCreateParams;
  591. else
  592. pb += cbCreateParams > 0 ? cbCreateParams : sizeof(WORD);
  593. // point at the next dialog item
  594. pb = alignDWORD(pb);
  595. }
  596. }
  597. *pcbDlg = pb - (PBYTE)pvDlg;
  598. return S_OK;
  599. }
  600. BOOL loadDialogTemplate(HINSTANCE hinstDlg, UINT nID, PVOID *ppvDT, PDWORD pcbDT)
  601. {
  602. PVOID p;
  603. HANDLE h;
  604. if (hinstDlg == NULL)
  605. return FALSE;
  606. if (ppvDT == NULL)
  607. return FALSE;
  608. *ppvDT = NULL;
  609. if (pcbDT == NULL)
  610. return FALSE;
  611. *pcbDT = 0;
  612. h = FindResource(hinstDlg, MAKEINTRESOURCE(nID), RT_DIALOG);
  613. if (h == NULL)
  614. return FALSE;
  615. *pcbDT = SizeofResource(hinstDlg, (HRSRC)h);
  616. if (*pcbDT == 0)
  617. return FALSE;
  618. h = LoadResource(hinstDlg, (HRSRC)h);
  619. if (h == NULL)
  620. return FALSE;
  621. p = LockResource(h);
  622. if (p == NULL)
  623. return FALSE;
  624. *ppvDT = p;
  625. return TRUE;
  626. }
  627. inline PBYTE skipDlgString(PBYTE pb)
  628. {
  629. PWCHAR pwch;
  630. if (*((PWORD)pb) == 0xFFFF)
  631. return (pb + sizeof(DWORD));
  632. pwch = (PWCHAR)pb;
  633. while (*pwch++ != L'\0')
  634. ;
  635. return (PBYTE)pwch;
  636. }
  637. inline PBYTE alignDWORD(PBYTE pb)
  638. {
  639. return (PBYTE)(((UINT_PTR)pb + 3) & ~((UINT_PTR)3));
  640. }
  641. //----- IsTahomaFontExist helpers -----
  642. int CALLBACK enumFontFamExProc(ENUMLOGFONTEX *, NEWTEXTMETRICEX *, int, LPARAM lParam)
  643. {
  644. (*(LPBOOL)lParam) = TRUE;
  645. return 0;
  646. }
  647. //----- PropSheetProc helpers -----
  648. void initializeBannerTextCtrlFont(HWND hWnd, INT nId)
  649. {
  650. NONCLIENTMETRICS ncm = {0};
  651. TCHAR szFontSize[24];
  652. INT nBigFontSize = 0;
  653. LOGFONT BigBoldLogFont;
  654. BOOL fUpdateFont = TRUE;
  655. ZeroMemory(&BigBoldLogFont, sizeof(BigBoldLogFont));
  656. ncm.cbSize = sizeof(ncm);
  657. if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
  658. {
  659. BigBoldLogFont = ncm.lfMessageFont;
  660. fUpdateFont = FALSE;
  661. }
  662. BigBoldLogFont.lfWeight = FW_NORMAL;
  663. if (!LoadString(g_rvInfo.hInst, IDS_BANNERFONT, BigBoldLogFont.lfFaceName, LF_FACESIZE))
  664. StrCpy(BigBoldLogFont.lfFaceName, TEXT("Verdana"));
  665. if (LoadString(g_rvInfo.hInst, IDS_BANNERFONTSIZE, szFontSize, countof(szFontSize)))
  666. nBigFontSize = StrToInt(szFontSize);
  667. if (nBigFontSize < 18)
  668. nBigFontSize = 18;
  669. HDC hdc = GetDC(hWnd);
  670. if (hdc != NULL)
  671. {
  672. int dyLogPixPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
  673. BigBoldLogFont.lfHeight = -MulDiv(dyLogPixPerInch, nBigFontSize, 72);
  674. if (fUpdateFont)
  675. {
  676. TEXTMETRIC tm;
  677. GetTextMetrics(hdc, &tm); // get the current textmetrics
  678. BigBoldLogFont.lfCharSet = tm.tmCharSet;
  679. }
  680. g_hFont = CreateFontIndirect(&BigBoldLogFont);
  681. ReleaseDC(hWnd, hdc);
  682. if (g_hFont != NULL)
  683. {
  684. HWND hControl = GetDlgItem(hWnd, nId);
  685. if (hControl)
  686. SendMessage(hControl, WM_SETFONT, (WPARAM)g_hFont, 0);
  687. }
  688. }
  689. }
  690. BOOL CALLBACK bannerTextCtrlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  691. {
  692. if (uMsg == WM_PAINT)
  693. {
  694. PAINTSTRUCT ps;
  695. HDC hdc = BeginPaint(hWnd, &ps);
  696. int iBkModeOld = SetBkMode(hdc, TRANSPARENT);
  697. HFONT hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0);
  698. HFONT hfontOld = (HFONT)SelectObject(hdc, hfont);
  699. COLORREF rgbSav = SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
  700. RECT rect;
  701. GetClientRect(hWnd, &rect);
  702. DrawText(hdc, s_szBannerText, -1, &rect, DT_WORDBREAK | DT_LEFT);
  703. SetTextColor(hdc, rgbSav);
  704. SelectObject(hdc, hfontOld);
  705. SetBkMode(hdc, iBkModeOld);
  706. EndPaint(hWnd, &ps);
  707. return (FALSE);
  708. }
  709. if (uMsg == WM_ERASEBKGND)
  710. return (FALSE);
  711. return (CallWindowProc(s_lpfnBannerTextCtrlProc, hWnd, uMsg, wParam, lParam));
  712. }
  713. void paintBmpInHdcRect(HBITMAP hBmp, HDC hDC, RECT rect)
  714. {
  715. BITMAP bm;
  716. if(!GetObject(hBmp, sizeof(BITMAP), (LPVOID)(&bm)))
  717. return;
  718. HDC hdcMem = CreateCompatibleDC(hDC);
  719. SelectObject(hdcMem, hBmp);
  720. SetStretchBltMode(hDC, COLORONCOLOR);
  721. StretchBlt(hDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
  722. hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  723. DeleteDC(hdcMem);
  724. }
  725. void handleEraseBkgndMsg(HWND hDlg, HDC hDC)
  726. {
  727. RECT rectBmp;
  728. GetClientRect(GetDlgItem(hDlg, IDC_BANNERBMPCTRL), &rectBmp);
  729. RECT rect;
  730. GetClientRect(hDlg, &rect);
  731. rect.top = rectBmp.bottom;
  732. HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  733. HBRUSH hbrSav = (HBRUSH)SelectObject(hDC, hbr);
  734. Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);
  735. paintBmpInHdcRect(g_hBannerBmp, hDC, rectBmp);
  736. SelectObject(hDC, hbrSav);
  737. DeleteObject((HGDIOBJ)hbr);
  738. }
  739. BOOL CALLBACK propertySheetWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  740. {
  741. if (uMsg == WM_ERASEBKGND)
  742. {
  743. handleEraseBkgndMsg(hWnd, (HDC)wParam);
  744. return TRUE;
  745. }
  746. else if (uMsg == WM_SIZE)
  747. {
  748. HWND hBannerWnd = GetDlgItem(hWnd, IDC_BANNERBMPCTRL);
  749. // set the bitmap control width to the property sheet window width
  750. if (hBannerWnd)
  751. {
  752. RECT rectBmp;
  753. RECT rectText;
  754. GetClientRect(s_hBannerWnd, &rectBmp);
  755. SetWindowPos(s_hBannerWnd, HWND_TOP, 0, 0, LOWORD(lParam), rectBmp.bottom - rectBmp.top, SWP_NOMOVE | SWP_NOZORDER);
  756. GetClientRect(s_hBannerText, &rectText);
  757. SetWindowPos(s_hBannerText, HWND_TOP, 0, 0, LOWORD(lParam) - 14, rectText.bottom - rectText.top, SWP_NOMOVE | SWP_NOZORDER);
  758. }
  759. }
  760. return (CallWindowProc(s_lpfnPSWndProc, hWnd, uMsg, wParam, lParam));
  761. }