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

/Samples/Chap20/Multi2/Multi2.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 434 lines | 327 code | 84 blank | 23 comment | 23 complexity | bdeda746fa16da74c35c4984e5b21e89 MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module Multi2;
  6. import core.memory;
  7. import core.runtime;
  8. import core.thread;
  9. import std.algorithm : max, min;
  10. import std.concurrency;
  11. import std.conv;
  12. import std.math;
  13. import std.random;
  14. import std.range;
  15. import std.string;
  16. import std.utf : count, toUTFz;
  17. auto toUTF16z(S)(S s)
  18. {
  19. return toUTFz!(const(wchar)*)(s);
  20. }
  21. pragma(lib, "gdi32.lib");
  22. pragma(lib, "comdlg32.lib");
  23. pragma(lib, "winmm.lib");
  24. import core.sys.windows.windef;
  25. import core.sys.windows.winuser;
  26. import core.sys.windows.wingdi;
  27. import core.sys.windows.winbase;
  28. import core.sys.windows.commdlg;
  29. import core.sys.windows.mmsystem;
  30. alias win32.winuser.MessageBox MessageBox;
  31. string appName = "Multi2";
  32. string description = "Multitasking Demo";
  33. HINSTANCE hinst;
  34. extern (Windows)
  35. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  36. {
  37. int result;
  38. try
  39. {
  40. Runtime.initialize();
  41. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  42. Runtime.terminate();
  43. }
  44. catch (Throwable o)
  45. {
  46. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  47. result = 0;
  48. }
  49. return result;
  50. }
  51. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  52. {
  53. hinst = hInstance;
  54. HACCEL hAccel;
  55. HWND hwnd;
  56. MSG msg;
  57. WNDCLASS wndclass;
  58. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  59. wndclass.lpfnWndProc = &WndProc;
  60. wndclass.cbClsExtra = 0;
  61. wndclass.cbWndExtra = 0;
  62. wndclass.hInstance = hInstance;
  63. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  64. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  65. wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  66. wndclass.lpszMenuName = appName.toUTF16z;
  67. wndclass.lpszClassName = appName.toUTF16z;
  68. if (!RegisterClass(&wndclass))
  69. {
  70. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  71. return 0;
  72. }
  73. hwnd = CreateWindow(appName.toUTF16z, // window class name
  74. description.toUTF16z, // window caption
  75. WS_OVERLAPPEDWINDOW, // window style
  76. CW_USEDEFAULT, // initial x position
  77. CW_USEDEFAULT, // initial y position
  78. CW_USEDEFAULT, // initial x size
  79. CW_USEDEFAULT, // initial y size
  80. NULL, // parent window handle
  81. NULL, // window menu handle
  82. hInstance, // program instance handle
  83. NULL); // creation parameters
  84. ShowWindow(hwnd, iCmdShow);
  85. UpdateWindow(hwnd);
  86. while (GetMessage(&msg, NULL, 0, 0))
  87. {
  88. TranslateMessage(&msg);
  89. DispatchMessage(&msg);
  90. }
  91. return msg.wParam;
  92. }
  93. struct PARAMS
  94. {
  95. HWND hwnd;
  96. int cxClient;
  97. int cyClient;
  98. int cyChar;
  99. BOOL bKill;
  100. }
  101. /+
  102. + In the original C example an address of a static variable from one thread is sent
  103. + to a new thread and then this is used for messaging (WTH?).
  104. + Enjoy: http://msdn.microsoft.com/en-us/library/kdzttdcb%28v=vs.80%29.aspx
  105. +/
  106. __gshared PARAMS params1;
  107. __gshared PARAMS params2;
  108. __gshared PARAMS params3;
  109. __gshared PARAMS params4;
  110. int CheckBottom(HWND hwnd, int cyClient, int cyChar, int iLine)
  111. {
  112. if (iLine * cyChar + cyChar > cyClient)
  113. {
  114. InvalidateRect(hwnd, NULL, TRUE);
  115. UpdateWindow(hwnd);
  116. iLine = 0;
  117. }
  118. return iLine;
  119. }
  120. // ------------------------------------------------
  121. // Window 1: Display increasing sequence of numbers
  122. // ------------------------------------------------
  123. void Thread1()
  124. {
  125. HDC hdc;
  126. int iNum = 0, iLine = 0;
  127. string szBuffer;
  128. while (!params1.bKill)
  129. {
  130. if (iNum < 0)
  131. iNum = 0;
  132. iLine = CheckBottom(params1.hwnd, params1.cyClient,
  133. params1.cyChar, iLine);
  134. hdc = GetDC(params1.hwnd);
  135. szBuffer = format("%s", iNum++);
  136. TextOut(hdc, 0, iLine * params1.cyChar, szBuffer.toUTF16z, szBuffer.count);
  137. ReleaseDC(params1.hwnd, hdc);
  138. iLine++;
  139. }
  140. }
  141. extern (Windows)
  142. LRESULT WndProc1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  143. {
  144. switch (message)
  145. {
  146. case WM_CREATE:
  147. params1.hwnd = hwnd;
  148. params1.cyChar = HIWORD(GetDialogBaseUnits());
  149. spawn(&Thread1);
  150. return 0;
  151. case WM_SIZE:
  152. params1.cyClient = HIWORD(lParam);
  153. return 0;
  154. case WM_DESTROY:
  155. params1.bKill = TRUE;
  156. return 0;
  157. default:
  158. }
  159. return DefWindowProc(hwnd, message, wParam, lParam);
  160. }
  161. // ------------------------------------------------------
  162. // Window 2: Display increasing sequence of prime numbers
  163. // ------------------------------------------------------
  164. void Thread2()
  165. {
  166. HDC hdc;
  167. int iNum = 1, iLine = 0, i, iSqrt;
  168. string szBuffer;
  169. while (!params2.bKill)
  170. {
  171. do
  172. {
  173. if (++iNum < 0)
  174. iNum = 0;
  175. iSqrt = cast(int)sqrt(cast(float)iNum);
  176. for (i = 2; i <= iSqrt; i++)
  177. if (iNum % i == 0)
  178. break;
  179. } while (i <= iSqrt);
  180. iLine = CheckBottom(params2.hwnd, params2.cyClient,
  181. params2.cyChar, iLine);
  182. hdc = GetDC(params2.hwnd);
  183. szBuffer = format("%s", iNum);
  184. TextOut(hdc, 0, iLine * params2.cyChar, szBuffer.toUTF16z, szBuffer.count);
  185. ReleaseDC(params2.hwnd, hdc);
  186. iLine++;
  187. }
  188. }
  189. extern (Windows)
  190. LRESULT WndProc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  191. {
  192. switch (message)
  193. {
  194. case WM_CREATE:
  195. params2.hwnd = hwnd;
  196. params2.cyChar = HIWORD(GetDialogBaseUnits());
  197. spawn(&Thread2);
  198. return 0;
  199. case WM_SIZE:
  200. params2.cyClient = HIWORD(lParam);
  201. return 0;
  202. case WM_DESTROY:
  203. params2.bKill = TRUE;
  204. return 0;
  205. default:
  206. }
  207. return DefWindowProc(hwnd, message, wParam, lParam);
  208. }
  209. // Window 3: Display increasing sequence of Fibonacci numbers
  210. // ----------------------------------------------------------
  211. void Thread3()
  212. {
  213. HDC hdc;
  214. int iNum = 0, iNext = 1, iLine = 0, iTemp;
  215. string szBuffer;
  216. while (!params3.bKill)
  217. {
  218. if (iNum < 0)
  219. {
  220. iNum = 0;
  221. iNext = 1;
  222. }
  223. iLine = CheckBottom(params3.hwnd, params3.cyClient,
  224. params3.cyChar, iLine);
  225. hdc = GetDC(params3.hwnd);
  226. szBuffer = format("%s", iNum);
  227. TextOut(hdc, 0, iLine * params3.cyChar, szBuffer.toUTF16z, szBuffer.count);
  228. ReleaseDC(params3.hwnd, hdc);
  229. iTemp = iNum;
  230. iNum = iNext;
  231. iNext += iTemp;
  232. iLine++;
  233. }
  234. }
  235. extern (Windows)
  236. LRESULT WndProc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  237. {
  238. switch (message)
  239. {
  240. case WM_CREATE:
  241. params3.hwnd = hwnd;
  242. params3.cyChar = HIWORD(GetDialogBaseUnits());
  243. spawn(&Thread3);
  244. return 0;
  245. case WM_SIZE:
  246. params3.cyClient = HIWORD(lParam);
  247. return 0;
  248. case WM_DESTROY:
  249. params3.bKill = TRUE;
  250. return 0;
  251. default:
  252. }
  253. return DefWindowProc(hwnd, message, wParam, lParam);
  254. }
  255. // -----------------------------------------
  256. // Window 4: Display circles of random radii
  257. // -----------------------------------------
  258. void Thread4()
  259. {
  260. HDC hdc;
  261. int iDiameter;
  262. while (!params4.bKill)
  263. {
  264. InvalidateRect(params4.hwnd, NULL, TRUE);
  265. UpdateWindow(params4.hwnd);
  266. iDiameter = uniform(0, (max(1, min(params4.cxClient, params4.cyClient))));
  267. hdc = GetDC(params4.hwnd);
  268. Ellipse(hdc, (params4.cxClient - iDiameter) / 2,
  269. (params4.cyClient - iDiameter) / 2,
  270. (params4.cxClient + iDiameter) / 2,
  271. (params4.cyClient + iDiameter) / 2);
  272. ReleaseDC(params4.hwnd, hdc);
  273. }
  274. }
  275. extern (Windows)
  276. LRESULT WndProc4(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  277. {
  278. switch (message)
  279. {
  280. case WM_CREATE:
  281. params4.hwnd = hwnd;
  282. params4.cyChar = HIWORD(GetDialogBaseUnits());
  283. spawn(&Thread4);
  284. return 0;
  285. case WM_SIZE:
  286. params4.cxClient = LOWORD(lParam);
  287. params4.cyClient = HIWORD(lParam);
  288. return 0;
  289. case WM_DESTROY:
  290. params4.bKill = TRUE;
  291. return 0;
  292. default:
  293. }
  294. return DefWindowProc(hwnd, message, wParam, lParam);
  295. }
  296. // -----------------------------------
  297. // Main window to create child windows
  298. // -----------------------------------
  299. extern (Windows)
  300. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  301. {
  302. scope (failure) assert(0);
  303. static HWND[4] hwndChild;
  304. static string[] szChildClass = ["Child1", "Child2", "Child3", "Child4"];
  305. static WNDPROC[] ChildProc = [&WndProc1, &WndProc2, &WndProc3, &WndProc4];
  306. HINSTANCE hInstance;
  307. int i, cxClient, cyClient;
  308. WNDCLASS wndclass;
  309. switch (message)
  310. {
  311. case WM_CREATE:
  312. hInstance = cast(HINSTANCE)GetWindowLongPtr(hwnd, GWL_HINSTANCE);
  313. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  314. wndclass.cbClsExtra = 0;
  315. wndclass.cbWndExtra = 0;
  316. wndclass.hInstance = hInstance;
  317. wndclass.hIcon = NULL;
  318. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  319. wndclass.hbrBackground = cast(HBRUSH)GetStockObject(WHITE_BRUSH);
  320. wndclass.lpszMenuName = NULL;
  321. for (i = 0; i < 4; i++)
  322. {
  323. wndclass.lpfnWndProc = ChildProc[i];
  324. wndclass.lpszClassName = szChildClass[i].toUTF16z;
  325. RegisterClass(&wndclass);
  326. hwndChild[i] = CreateWindow(szChildClass[i].toUTF16z, NULL,
  327. WS_CHILDWINDOW | WS_BORDER | WS_VISIBLE,
  328. 0, 0, 0, 0,
  329. hwnd, cast(HMENU)i, hInstance, NULL);
  330. }
  331. return 0;
  332. case WM_SIZE:
  333. cxClient = LOWORD(lParam);
  334. cyClient = HIWORD(lParam);
  335. for (i = 0; i < 4; i++)
  336. MoveWindow(hwndChild[i], (i % 2) * cxClient / 2,
  337. (i > 1) * cyClient / 2,
  338. cxClient / 2, cyClient / 2, TRUE);
  339. return 0;
  340. case WM_CHAR:
  341. if (wParam == '\x1B')
  342. DestroyWindow(hwnd);
  343. return 0;
  344. case WM_DESTROY:
  345. PostQuitMessage(0);
  346. return 0;
  347. default:
  348. }
  349. return DefWindowProc(hwnd, message, wParam, lParam);
  350. }