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.

461 lines
13 KiB

  1. /* CUSTFONT.C
  2. **
  3. ** Copyright (C) Microsoft, 1993, All Rights Reserved.
  4. **
  5. ** History:
  6. **
  7. */
  8. #include "priv.h"
  9. #pragma hdrstop
  10. static struct
  11. {
  12. UINT wWidth;
  13. UINT wHeight;
  14. UINT wSizeFontId;
  15. UINT wStartPos;
  16. UINT wStartPix;
  17. } g;
  18. static UINT g_iCurPercent;
  19. static RECT g_rcRuler;
  20. static TCHAR g_szRulerDirections[200];
  21. static TCHAR g_szSample[100];
  22. static TCHAR g_szSampleFace[32];
  23. static int g_cxRulerDirections;
  24. static BOOL g_bTypeTimer = FALSE;
  25. static TCHAR szPctD[] = TEXT("%d");
  26. static TCHAR szPercentNum[] = TEXT("%d%%");
  27. #define NUM_DEFPERCENTS 5
  28. static UINT g_DefaultPercents[NUM_DEFPERCENTS] = {75, 100, 125, 150, 200};
  29. #define MAX_PERCENT 500
  30. #define MIN_PERCENT 20
  31. #define GETPERCENT(dpi) ((dpi * 100 + 50) / 96)
  32. #define GETDPI(percent) ((percent * 96 + 48) /100)
  33. #define UPDATE_CURPER 0x0001
  34. #define UPDATE_COMBO 0x0002
  35. #define UPDATE_SAMPLE 0x0004
  36. #define UPDATE_RULER 0x0008
  37. #define UPDATE_ALL 0x000F
  38. void NEAR PASCAL DrawRuler(HWND hDlg, LPDRAWITEMSTRUCT lpdis)
  39. {
  40. int nFact;
  41. RECT rc;
  42. HDC hdc;
  43. int nPixInch;
  44. int i, j;
  45. TCHAR szTemp[10];
  46. int nOldMode;
  47. hdc = lpdis->hDC;
  48. nOldMode = SetBkMode(hdc, TRANSPARENT);
  49. // use g_rcRuler to draw the ruler. it's already been spaced
  50. rc = g_rcRuler;
  51. // first, draw the directions
  52. i = rc.left + ((rc.right - rc.left) - g_cxRulerDirections)/2;
  53. nPixInch = GETDPI(g_iCurPercent);
  54. // draw the top and left edge of the ruler
  55. DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOPLEFT);
  56. // rest of drawing happens just below the top
  57. rc.top += ClassicGetSystemMetrics(SM_CYEDGE);
  58. nFact = 1;
  59. // draw one of the etch heights (1", 1/2", 1/4") per iteration
  60. for (j=0; j<3; ++j)
  61. {
  62. for (i=0; ; ++i)
  63. {
  64. rc.left = g_rcRuler.left + (j==0 ? i*nPixInch : (2*i+1)*nPixInch/nFact);
  65. if (rc.left >= g_rcRuler.right)
  66. {
  67. break;
  68. }
  69. DrawEdge(hdc, &rc, EDGE_ETCHED, BF_LEFT | BF_ADJUST);
  70. // dominant etch deserves a number
  71. if (j == 0)
  72. {
  73. TextOut(hdc, rc.left+1, rc.bottom-g.wHeight,
  74. szTemp, wsprintf(szTemp, szPctD, i));
  75. }
  76. }
  77. rc.bottom -= (rc.bottom - rc.top)/2;
  78. nFact *= 2;
  79. }
  80. SetBkMode(hdc, nOldMode);
  81. }
  82. void NEAR PASCAL CF_UpdateRuler(HWND hDlg)
  83. {
  84. RECT rc;
  85. HWND hwnd;
  86. /* Don't do this stuff if the dialog is not
  87. ** visible yet, or other windows will flash.
  88. */
  89. if (IsWindowVisible(hDlg))
  90. {
  91. // don't invalidate top and left because they never change.
  92. rc = g_rcRuler;
  93. rc.left += ClassicGetSystemMetrics(SM_CXEDGE);
  94. rc.top += ClassicGetSystemMetrics(SM_CYEDGE);
  95. hwnd = GetDlgItem(hDlg, IDC_CUSTOMRULER);
  96. InvalidateRect(hwnd, &rc, TRUE);
  97. UpdateWindow(hwnd);
  98. }
  99. }
  100. void NEAR PASCAL CF_ShowNewPercent(HWND hDlg, UINT uPer)
  101. {
  102. TCHAR szBuf[10];
  103. g_iCurPercent = uPer;
  104. wsprintf(szBuf, szPercentNum, uPer);
  105. SetWindowText(GetDlgItem(hDlg, IDC_CUSTOMCOMBO), szBuf);
  106. UpdateWindow(GetDlgItem(hDlg, IDC_CUSTOMCOMBO));
  107. }
  108. // Build lf with given face and height
  109. //
  110. int CALLBACK EnumProc(CONST LOGFONT *lplf, CONST TEXTMETRIC *lptm, DWORD nType, LPARAM lpData )
  111. {
  112. *(LPLOGFONT)lpData = *lplf;
  113. return FALSE;
  114. }
  115. HFONT CreateFontWithFace(HWND hwnd, int nHeight, LPCTSTR lpszFace)
  116. {
  117. LOGFONT lf;
  118. HDC hdc;
  119. hdc = GetDC(hwnd);
  120. if(hdc)
  121. {
  122. EnumFontFamilies(hdc, lpszFace, EnumProc, (LPARAM)&lf);
  123. ReleaseDC(hwnd,hdc);
  124. }
  125. lf.lfHeight = nHeight;
  126. lf.lfWidth = lf. lfEscapement = lf.lfOrientation = 0;
  127. return CreateFontIndirect(&lf);
  128. }
  129. void NEAR PASCAL CF_UpdateData(HWND hDlg, UINT uPer, UINT flags)
  130. {
  131. TCHAR szBuf[100];
  132. HFONT hfont;
  133. int i;
  134. HWND hwnd;
  135. int iDPI;
  136. if (flags & UPDATE_CURPER)
  137. {
  138. if (uPer == g_iCurPercent)
  139. return;
  140. if (uPer < MIN_PERCENT)
  141. uPer = MIN_PERCENT;
  142. else if (uPer > MAX_PERCENT)
  143. uPer = MAX_PERCENT;
  144. g_iCurPercent = uPer;
  145. }
  146. if (flags & UPDATE_COMBO)
  147. {
  148. hwnd = GetDlgItem(hDlg, IDC_CUSTOMCOMBO);
  149. wsprintf(szBuf, szPercentNum, g_iCurPercent);
  150. i = (int)SendMessage(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)szBuf);
  151. SendMessage(hwnd, CB_SETCURSEL, (WPARAM)i, 0L);
  152. if (i == -1)
  153. {
  154. SetWindowText(hwnd, szBuf);
  155. UpdateWindow(hwnd);
  156. }
  157. }
  158. if (flags & UPDATE_RULER)
  159. CF_UpdateRuler(hDlg);
  160. if (flags & UPDATE_SAMPLE)
  161. {
  162. iDPI = GETDPI(g_iCurPercent);
  163. // build and set string with DPI info
  164. hwnd = GetDlgItem(hDlg, IDC_CUSTOMSAMPLE);
  165. wsprintf(szBuf, g_szSample, (LPTSTR)g_szSampleFace, iDPI);
  166. SetWindowText(hwnd, szBuf);
  167. hfont = CreateFontWithFace(hwnd, -10 * iDPI / 72, g_szSampleFace);
  168. if (hfont)
  169. {
  170. hfont = (HFONT)SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, 1L);
  171. if (hfont)
  172. DeleteObject(hfont);
  173. }
  174. }
  175. }
  176. void NEAR PASCAL CF_ReadNewPercent(HWND hDlg)
  177. {
  178. TCHAR szBuf[10];
  179. LPTSTR pstr;
  180. UINT uPer = 0;
  181. GetWindowText(GetDlgItem(hDlg, IDC_CUSTOMCOMBO), szBuf, ARRAYSIZE(szBuf));
  182. pstr = szBuf;
  183. while (*pstr && (*pstr != TEXT('%')))
  184. {
  185. if (*pstr >= TEXT('0') && *pstr <= TEXT('9'))
  186. uPer = uPer * 10 + (*pstr - TEXT('0'));
  187. pstr++;
  188. }
  189. CF_UpdateData(hDlg, uPer, UPDATE_ALL);
  190. }
  191. void NEAR PASCAL CF_InitDialog(HWND hDlg, UINT uDPI)
  192. {
  193. HWND hwnd;
  194. HDC hdc;
  195. HFONT hfont;
  196. SIZE szSize;
  197. int i;
  198. TCHAR szBuf[10];
  199. int iCurSel;
  200. g_iCurPercent = GETPERCENT(uDPI);
  201. hwnd = GetDlgItem(hDlg, IDC_CUSTOMCOMBO);
  202. iCurSel = -1; // assume not in list
  203. for (i = 0; i < NUM_DEFPERCENTS; i++)
  204. {
  205. wsprintf(szBuf, szPercentNum, g_DefaultPercents[i]);
  206. SendMessage(hwnd, CB_INSERTSTRING, (WPARAM)i, (LPARAM)szBuf);
  207. SendMessage(hwnd, CB_SETITEMDATA, (WPARAM)i, g_DefaultPercents[i]);
  208. if (g_iCurPercent == g_DefaultPercents[i])
  209. iCurSel = i;
  210. }
  211. SendMessage(hwnd, CB_SETCURSEL, (WPARAM)iCurSel, 0L);
  212. if (iCurSel == -1)
  213. {
  214. wsprintf(szBuf, szPercentNum, g_iCurPercent);
  215. SetWindowText(hwnd, szBuf);
  216. }
  217. hdc = GetDC(hDlg);
  218. hfont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
  219. if (hfont)
  220. hfont = (HFONT) SelectObject(hdc, hfont);
  221. //dwSize = GetTextExtentPoint32(hdc, TEXT("0"), 1);
  222. GetTextExtentPoint32(hdc, TEXT("0"), 1, &szSize);
  223. g.wWidth = szSize.cx;
  224. g.wHeight = szSize.cy;
  225. LoadString(HINST_THISDLL, IDS_RULERDIRECTION, g_szRulerDirections, ARRAYSIZE(g_szRulerDirections));
  226. //g_cxRulerDirections = LOWORD(GetTextExtent(hdc, g_szRulerDirections, lstrlen(g_szRulerDirections)));
  227. GetTextExtentPoint32(hdc, g_szRulerDirections, lstrlen(g_szRulerDirections), &szSize);
  228. g_cxRulerDirections = szSize.cx;
  229. if (hfont)
  230. SelectObject(hdc, hfont);
  231. ReleaseDC(hDlg, hdc);
  232. // calculate the rectangle for the actual ruler drawing in relation
  233. // to its window
  234. GetClientRect(GetDlgItem(hDlg, IDC_CUSTOMRULER), &g_rcRuler);
  235. g_rcRuler.left += g.wWidth;
  236. g_rcRuler.right -= g.wWidth;
  237. // bottom offset like the sides
  238. g_rcRuler.bottom -= g.wWidth;
  239. LoadString(HINST_THISDLL, IDS_10PTSAMPLE, g_szSample, ARRAYSIZE(g_szSample));
  240. LoadString(HINST_THISDLL, IDS_10PTSAMPLEFACENAME, g_szSampleFace, ARRAYSIZE(g_szSampleFace));
  241. CF_UpdateData(hDlg, 0, UPDATE_SAMPLE);
  242. }
  243. /////////////////////////////////////////////////////////////////////////////
  244. const static DWORD FAR aCustFontHelpIds[] = {
  245. // IDC_NO_HELP_1, IDH_COMM_GROUPBOX,
  246. IDC_CUSTOMCOMBO, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_CUSTOMFONT_LISTBOX,
  247. IDC_CUSTOMRULER, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_CUSTOMFONT_RULER,
  248. IDC_CUSTOMSAMPLE,IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_CUSTOMFONT_SAMPLE,
  249. 0, 0
  250. };
  251. INT_PTR CALLBACK CustomFontDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
  252. {
  253. HFONT hfont;
  254. int i;
  255. switch (uMessage)
  256. {
  257. case WM_CREATE:
  258. break;
  259. case WM_INITDIALOG:
  260. CF_InitDialog(hDlg, (UINT)lParam);
  261. break;
  262. case WM_DESTROY:
  263. hfont = (HFONT)SendDlgItemMessage(hDlg, IDC_CUSTOMSAMPLE, WM_GETFONT, 0, 0L);
  264. if (hfont)
  265. DeleteObject(hfont);
  266. break;
  267. case WM_DRAWITEM:
  268. if (wParam == IDC_CUSTOMRULER)
  269. DrawRuler(hDlg, (LPDRAWITEMSTRUCT)lParam);
  270. break;
  271. case WM_TIMER:
  272. if (g_bTypeTimer)
  273. {
  274. KillTimer(hDlg, 13);
  275. g_bTypeTimer = FALSE;
  276. CF_ReadNewPercent(hDlg);
  277. }
  278. break;
  279. case WM_HELP:
  280. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, TEXT("display.hlp"), HELP_WM_HELP,
  281. (DWORD_PTR)(LPTSTR)aCustFontHelpIds);
  282. break;
  283. case WM_CONTEXTMENU:
  284. WinHelp((HWND)wParam, TEXT("display.hlp"), HELP_CONTEXTMENU,
  285. (DWORD_PTR)(LPTSTR)aCustFontHelpIds);
  286. break;
  287. case WM_COMMAND:
  288. switch (LOWORD(wParam))
  289. {
  290. case IDOK:
  291. EndDialog(hDlg, GETDPI(g_iCurPercent));
  292. break;
  293. case IDCANCEL:
  294. EndDialog(hDlg, 0);
  295. break;
  296. case IDC_CUSTOMRULER:
  297. switch (HIWORD(wParam))
  298. {
  299. case DSN_NCCREATE:
  300. SetWindowLong((HWND)lParam, GWL_EXSTYLE,
  301. GetWindowLong((HWND)lParam, GWL_EXSTYLE) | WS_EX_WINDOWEDGE);
  302. break;
  303. case DSN_BEGINDRAG:
  304. // Set the focus to the corresponding edit ctl
  305. SendMessage(hDlg, WM_NEXTDLGCTL,
  306. (WPARAM)GetDlgItem(hDlg, IDC_CUSTOMCOMBO), 1L);
  307. SendMessage((HWND)lParam, DSM_DRAGPOS, 0, (LPARAM)&(g.wStartPos));
  308. if ((int)g.wStartPos < g_rcRuler.left)
  309. {
  310. g.wStartPos = g_rcRuler.left;
  311. }
  312. g.wStartPix = g_iCurPercent;
  313. break;
  314. case DSN_DRAGGING:
  315. {
  316. UINT wNow, wPix;
  317. POINT pt;
  318. //wNow = LOWORD(SendMessage((HWND)lParam, DSM_DRAGPOS, 0, 0L));
  319. SendMessage((HWND)lParam, DSM_DRAGPOS, 0, (LPARAM)&pt);
  320. wNow = pt.x;
  321. if ((int)wNow < g_rcRuler.left)
  322. {
  323. wNow = g_rcRuler.left;
  324. }
  325. wPix = LOWORD((DWORD)wNow*g.wStartPix/g.wStartPos);
  326. if (wPix < MIN_PERCENT)
  327. {
  328. wPix = MIN_PERCENT;
  329. }
  330. if (wPix > MAX_PERCENT)
  331. {
  332. wPix = MAX_PERCENT;
  333. }
  334. if (wPix != g_iCurPercent)
  335. {
  336. CF_ShowNewPercent(hDlg, wPix);
  337. CF_UpdateRuler(hDlg);
  338. }
  339. break;
  340. }
  341. case DSN_ENDDRAG:
  342. CF_UpdateData(hDlg, 0, UPDATE_COMBO | UPDATE_SAMPLE);
  343. break;
  344. default:
  345. break;
  346. }
  347. break;
  348. case IDC_CUSTOMCOMBO:
  349. switch(HIWORD(wParam))
  350. {
  351. case CBN_SELCHANGE:
  352. i = (int)SendDlgItemMessage(hDlg, IDC_CUSTOMCOMBO, CB_GETCURSEL, 0, 0L);
  353. if (i != CB_ERR)
  354. {
  355. i = LOWORD(SendDlgItemMessage(hDlg, IDC_CUSTOMCOMBO, CB_GETITEMDATA, (WPARAM)i, 0L));
  356. CF_UpdateData(hDlg, (UINT)i, UPDATE_CURPER | UPDATE_SAMPLE | UPDATE_RULER);
  357. }
  358. break;
  359. case CBN_EDITCHANGE:
  360. if (g_bTypeTimer)
  361. {
  362. KillTimer(hDlg, 13);
  363. }
  364. g_bTypeTimer = TRUE;
  365. SetTimer(hDlg, 13, 500, NULL);
  366. break;
  367. }
  368. break;
  369. default:
  370. return(FALSE);
  371. }
  372. break;
  373. default:
  374. return(FALSE);
  375. }
  376. return(TRUE);
  377. }