PageRenderTime 95ms CodeModel.GetById 24ms RepoModel.GetById 6ms app.codeStats 0ms

/Samples/Chap17/Justify1/Justify1.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 426 lines | 313 code | 92 blank | 21 comment | 34 complexity | 6e8ff2f680bd9128f7d4650a9c149ac6 MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module Justify1;
  6. import core.memory;
  7. import core.runtime;
  8. import core.thread;
  9. import std.conv;
  10. import std.math;
  11. import std.range;
  12. import std.string;
  13. import std.utf;
  14. auto toUTF16z(S)(S s)
  15. {
  16. return toUTFz!(const(wchar)*)(s);
  17. }
  18. pragma(lib, "gdi32.lib");
  19. pragma(lib, "comdlg32.lib");
  20. import core.sys.windows.windef;
  21. import core.sys.windows.winuser;
  22. import core.sys.windows.wingdi;
  23. import core.sys.windows.winbase;
  24. import core.sys.windows.commdlg;
  25. import resource;
  26. string appName = "Justify1";
  27. string description = "Justified Type #1";
  28. HINSTANCE hinst;
  29. extern (Windows)
  30. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  31. {
  32. int result;
  33. try
  34. {
  35. Runtime.initialize();
  36. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  37. Runtime.terminate();
  38. }
  39. catch (Throwable o)
  40. {
  41. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  42. result = 0;
  43. }
  44. return result;
  45. }
  46. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  47. {
  48. hinst = hInstance;
  49. HACCEL hAccel;
  50. HWND hwnd;
  51. MSG msg;
  52. WNDCLASS wndclass;
  53. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  54. wndclass.lpfnWndProc = &WndProc;
  55. wndclass.cbClsExtra = 0;
  56. wndclass.cbWndExtra = 0;
  57. wndclass.hInstance = hInstance;
  58. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  59. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  60. wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  61. wndclass.lpszMenuName = appName.toUTF16z;
  62. wndclass.lpszClassName = appName.toUTF16z;
  63. if (!RegisterClass(&wndclass))
  64. {
  65. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  66. return 0;
  67. }
  68. hwnd = CreateWindow(appName.toUTF16z, // window class name
  69. description.toUTF16z, // window caption
  70. WS_OVERLAPPEDWINDOW, // window style
  71. CW_USEDEFAULT, // initial x position
  72. CW_USEDEFAULT, // initial y position
  73. CW_USEDEFAULT, // initial x size
  74. CW_USEDEFAULT, // initial y size
  75. NULL, // parent window handle
  76. NULL, // window menu handle
  77. hInstance, // program instance handle
  78. NULL); // creation parameters
  79. ShowWindow(hwnd, iCmdShow);
  80. UpdateWindow(hwnd);
  81. while (GetMessage(&msg, NULL, 0, 0))
  82. {
  83. TranslateMessage(&msg);
  84. DispatchMessage(&msg);
  85. }
  86. return msg.wParam;
  87. }
  88. void DrawRuler(HDC hdc, RECT* prc)
  89. {
  90. enum iRuleSize = [360, 72, 144, 72, 216, 72, 144, 72,
  91. 288, 72, 144, 72, 216, 72, 144, 72];
  92. int i, j;
  93. POINT ptClient;
  94. SaveDC(hdc);
  95. // Set Logical Twips mapping mode
  96. SetMapMode(hdc, MM_ANISOTROPIC);
  97. SetWindowExtEx(hdc, 1440, 1440, NULL);
  98. SetViewportExtEx(hdc, GetDeviceCaps(hdc, LOGPIXELSX),
  99. GetDeviceCaps(hdc, LOGPIXELSY), NULL);
  100. // Move the origin to a half inch from upper left
  101. SetWindowOrgEx(hdc, -720, -720, NULL);
  102. // Find the right margin (quarter inch from right)
  103. ptClient.x = prc.right;
  104. ptClient.y = prc.bottom;
  105. DPtoLP(hdc, &ptClient, 1);
  106. ptClient.x -= 360;
  107. // Draw the rulers
  108. MoveToEx(hdc, 0, -360, NULL);
  109. LineTo(hdc, ptClient.x, -360);
  110. MoveToEx(hdc, -360, 0, NULL);
  111. LineTo(hdc, -360, ptClient.y);
  112. for (i = 0, j = 0; i <= ptClient.x; i += 1440 / 16, j++)
  113. {
  114. MoveToEx(hdc, i, -360, NULL);
  115. LineTo(hdc, i, -360 - iRuleSize [j % 16]);
  116. }
  117. for (i = 0, j = 0; i <= ptClient.y; i += 1440 / 16, j++)
  118. {
  119. MoveToEx(hdc, -360, i, NULL);
  120. LineTo(hdc, -360 - iRuleSize [j % 16], i);
  121. }
  122. RestoreDC(hdc, -1);
  123. }
  124. // I'll leave porting this to a better D equivalent as an exercise to the reader. :p
  125. void Justify(HDC hdc, PTSTR pText, RECT* prc, int iAlign)
  126. {
  127. int xStart, yStart, cSpaceChars;
  128. PTSTR pBegin, pEnd;
  129. SIZE size;
  130. yStart = prc.top;
  131. do // for each text line
  132. {
  133. cSpaceChars = 0; // initialize number of spaces in line
  134. while (*pText == ' ') // skip over leading spaces
  135. pText++;
  136. pBegin = pText; // set pointer to char at beginning of line
  137. do // until the line is known
  138. {
  139. pEnd = pText; // set pointer to char at end of line
  140. // skip to next space
  141. while (*pText != '\0' && *pText++ != ' ')
  142. {
  143. }
  144. if (*pText == '\0')
  145. break;
  146. // after each space encountered, calculate extents
  147. cSpaceChars++;
  148. GetTextExtentPoint32(hdc, pBegin, pText - pBegin - 1, &size);
  149. }
  150. while (size.cx < (prc.right - prc.left));
  151. cSpaceChars--; // discount last space at end of line
  152. while (*(pEnd - 1) == ' ') // eliminate trailing spaces
  153. {
  154. pEnd--;
  155. cSpaceChars--;
  156. }
  157. // if end of text and no space characters, set pEnd to end
  158. if (*pText == '\0' || cSpaceChars <= 0)
  159. pEnd = pText;
  160. GetTextExtentPoint32(hdc, pBegin, pEnd - pBegin, &size);
  161. switch (iAlign) // use alignment for xStart
  162. {
  163. case IDM_ALIGN_LEFT:
  164. xStart = prc.left;
  165. break;
  166. case IDM_ALIGN_RIGHT:
  167. xStart = prc.right - size.cx;
  168. break;
  169. case IDM_ALIGN_CENTER:
  170. xStart = (prc.right + prc.left - size.cx) / 2;
  171. break;
  172. case IDM_ALIGN_JUSTIFIED:
  173. if (*pText != '\0' && cSpaceChars > 0)
  174. SetTextJustification(hdc,
  175. prc.right - prc.left - size.cx,
  176. cSpaceChars);
  177. xStart = prc.left;
  178. break;
  179. default:
  180. }
  181. // display the text
  182. TextOut(hdc, xStart, yStart, pBegin, pEnd - pBegin);
  183. // prepare for next line
  184. SetTextJustification(hdc, 0, 0);
  185. yStart += size.cy;
  186. pText = pEnd;
  187. }
  188. while (*pText && yStart < prc.bottom - size.cy);
  189. }
  190. extern (Windows)
  191. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  192. {
  193. scope (failure) assert(0);
  194. static CHOOSEFONT cf;
  195. static DOCINFO di = DOCINFO(DOCINFO.sizeof, "Justify1: Printing");
  196. static int iAlign = IDM_ALIGN_LEFT;
  197. static LOGFONT lf;
  198. static PRINTDLG pd;
  199. static string szText =
  200. "You don't know about me, without you "
  201. "have read a book by the name of \"The "
  202. "Adventures of Tom Sawyer,\" but that "
  203. "ain't no matter. That book was made by "
  204. "Mr. Mark Twain, and he told the truth, "
  205. "mainly. There was things which he "
  206. "stretched, but mainly he told the truth. "
  207. "That is nothing. I never seen anybody "
  208. "but lied, one time or another, without "
  209. "it was Aunt Polly, or the widow, or "
  210. "maybe Mary. Aunt Polly -- Tom's Aunt "
  211. "Polly, she is -- and Mary, and the Widow "
  212. "Douglas, is all told about in that book "
  213. "-- which is mostly a true book; with "
  214. "some stretchers, as I said before.";
  215. BOOL fSuccess;
  216. HDC hdc, hdcPrn;
  217. HMENU hMenu;
  218. int iSavePointSize;
  219. PAINTSTRUCT ps;
  220. RECT rect;
  221. switch (message)
  222. {
  223. case WM_CREATE:
  224. // Initialize the CHOOSEFONT structure
  225. GetObject(GetStockObject(SYSTEM_FONT), lf.sizeof, &lf);
  226. cf.hwndOwner = hwnd;
  227. cf.hDC = NULL;
  228. cf.lpLogFont = &lf;
  229. cf.iPointSize = 0;
  230. cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS |
  231. CF_EFFECTS;
  232. cf.rgbColors = 0;
  233. cf.lCustData = 0;
  234. cf.lpfnHook = NULL;
  235. cf.lpTemplateName = NULL;
  236. cf.hInstance = NULL;
  237. cf.lpszStyle = NULL;
  238. cf.nFontType = 0;
  239. cf.nSizeMin = 0;
  240. cf.nSizeMax = 0;
  241. return 0;
  242. case WM_COMMAND:
  243. hMenu = GetMenu(hwnd);
  244. switch (LOWORD(wParam))
  245. {
  246. case IDM_FILE_PRINT:
  247. // Get printer DC
  248. pd.lStructSize = PRINTDLG.sizeof;
  249. pd.hwndOwner = hwnd;
  250. pd.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION;
  251. if (!PrintDlg(&pd))
  252. return 0;
  253. if (NULL == (hdcPrn = pd.hDC))
  254. {
  255. MessageBox(hwnd, "Cannot obtain Printer DC",
  256. appName.toUTF16z, MB_ICONEXCLAMATION | MB_OK);
  257. return 0;
  258. }
  259. // Set margins of 1 inch
  260. rect.left = GetDeviceCaps(hdcPrn, LOGPIXELSX) -
  261. GetDeviceCaps(hdcPrn, PHYSICALOFFSETX);
  262. rect.top = GetDeviceCaps(hdcPrn, LOGPIXELSY) -
  263. GetDeviceCaps(hdcPrn, PHYSICALOFFSETY);
  264. rect.right = GetDeviceCaps(hdcPrn, PHYSICALWIDTH) -
  265. GetDeviceCaps(hdcPrn, LOGPIXELSX) -
  266. GetDeviceCaps(hdcPrn, PHYSICALOFFSETX);
  267. rect.bottom = GetDeviceCaps(hdcPrn, PHYSICALHEIGHT) -
  268. GetDeviceCaps(hdcPrn, LOGPIXELSY) -
  269. GetDeviceCaps(hdcPrn, PHYSICALOFFSETY);
  270. // Display text on printer
  271. SetCursor(LoadCursor(NULL, IDC_WAIT));
  272. ShowCursor(TRUE);
  273. fSuccess = FALSE;
  274. if ((StartDoc(hdcPrn, &di) > 0) && (StartPage(hdcPrn) > 0))
  275. {
  276. // Select font using adjusted lfHeight
  277. iSavePointSize = lf.lfHeight;
  278. lf.lfHeight = -(GetDeviceCaps(hdcPrn, LOGPIXELSY) *
  279. cf.iPointSize) / 720;
  280. SelectObject(hdcPrn, CreateFontIndirect(&lf));
  281. lf.lfHeight = iSavePointSize;
  282. // Set text color
  283. SetTextColor(hdcPrn, cf.rgbColors);
  284. // Display text
  285. Justify(hdcPrn, cast(wchar*)szText.toUTF16z, &rect, iAlign);
  286. if (EndPage(hdcPrn) > 0)
  287. {
  288. fSuccess = TRUE;
  289. EndDoc(hdcPrn);
  290. }
  291. }
  292. ShowCursor(FALSE);
  293. SetCursor(LoadCursor(NULL, IDC_ARROW));
  294. DeleteDC(hdcPrn);
  295. if (!fSuccess)
  296. MessageBox(hwnd, "Could not print text",
  297. appName.toUTF16z, MB_ICONEXCLAMATION | MB_OK);
  298. return 0;
  299. case IDM_FONT:
  300. if (ChooseFont(&cf))
  301. InvalidateRect(hwnd, NULL, TRUE);
  302. return 0;
  303. case IDM_ALIGN_LEFT:
  304. case IDM_ALIGN_RIGHT:
  305. case IDM_ALIGN_CENTER:
  306. case IDM_ALIGN_JUSTIFIED:
  307. CheckMenuItem(hMenu, iAlign, MF_UNCHECKED);
  308. iAlign = LOWORD(wParam);
  309. CheckMenuItem(hMenu, iAlign, MF_CHECKED);
  310. InvalidateRect(hwnd, NULL, TRUE);
  311. return 0;
  312. default:
  313. }
  314. return 0;
  315. case WM_PAINT:
  316. hdc = BeginPaint(hwnd, &ps);
  317. GetClientRect(hwnd, &rect);
  318. DrawRuler(hdc, &rect);
  319. rect.left += GetDeviceCaps(hdc, LOGPIXELSX) / 2;
  320. rect.top += GetDeviceCaps(hdc, LOGPIXELSY) / 2;
  321. rect.right -= GetDeviceCaps(hdc, LOGPIXELSX) / 4;
  322. SelectObject(hdc, CreateFontIndirect(&lf));
  323. SetTextColor(hdc, cf.rgbColors);
  324. Justify(hdc, cast(wchar*)szText.toUTF16z, &rect, iAlign);
  325. DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
  326. EndPaint(hwnd, &ps);
  327. return 0;
  328. case WM_DESTROY:
  329. PostQuitMessage(0);
  330. return 0;
  331. default:
  332. }
  333. return DefWindowProc(hwnd, message, wParam, lParam);
  334. }