PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/Samples/Chap17/PickFont/PickFont.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 561 lines | 407 code | 128 blank | 26 comment | 15 complexity | fc2884b0692765d917813320080eee5e MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module PickFont;
  6. import core.memory;
  7. import core.runtime;
  8. import core.thread;
  9. import std.algorithm : max, min;
  10. import std.conv;
  11. import std.math;
  12. import std.range;
  13. import std.string;
  14. import std.utf : count, toUTFz;
  15. auto toUTF16z(S)(S s)
  16. {
  17. return toUTFz!(const(wchar)*)(s);
  18. }
  19. pragma(lib, "gdi32.lib");
  20. pragma(lib, "comdlg32.lib");
  21. import core.sys.windows.windef;
  22. import core.sys.windows.winuser;
  23. import core.sys.windows.wingdi;
  24. import core.sys.windows.winbase;
  25. import core.sys.windows.commdlg;
  26. import resource;
  27. string appName = "PickFont";
  28. string description = "PickFont: Create Logical Font";
  29. HINSTANCE hinst;
  30. extern (Windows)
  31. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  32. {
  33. int result;
  34. try
  35. {
  36. Runtime.initialize();
  37. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  38. Runtime.terminate();
  39. }
  40. catch (Throwable o)
  41. {
  42. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  43. result = 0;
  44. }
  45. return result;
  46. }
  47. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  48. {
  49. hinst = hInstance;
  50. HACCEL hAccel;
  51. HWND hwnd;
  52. MSG msg;
  53. WNDCLASS wndclass;
  54. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  55. wndclass.lpfnWndProc = &WndProc;
  56. wndclass.cbClsExtra = 0;
  57. wndclass.cbWndExtra = 0;
  58. wndclass.hInstance = hInstance;
  59. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  60. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  61. wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  62. wndclass.lpszMenuName = appName.toUTF16z;
  63. wndclass.lpszClassName = appName.toUTF16z;
  64. if (!RegisterClass(&wndclass))
  65. {
  66. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  67. return 0;
  68. }
  69. hwnd = CreateWindow(appName.toUTF16z, // window class name
  70. description.toUTF16z, // window caption
  71. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, // window style
  72. CW_USEDEFAULT, // initial x position
  73. CW_USEDEFAULT, // initial y position
  74. CW_USEDEFAULT, // initial x size
  75. CW_USEDEFAULT, // initial y size
  76. NULL, // parent window handle
  77. NULL, // window menu handle
  78. hInstance, // program instance handle
  79. NULL); // creation parameters
  80. ShowWindow(hwnd, iCmdShow);
  81. UpdateWindow(hwnd);
  82. while (GetMessage(&msg, NULL, 0, 0))
  83. {
  84. if (hdlg == null || !IsDialogMessage(hdlg, &msg))
  85. {
  86. TranslateMessage(&msg);
  87. DispatchMessage(&msg);
  88. }
  89. }
  90. return msg.wParam;
  91. }
  92. struct DLGPARAMS
  93. {
  94. int iDevice, iMapMode;
  95. BOOL fMatchAspect;
  96. BOOL fAdvGraphics;
  97. LOGFONT lf;
  98. TEXTMETRIC tm;
  99. TCHAR[LF_FULLFACESIZE] szFaceName;
  100. }
  101. // Formatting for BCHAR fields of TEXTMETRIC structure
  102. enum BCHARFORM = "0x%04X";
  103. HWND hdlg;
  104. extern (Windows)
  105. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  106. {
  107. scope (failure) assert(0);
  108. static DLGPARAMS dp;
  109. dstring szText = "ABCDE abcde ÀÁÂÃÄÅ àáâãäå";
  110. HDC hdc;
  111. PAINTSTRUCT ps;
  112. RECT rect;
  113. switch (message)
  114. {
  115. case WM_CREATE:
  116. dp.iDevice = IDM_DEVICE_SCREEN;
  117. hdlg = CreateDialogParam((cast(LPCREATESTRUCT)lParam).hInstance,
  118. appName.toUTF16z, hwnd, &DlgProc, cast(LPARAM)&dp);
  119. return 0;
  120. case WM_SETFOCUS:
  121. SetFocus(hdlg);
  122. return 0;
  123. case WM_COMMAND:
  124. switch (LOWORD(wParam))
  125. {
  126. case IDM_DEVICE_SCREEN:
  127. case IDM_DEVICE_PRINTER:
  128. CheckMenuItem(GetMenu(hwnd), dp.iDevice, MF_UNCHECKED);
  129. dp.iDevice = LOWORD(wParam);
  130. CheckMenuItem(GetMenu(hwnd), dp.iDevice, MF_CHECKED);
  131. SendMessage(hwnd, WM_COMMAND, IDOK, 0);
  132. return 0;
  133. default:
  134. }
  135. break;
  136. case WM_PAINT:
  137. hdc = BeginPaint(hwnd, &ps);
  138. // Set graphics mode so escapement works in Windows NT
  139. SetGraphicsMode(hdc, dp.fAdvGraphics ? GM_ADVANCED : GM_COMPATIBLE);
  140. // Set the mapping mode and the mapper flag
  141. MySetMapMode(hdc, dp.iMapMode);
  142. SetMapperFlags(hdc, dp.fMatchAspect);
  143. // Find the point to begin drawing text
  144. GetClientRect(hdlg, &rect);
  145. rect.bottom += 1;
  146. DPtoLP(hdc, cast(PPOINT)&rect, 2);
  147. // Create and select the font; display the text
  148. SelectObject(hdc, CreateFontIndirect(&dp.lf));
  149. TextOut(hdc, rect.left, rect.bottom, to!string(szText).toUTF16z, szText.count);
  150. DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
  151. EndPaint(hwnd, &ps);
  152. return 0;
  153. case WM_DESTROY:
  154. PostQuitMessage(0);
  155. return 0;
  156. default:
  157. }
  158. return DefWindowProc(hwnd, message, wParam, lParam);
  159. }
  160. extern (Windows)
  161. BOOL DlgProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
  162. {
  163. static DLGPARAMS* pdp;
  164. static PRINTDLG pd = PRINTDLG(PRINTDLG.sizeof);
  165. HDC hdcDevice;
  166. HFONT hFont;
  167. switch (message)
  168. {
  169. case WM_INITDIALOG:
  170. // Save pointer to dialog-parameters structure in WndProc
  171. pdp = cast(DLGPARAMS*)lParam;
  172. SendDlgItemMessage(hdlg, IDC_LF_FACENAME, EM_LIMITTEXT,
  173. LF_FACESIZE - 1, 0);
  174. CheckRadioButton(hdlg, IDC_OUT_DEFAULT, IDC_OUT_OUTLINE,
  175. IDC_OUT_DEFAULT);
  176. CheckRadioButton(hdlg, IDC_DEFAULT_QUALITY, IDC_PROOF_QUALITY,
  177. IDC_DEFAULT_QUALITY);
  178. CheckRadioButton(hdlg, IDC_DEFAULT_PITCH, IDC_VARIABLE_PITCH,
  179. IDC_DEFAULT_PITCH);
  180. CheckRadioButton(hdlg, IDC_FF_DONTCARE, IDC_FF_DECORATIVE,
  181. IDC_FF_DONTCARE);
  182. CheckRadioButton(hdlg, IDC_MM_TEXT, IDC_MM_LOGTWIPS,
  183. IDC_MM_TEXT);
  184. SendMessage(hdlg, WM_COMMAND, IDOK, 0);
  185. goto case;
  186. case WM_SETFOCUS:
  187. SetFocus(GetDlgItem(hdlg, IDC_LF_HEIGHT));
  188. return FALSE;
  189. case WM_COMMAND:
  190. switch (LOWORD(wParam))
  191. {
  192. case IDC_CHARSET_HELP:
  193. MessageBox(hdlg,
  194. "0 = Ansi\n"
  195. "1 = Default\n"
  196. "2 = Symbol\n"
  197. "128 = Shift JIS (Japanese)\n"
  198. "129 = Hangul (Korean)\n"
  199. "130 = Johab (Korean)\n"
  200. "134 = GB 2312 (Simplified Chinese)\n"
  201. "136 = Chinese Big 5 (Traditional Chinese)\n"
  202. "177 = Hebrew\n"
  203. "178 = Arabic\n"
  204. "161 = Greek\n"
  205. "162 = Turkish\n"
  206. "163 = Vietnamese\n"
  207. "204 = Russian\n"
  208. "222 = Thai\n"
  209. "238 = East European\n"
  210. "255 = OEM",
  211. appName.toUTF16z, MB_OK | MB_ICONINFORMATION);
  212. return TRUE;
  213. // These radio buttons set the lfOutPrecision field
  214. case IDC_OUT_DEFAULT:
  215. pdp.lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  216. return TRUE;
  217. case IDC_OUT_STRING:
  218. pdp.lf.lfOutPrecision = OUT_STRING_PRECIS;
  219. return TRUE;
  220. case IDC_OUT_CHARACTER:
  221. pdp.lf.lfOutPrecision = OUT_CHARACTER_PRECIS;
  222. return TRUE;
  223. case IDC_OUT_STROKE:
  224. pdp.lf.lfOutPrecision = OUT_STROKE_PRECIS;
  225. return TRUE;
  226. case IDC_OUT_TT:
  227. pdp.lf.lfOutPrecision = OUT_TT_PRECIS;
  228. return TRUE;
  229. case IDC_OUT_DEVICE:
  230. pdp.lf.lfOutPrecision = OUT_DEVICE_PRECIS;
  231. return TRUE;
  232. case IDC_OUT_RASTER:
  233. pdp.lf.lfOutPrecision = OUT_RASTER_PRECIS;
  234. return TRUE;
  235. case IDC_OUT_TT_ONLY:
  236. pdp.lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
  237. return TRUE;
  238. case IDC_OUT_OUTLINE:
  239. pdp.lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
  240. return TRUE;
  241. // These three radio buttons set the lfQuality field
  242. case IDC_DEFAULT_QUALITY:
  243. pdp.lf.lfQuality = DEFAULT_QUALITY;
  244. return TRUE;
  245. case IDC_DRAFT_QUALITY:
  246. pdp.lf.lfQuality = DRAFT_QUALITY;
  247. return TRUE;
  248. case IDC_PROOF_QUALITY:
  249. pdp.lf.lfQuality = PROOF_QUALITY;
  250. return TRUE;
  251. // These three radio buttons set the lower nibble
  252. // of the lfPitchAndFamily field
  253. case IDC_DEFAULT_PITCH:
  254. pdp.lf.lfPitchAndFamily = cast(BYTE)
  255. ((0xF0 & pdp.lf.lfPitchAndFamily) | DEFAULT_PITCH);
  256. return TRUE;
  257. case IDC_FIXED_PITCH:
  258. pdp.lf.lfPitchAndFamily = cast(BYTE)
  259. ((0xF0 & pdp.lf.lfPitchAndFamily) | FIXED_PITCH);
  260. return TRUE;
  261. case IDC_VARIABLE_PITCH:
  262. pdp.lf.lfPitchAndFamily = cast(BYTE)
  263. ((0xF0 & pdp.lf.lfPitchAndFamily) | VARIABLE_PITCH);
  264. return TRUE;
  265. // These six radio buttons set the upper nibble
  266. // of the lpPitchAndFamily field
  267. case IDC_FF_DONTCARE:
  268. pdp.lf.lfPitchAndFamily = cast(BYTE)
  269. ((0x0F & pdp.lf.lfPitchAndFamily) | FF_DONTCARE);
  270. return TRUE;
  271. case IDC_FF_ROMAN:
  272. pdp.lf.lfPitchAndFamily = cast(BYTE)
  273. ((0x0F & pdp.lf.lfPitchAndFamily) | FF_ROMAN);
  274. return TRUE;
  275. case IDC_FF_SWISS:
  276. pdp.lf.lfPitchAndFamily = cast(BYTE)
  277. ((0x0F & pdp.lf.lfPitchAndFamily) | FF_SWISS);
  278. return TRUE;
  279. case IDC_FF_MODERN:
  280. pdp.lf.lfPitchAndFamily = cast(BYTE)
  281. ((0x0F & pdp.lf.lfPitchAndFamily) | FF_MODERN);
  282. return TRUE;
  283. case IDC_FF_SCRIPT:
  284. pdp.lf.lfPitchAndFamily = cast(BYTE)
  285. ((0x0F & pdp.lf.lfPitchAndFamily) | FF_SCRIPT);
  286. return TRUE;
  287. case IDC_FF_DECORATIVE:
  288. pdp.lf.lfPitchAndFamily = cast(BYTE)
  289. ((0x0F & pdp.lf.lfPitchAndFamily) | FF_DECORATIVE);
  290. return TRUE;
  291. // Mapping mode:
  292. case IDC_MM_TEXT:
  293. case IDC_MM_LOMETRIC:
  294. case IDC_MM_HIMETRIC:
  295. case IDC_MM_LOENGLISH:
  296. case IDC_MM_HIENGLISH:
  297. case IDC_MM_TWIPS:
  298. case IDC_MM_LOGTWIPS:
  299. pdp.iMapMode = LOWORD(wParam);
  300. return TRUE;
  301. // OK button pressed
  302. // -----------------
  303. case IDOK:
  304. // Get LOGFONT structure
  305. SetLogFontFromFields(hdlg, pdp);
  306. // Set Match-Aspect and Advanced Graphics flags
  307. pdp.fMatchAspect = IsDlgButtonChecked(hdlg, IDC_MATCH_ASPECT);
  308. pdp.fAdvGraphics = IsDlgButtonChecked(hdlg, IDC_ADV_GRAPHICS);
  309. // Get Information Context
  310. if (pdp.iDevice == IDM_DEVICE_SCREEN)
  311. {
  312. hdcDevice = CreateIC("DISPLAY", NULL, NULL, NULL);
  313. }
  314. else
  315. {
  316. pd.hwndOwner = hdlg;
  317. pd.Flags = PD_RETURNDEFAULT | PD_RETURNIC;
  318. pd.hDevNames = NULL;
  319. pd.hDevMode = NULL;
  320. PrintDlg(&pd);
  321. hdcDevice = pd.hDC;
  322. }
  323. // Set the mapping mode and the mapper flag
  324. MySetMapMode(hdcDevice, pdp.iMapMode);
  325. SetMapperFlags(hdcDevice, pdp.fMatchAspect);
  326. // Create font and select it into IC
  327. hFont = CreateFontIndirect(&pdp.lf);
  328. SelectObject(hdcDevice, hFont);
  329. // Get the text metrics and face name
  330. GetTextMetrics(hdcDevice, &pdp.tm);
  331. GetTextFace(hdcDevice, LF_FULLFACESIZE, pdp.szFaceName.ptr);
  332. DeleteDC(hdcDevice);
  333. DeleteObject(hFont);
  334. // Update dialog fields and invalidate main window
  335. SetFieldsFromTextMetric(hdlg, pdp);
  336. InvalidateRect(GetParent(hdlg), NULL, TRUE);
  337. return TRUE;
  338. default:
  339. }
  340. break;
  341. default:
  342. }
  343. return FALSE;
  344. }
  345. void SetLogFontFromFields(HWND hdlg, DLGPARAMS* pdp)
  346. {
  347. pdp.lf.lfHeight = GetDlgItemInt(hdlg, IDC_LF_HEIGHT, NULL, TRUE);
  348. pdp.lf.lfWidth = GetDlgItemInt(hdlg, IDC_LF_WIDTH, NULL, TRUE);
  349. pdp.lf.lfEscapement = GetDlgItemInt(hdlg, IDC_LF_ESCAPE, NULL, TRUE);
  350. pdp.lf.lfOrientation = cast(ubyte)GetDlgItemInt(hdlg, IDC_LF_ORIENT, NULL, TRUE);
  351. pdp.lf.lfWeight = GetDlgItemInt(hdlg, IDC_LF_WEIGHT, NULL, TRUE);
  352. pdp.lf.lfCharSet = cast(ubyte)GetDlgItemInt(hdlg, IDC_LF_CHARSET, NULL, FALSE);
  353. pdp.lf.lfItalic =
  354. IsDlgButtonChecked(hdlg, IDC_LF_ITALIC) == BST_CHECKED;
  355. pdp.lf.lfUnderline =
  356. IsDlgButtonChecked(hdlg, IDC_LF_UNDER) == BST_CHECKED;
  357. pdp.lf.lfStrikeOut =
  358. IsDlgButtonChecked(hdlg, IDC_LF_STRIKE) == BST_CHECKED;
  359. GetDlgItemText(hdlg, IDC_LF_FACENAME, pdp.lf.lfFaceName.ptr, LF_FACESIZE);
  360. }
  361. void SetFieldsFromTextMetric(HWND hdlg, DLGPARAMS* pdp)
  362. {
  363. string szBuffer;
  364. TCHAR* szYes = ("Yes\0"w.dup.ptr);
  365. TCHAR* szNo = ("No\0"w.dup.ptr);
  366. string[] szFamily = ["Don't Know", "Roman", "Swiss", "Modern",
  367. "Script", "Decorative", "Undefined"];
  368. SetDlgItemInt(hdlg, IDC_TM_HEIGHT, pdp.tm.tmHeight, TRUE);
  369. SetDlgItemInt(hdlg, IDC_TM_ASCENT, pdp.tm.tmAscent, TRUE);
  370. SetDlgItemInt(hdlg, IDC_TM_DESCENT, pdp.tm.tmDescent, TRUE);
  371. SetDlgItemInt(hdlg, IDC_TM_INTLEAD, pdp.tm.tmInternalLeading, TRUE);
  372. SetDlgItemInt(hdlg, IDC_TM_EXTLEAD, pdp.tm.tmExternalLeading, TRUE);
  373. SetDlgItemInt(hdlg, IDC_TM_AVECHAR, pdp.tm.tmAveCharWidth, TRUE);
  374. SetDlgItemInt(hdlg, IDC_TM_MAXCHAR, pdp.tm.tmMaxCharWidth, TRUE);
  375. SetDlgItemInt(hdlg, IDC_TM_WEIGHT, pdp.tm.tmWeight, TRUE);
  376. SetDlgItemInt(hdlg, IDC_TM_OVERHANG, pdp.tm.tmOverhang, TRUE);
  377. SetDlgItemInt(hdlg, IDC_TM_DIGASPX, pdp.tm.tmDigitizedAspectX, TRUE);
  378. SetDlgItemInt(hdlg, IDC_TM_DIGASPY, pdp.tm.tmDigitizedAspectY, TRUE);
  379. szBuffer = format(BCHARFORM, pdp.tm.tmFirstChar);
  380. SetDlgItemText(hdlg, IDC_TM_FIRSTCHAR, szBuffer.toUTF16z);
  381. szBuffer = format(BCHARFORM, pdp.tm.tmLastChar);
  382. SetDlgItemText(hdlg, IDC_TM_LASTCHAR, szBuffer.toUTF16z);
  383. szBuffer = format(BCHARFORM, pdp.tm.tmDefaultChar);
  384. SetDlgItemText(hdlg, IDC_TM_DEFCHAR, szBuffer.toUTF16z);
  385. szBuffer = format(BCHARFORM, pdp.tm.tmBreakChar);
  386. SetDlgItemText(hdlg, IDC_TM_BREAKCHAR, szBuffer.toUTF16z);
  387. SetDlgItemText(hdlg, IDC_TM_ITALIC, pdp.tm.tmItalic ? szYes : szNo);
  388. SetDlgItemText(hdlg, IDC_TM_UNDER, pdp.tm.tmUnderlined ? szYes : szNo);
  389. SetDlgItemText(hdlg, IDC_TM_STRUCK, pdp.tm.tmStruckOut ? szYes : szNo);
  390. SetDlgItemText(hdlg, IDC_TM_VARIABLE,
  391. TMPF_FIXED_PITCH & pdp.tm.tmPitchAndFamily ? szYes : szNo);
  392. SetDlgItemText(hdlg, IDC_TM_VECTOR,
  393. TMPF_VECTOR & pdp.tm.tmPitchAndFamily ? szYes : szNo);
  394. SetDlgItemText(hdlg, IDC_TM_TRUETYPE,
  395. TMPF_TRUETYPE & pdp.tm.tmPitchAndFamily ? szYes : szNo);
  396. SetDlgItemText(hdlg, IDC_TM_DEVICE,
  397. TMPF_DEVICE & pdp.tm.tmPitchAndFamily ? szYes : szNo);
  398. SetDlgItemText(hdlg, IDC_TM_FAMILY,
  399. szFamily[min(6, pdp.tm.tmPitchAndFamily >> 4)].toUTF16z);
  400. SetDlgItemInt(hdlg, IDC_TM_CHARSET, pdp.tm.tmCharSet, FALSE);
  401. SetDlgItemText(hdlg, IDC_TM_FACENAME, pdp.szFaceName.ptr);
  402. }
  403. void MySetMapMode(HDC hdc, int iMapMode)
  404. {
  405. switch (iMapMode)
  406. {
  407. case IDC_MM_TEXT:
  408. SetMapMode(hdc, MM_TEXT);
  409. break;
  410. case IDC_MM_LOMETRIC:
  411. SetMapMode(hdc, MM_LOMETRIC);
  412. break;
  413. case IDC_MM_HIMETRIC:
  414. SetMapMode(hdc, MM_HIMETRIC);
  415. break;
  416. case IDC_MM_LOENGLISH:
  417. SetMapMode(hdc, MM_LOENGLISH);
  418. break;
  419. case IDC_MM_HIENGLISH:
  420. SetMapMode(hdc, MM_HIENGLISH);
  421. break;
  422. case IDC_MM_TWIPS:
  423. SetMapMode(hdc, MM_TWIPS);
  424. break;
  425. case IDC_MM_LOGTWIPS:
  426. SetMapMode(hdc, MM_ANISOTROPIC);
  427. SetWindowExtEx(hdc, 1440, 1440, NULL);
  428. SetViewportExtEx(hdc, GetDeviceCaps(hdc, LOGPIXELSX),
  429. GetDeviceCaps(hdc, LOGPIXELSY), NULL);
  430. break;
  431. default:
  432. }
  433. }