PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Chap13/PopPad/PopPad.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 499 lines | 367 code | 115 blank | 17 comment | 52 complexity | 1c5e34c190398562b2efbaf704835618 MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module PopPad;
  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. pragma(lib, "winmm.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 core.sys.windows.mmsystem;
  27. import PopFile;
  28. import PopFind;
  29. import PopFont;
  30. import PopPrnt;
  31. import resource;
  32. string appName = "PopPad";
  33. string description = "name";
  34. HINSTANCE hinst;
  35. extern (Windows)
  36. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  37. {
  38. int result;
  39. try
  40. {
  41. Runtime.initialize();
  42. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  43. Runtime.terminate();
  44. }
  45. catch (Throwable o)
  46. {
  47. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  48. result = 0;
  49. }
  50. return result;
  51. }
  52. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  53. {
  54. hinst = hInstance;
  55. HACCEL hAccel;
  56. HWND hwnd;
  57. MSG msg;
  58. WNDCLASS wndclass;
  59. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  60. wndclass.lpfnWndProc = &WndProc;
  61. wndclass.cbClsExtra = 0;
  62. wndclass.cbWndExtra = 0;
  63. wndclass.hInstance = hInstance;
  64. wndclass.hIcon = LoadIcon(hInstance, appName.toUTF16z);
  65. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  66. wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  67. wndclass.lpszMenuName = appName.toUTF16z;
  68. wndclass.lpszClassName = appName.toUTF16z;
  69. if (!RegisterClass(&wndclass))
  70. {
  71. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  72. return 0;
  73. }
  74. hwnd = CreateWindow(appName.toUTF16z, // window class name
  75. description.toUTF16z, // window caption
  76. WS_OVERLAPPEDWINDOW, // window style
  77. CW_USEDEFAULT, // initial x position
  78. CW_USEDEFAULT, // initial y position
  79. CW_USEDEFAULT, // initial x size
  80. CW_USEDEFAULT, // initial y size
  81. NULL, // parent window handle
  82. NULL, // window menu handle
  83. hInstance, // program instance handle
  84. NULL); // creation parameters
  85. ShowWindow(hwnd, iCmdShow);
  86. UpdateWindow(hwnd);
  87. hAccel = LoadAccelerators(hInstance, appName.toUTF16z);
  88. while (GetMessage(&msg, NULL, 0, 0))
  89. {
  90. if (hDlgModeless == NULL || !IsDialogMessage(hDlgModeless, &msg))
  91. {
  92. if (!TranslateAccelerator(hwnd, hAccel, &msg))
  93. {
  94. TranslateMessage(&msg);
  95. DispatchMessage(&msg);
  96. }
  97. }
  98. }
  99. return msg.wParam;
  100. }
  101. enum EDITID = 1;
  102. enum UNTITLED = "(untitled)";
  103. HWND hDlgModeless;
  104. void DoCaption(HWND hwnd, string szTitleName)
  105. {
  106. string szCaption;
  107. szCaption = format("%s - %s", appName, szTitleName.length ? szTitleName : UNTITLED);
  108. SetWindowText(hwnd, szCaption.toUTF16z);
  109. }
  110. void OkMessage(HWND hwnd, string szMessage, string szTitleName)
  111. {
  112. string szBuffer;
  113. szBuffer = format(szMessage, szTitleName.length ? szTitleName : UNTITLED);
  114. MessageBox(hwnd, szBuffer.toUTF16z, appName.toUTF16z, MB_OK | MB_ICONEXCLAMATION);
  115. }
  116. int AskAboutSave(HWND hwnd, string szTitleName)
  117. {
  118. string szBuffer;
  119. int iReturn;
  120. szBuffer = format("Save current changes in %s?", szTitleName.length ? szTitleName : UNTITLED);
  121. iReturn = MessageBox(hwnd, szBuffer.toUTF16z, appName.toUTF16z, MB_YESNOCANCEL | MB_ICONQUESTION);
  122. if (iReturn == IDYES)
  123. if (!SendMessage(hwnd, WM_COMMAND, IDM_FILE_SAVE, 0))
  124. iReturn = IDCANCEL;
  125. return iReturn;
  126. }
  127. wchar[MAX_PATH] szFileName = 0;
  128. wchar[MAX_PATH] szTitleName = 0;
  129. extern (Windows)
  130. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  131. {
  132. scope (failure) assert(0);
  133. static BOOL bNeedSave = FALSE;
  134. static HINSTANCE hInst;
  135. static HWND hwndEdit;
  136. static int iOffset;
  137. static UINT messageFindReplace;
  138. int iSelBeg, iSelEnd, iEnable;
  139. LPFINDREPLACE pfr;
  140. switch (message)
  141. {
  142. case WM_CREATE:
  143. hInst = (cast(LPCREATESTRUCT)lParam).hInstance;
  144. // Create the edit control child window
  145. hwndEdit = CreateWindow("edit", NULL,
  146. WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
  147. WS_BORDER | ES_LEFT | ES_MULTILINE |
  148. ES_NOHIDESEL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
  149. 0, 0, 0, 0,
  150. hwnd, cast(HMENU)EDITID, hInst, NULL);
  151. SendMessage(hwndEdit, EM_LIMITTEXT, 32000, 0L);
  152. // Initialize common dialog box stuff
  153. PopFileInitialize(hwnd);
  154. PopFontInitialize(hwndEdit);
  155. messageFindReplace = RegisterWindowMessage(FINDMSGSTRING.ptr);
  156. DoCaption(hwnd, to!string(fromWStringz(szTitleName.ptr)));
  157. return 0;
  158. case WM_SETFOCUS:
  159. SetFocus(hwndEdit);
  160. return 0;
  161. case WM_SIZE:
  162. MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  163. return 0;
  164. case WM_INITMENUPOPUP:
  165. switch (lParam)
  166. {
  167. case 1: // Edit menu
  168. // Enable Undo if edit control can do it
  169. EnableMenuItem(cast(HMENU)wParam, IDM_EDIT_UNDO,
  170. SendMessage(hwndEdit, EM_CANUNDO, 0, 0L) ?
  171. MF_ENABLED : MF_GRAYED);
  172. // Enable Paste if text is in the clipboard
  173. EnableMenuItem(cast(HMENU)wParam, IDM_EDIT_PASTE,
  174. IsClipboardFormatAvailable(CF_TEXT) ?
  175. MF_ENABLED : MF_GRAYED);
  176. // Enable Cut, Copy, and Del if text is selected
  177. SendMessage(hwndEdit, EM_GETSEL, cast(WPARAM)&iSelBeg, cast(LPARAM)&iSelEnd);
  178. iEnable = (iSelBeg != iSelEnd) ? MF_ENABLED : MF_GRAYED;
  179. EnableMenuItem(cast(HMENU)wParam, IDM_EDIT_CUT, iEnable);
  180. EnableMenuItem(cast(HMENU)wParam, IDM_EDIT_COPY, iEnable);
  181. EnableMenuItem(cast(HMENU)wParam, IDM_EDIT_CLEAR, iEnable);
  182. break;
  183. case 2: // Search menu
  184. // Enable Find, Next, and Replace if modeless
  185. // dialogs are not already active
  186. iEnable = hDlgModeless == NULL ?
  187. MF_ENABLED : MF_GRAYED;
  188. EnableMenuItem(cast(HMENU)wParam, IDM_SEARCH_FIND, iEnable);
  189. EnableMenuItem(cast(HMENU)wParam, IDM_SEARCH_NEXT, iEnable);
  190. EnableMenuItem(cast(HMENU)wParam, IDM_SEARCH_REPLACE, iEnable);
  191. break;
  192. default:
  193. }
  194. return 0;
  195. case WM_COMMAND:
  196. // Messages from edit control
  197. if (lParam && LOWORD(wParam) == EDITID)
  198. {
  199. switch (HIWORD(wParam))
  200. {
  201. case EN_UPDATE:
  202. bNeedSave = TRUE;
  203. return 0;
  204. case EN_ERRSPACE:
  205. case EN_MAXTEXT:
  206. MessageBox(hwnd, "Edit control out of space.",
  207. appName.toUTF16z, MB_OK | MB_ICONSTOP);
  208. return 0;
  209. default:
  210. }
  211. break;
  212. }
  213. switch (LOWORD(wParam))
  214. {
  215. // Messages from File menu
  216. case IDM_FILE_NEW:
  217. if (bNeedSave && IDCANCEL == AskAboutSave(hwnd, to!string(fromWStringz(szTitleName.ptr))))
  218. return 0;
  219. SetWindowText(hwndEdit, "\0");
  220. szFileName[0] = 0;
  221. szTitleName[0] = 0;
  222. DoCaption(hwnd, to!string(fromWStringz(szTitleName.ptr)));
  223. bNeedSave = FALSE;
  224. return 0;
  225. case IDM_FILE_OPEN:
  226. if (bNeedSave && IDCANCEL == AskAboutSave(hwnd, to!string(fromWStringz(szTitleName.ptr))))
  227. return 0;
  228. if (PopFileOpenDlg(hwnd, szFileName.ptr, szTitleName.ptr))
  229. {
  230. if (!PopFileRead(hwndEdit, szFileName.ptr))
  231. {
  232. OkMessage(hwnd, "Could not read file %s!", to!string(fromWStringz(szTitleName.ptr)));
  233. szFileName[0] = 0;
  234. szTitleName[0] = 0;
  235. }
  236. }
  237. DoCaption(hwnd, to!string(fromWStringz(szTitleName.ptr)));
  238. bNeedSave = FALSE;
  239. return 0;
  240. case IDM_FILE_SAVE:
  241. if (szFileName[0] != 0)
  242. {
  243. if (PopFileWrite(hwndEdit, szFileName.ptr))
  244. {
  245. bNeedSave = FALSE;
  246. return 1;
  247. }
  248. else
  249. {
  250. OkMessage(hwnd, "Could not write file %s", to!string(fromWStringz(szTitleName.ptr)));
  251. return 0;
  252. }
  253. }
  254. goto case;
  255. case IDM_FILE_SAVE_AS:
  256. if (PopFileSaveDlg(hwnd, szFileName.ptr, szTitleName.ptr))
  257. {
  258. DoCaption(hwnd, to!string(fromWStringz(szTitleName.ptr)));
  259. if (PopFileWrite(hwndEdit, szFileName.ptr))
  260. {
  261. bNeedSave = FALSE;
  262. return 1;
  263. }
  264. else
  265. {
  266. OkMessage(hwnd, "Could not write file %s", to!string(fromWStringz(szTitleName.ptr)));
  267. return 0;
  268. }
  269. }
  270. return 0;
  271. case IDM_FILE_PRINT:
  272. if (!PopPrntPrintFile(hInst, hwnd, hwndEdit, szTitleName.ptr))
  273. OkMessage(hwnd, "Could not print file %s", to!string(fromWStringz(szTitleName.ptr)));
  274. return 0;
  275. case IDM_APP_EXIT:
  276. SendMessage(hwnd, WM_CLOSE, 0, 0);
  277. return 0;
  278. // Messages from Edit menu
  279. case IDM_EDIT_UNDO:
  280. SendMessage(hwndEdit, WM_UNDO, 0, 0);
  281. return 0;
  282. case IDM_EDIT_CUT:
  283. SendMessage(hwndEdit, WM_CUT, 0, 0);
  284. return 0;
  285. case IDM_EDIT_COPY:
  286. SendMessage(hwndEdit, WM_COPY, 0, 0);
  287. return 0;
  288. case IDM_EDIT_PASTE:
  289. SendMessage(hwndEdit, WM_PASTE, 0, 0);
  290. return 0;
  291. case IDM_EDIT_CLEAR:
  292. SendMessage(hwndEdit, WM_CLEAR, 0, 0);
  293. return 0;
  294. case IDM_EDIT_SELECT_ALL:
  295. SendMessage(hwndEdit, EM_SETSEL, 0, -1);
  296. return 0;
  297. // Messages from Search menu
  298. case IDM_SEARCH_FIND:
  299. SendMessage(hwndEdit, EM_GETSEL, 0, cast(LPARAM)&iOffset);
  300. hDlgModeless = PopFindFindDlg(hwnd);
  301. return 0;
  302. case IDM_SEARCH_NEXT:
  303. SendMessage(hwndEdit, EM_GETSEL, 0, cast(LPARAM)&iOffset);
  304. if (PopFindValidFind())
  305. PopFindNextText(hwndEdit, &iOffset);
  306. else
  307. hDlgModeless = PopFindFindDlg(hwnd);
  308. return 0;
  309. case IDM_SEARCH_REPLACE:
  310. SendMessage(hwndEdit, EM_GETSEL, 0, cast(LPARAM)&iOffset);
  311. hDlgModeless = PopFindReplaceDlg(hwnd);
  312. return 0;
  313. case IDM_FORMAT_FONT:
  314. if (PopFontChooseFont(hwnd))
  315. PopFontSetFont(hwndEdit);
  316. return 0;
  317. // Messages from Help menu
  318. case IDM_HELP:
  319. OkMessage(hwnd, "Help not yet implemented!",
  320. "\0");
  321. return 0;
  322. case IDM_APP_ABOUT:
  323. DialogBox(hInst, "AboutBox", hwnd, &AboutDlgProc);
  324. return 0;
  325. default:
  326. }
  327. break;
  328. case WM_CLOSE:
  329. if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, to!string(fromWStringz(szTitleName.ptr))))
  330. DestroyWindow(hwnd);
  331. return 0;
  332. case WM_QUERYENDSESSION:
  333. if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, to!string(fromWStringz(szTitleName.ptr))))
  334. return 1;
  335. return 0;
  336. case WM_DESTROY:
  337. PopFontDeinitialize();
  338. PostQuitMessage(0);
  339. return 0;
  340. default:
  341. // Process "Find-Replace" messages
  342. if (message == messageFindReplace)
  343. {
  344. pfr = cast(LPFINDREPLACE)lParam;
  345. if (pfr.Flags & FR_DIALOGTERM)
  346. hDlgModeless = NULL;
  347. if (pfr.Flags & FR_FINDNEXT)
  348. if (!PopFindFindText(hwndEdit, &iOffset, pfr))
  349. OkMessage(hwnd, "Text not found!", "\0");
  350. if (pfr.Flags & FR_REPLACE || pfr.Flags & FR_REPLACEALL)
  351. if (!PopFindReplaceText(hwndEdit, &iOffset, pfr))
  352. OkMessage(hwnd, "Text not found!", "\0");
  353. if (pfr.Flags & FR_REPLACEALL)
  354. {
  355. while (PopFindReplaceText(hwndEdit, &iOffset, pfr))
  356. {
  357. }
  358. }
  359. return 0;
  360. }
  361. break;
  362. }
  363. return DefWindowProc(hwnd, message, wParam, lParam);
  364. }
  365. extern (Windows)
  366. BOOL AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  367. {
  368. switch (message)
  369. {
  370. case WM_INITDIALOG:
  371. return TRUE;
  372. case WM_COMMAND:
  373. switch (LOWORD(wParam))
  374. {
  375. case IDOK:
  376. EndDialog(hDlg, 0);
  377. return TRUE;
  378. default:
  379. }
  380. break;
  381. default:
  382. }
  383. return FALSE;
  384. }