PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Chap07/Checker4/Checker4.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 274 lines | 203 code | 58 blank | 13 comment | 16 complexity | 0fccd711ff318620bbc7537893e7bf6c MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module Checker4;
  6. import core.runtime;
  7. import core.thread;
  8. import core.stdc.config;
  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. import core.sys.windows.windef;
  20. import core.sys.windows.winuser;
  21. import core.sys.windows.wingdi;
  22. extern (Windows)
  23. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  24. {
  25. int result;
  26. try
  27. {
  28. Runtime.initialize();
  29. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  30. Runtime.terminate();
  31. }
  32. catch (Throwable o)
  33. {
  34. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  35. result = 0;
  36. }
  37. return result;
  38. }
  39. enum DIVISIONS = 5;
  40. string childClass = "Checker4_Child";
  41. int idFocus;
  42. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  43. {
  44. string appName = "Checker4";
  45. HWND hwnd;
  46. MSG msg;
  47. WNDCLASS wndclass;
  48. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  49. wndclass.lpfnWndProc = &WndProc;
  50. wndclass.cbClsExtra = 0;
  51. wndclass.cbWndExtra = 0;
  52. wndclass.hInstance = hInstance;
  53. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  54. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  55. wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  56. wndclass.lpszMenuName = NULL;
  57. wndclass.lpszClassName = appName.toUTF16z;
  58. if(!RegisterClass(&wndclass))
  59. {
  60. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  61. return 0;
  62. }
  63. wndclass.lpfnWndProc = &ChildWndProc;
  64. wndclass.cbWndExtra = c_long.sizeof;
  65. wndclass.hIcon = NULL;
  66. wndclass.lpszClassName = childClass.toUTF16z;
  67. if(!RegisterClass(&wndclass))
  68. {
  69. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  70. return 0;
  71. }
  72. hwnd = CreateWindow(appName.toUTF16z, "Checker4 Mouse Hit-Test Demo",
  73. WS_OVERLAPPEDWINDOW,
  74. CW_USEDEFAULT, CW_USEDEFAULT,
  75. CW_USEDEFAULT, CW_USEDEFAULT,
  76. NULL, NULL, hInstance, NULL);
  77. ShowWindow(hwnd, iCmdShow);
  78. UpdateWindow(hwnd);
  79. while(GetMessage(&msg, NULL, 0, 0))
  80. {
  81. TranslateMessage(&msg);
  82. DispatchMessage(&msg);
  83. }
  84. return msg.wParam;
  85. }
  86. extern(Windows)
  87. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  88. {
  89. scope (failure) assert(0);
  90. static HWND[DIVISIONS][DIVISIONS] hwndChild;
  91. int cxBlock, cyBlock, x, y;
  92. switch (message)
  93. {
  94. case WM_CREATE:
  95. for(x = 0; x < DIVISIONS; x++)
  96. for(y = 0; y < DIVISIONS; y++)
  97. hwndChild[x][y] = CreateWindow(childClass.toUTF16z, NULL,
  98. WS_CHILDWINDOW | WS_VISIBLE,
  99. 0, 0, 0, 0,
  100. hwnd, cast(HMENU)(y << 8 | x), // child ID
  101. cast(HINSTANCE)GetWindowLongPtr(hwnd, GWL_HINSTANCE), // hInstance
  102. NULL);
  103. return 0;
  104. case WM_SIZE:
  105. cxBlock = LOWORD(lParam) / DIVISIONS;
  106. cyBlock = HIWORD(lParam) / DIVISIONS;
  107. for(x = 0; x < DIVISIONS; x++)
  108. for(y = 0; y < DIVISIONS; y++)
  109. MoveWindow(hwndChild[x][y],
  110. x * cxBlock, y * cyBlock,
  111. cxBlock, cyBlock, TRUE);
  112. return 0;
  113. case WM_LBUTTONDOWN:
  114. MessageBeep(0);
  115. return 0;
  116. case WM_SETFOCUS:
  117. // GetDlgItem takes a parent hwnd and child ID to get child hwnd.
  118. // child will update idFocus
  119. SetFocus(GetDlgItem(hwnd, idFocus));
  120. return 0;
  121. case WM_KEYDOWN: // Possibly change the focus window
  122. x = idFocus & 0xFF;
  123. y = idFocus >> 8;
  124. switch (wParam)
  125. {
  126. case VK_UP:
  127. y--; break;
  128. case VK_DOWN:
  129. y++; break;
  130. case VK_LEFT:
  131. x--; break;
  132. case VK_RIGHT:
  133. x++; break;
  134. case VK_HOME:
  135. x = y = 0; break;
  136. case VK_END:
  137. x = y = DIVISIONS - 1; break;
  138. default:
  139. return 0;
  140. }
  141. x = (x + DIVISIONS) % DIVISIONS; // wrap around if went beyond bounds
  142. y = (y + DIVISIONS) % DIVISIONS;
  143. idFocus = y << 8 | x;
  144. SetFocus(GetDlgItem(hwnd, idFocus));
  145. return 0;
  146. case WM_DESTROY:
  147. PostQuitMessage(0);
  148. return 0;
  149. default:
  150. }
  151. return DefWindowProc(hwnd, message, wParam, lParam);
  152. }
  153. extern(Windows)
  154. LRESULT ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  155. {
  156. HDC hdc;
  157. PAINTSTRUCT ps;
  158. RECT rect;
  159. switch (message)
  160. {
  161. case WM_CREATE:
  162. SetWindowLongPtr(hwnd, 0, 0); // on/off flag
  163. return 0;
  164. case WM_KEYDOWN:
  165. // Send most key presses to the parent window, except return or space
  166. if (wParam != VK_RETURN && wParam != VK_SPACE)
  167. {
  168. SendMessage(GetParent(hwnd), message, wParam, lParam);
  169. return 0;
  170. }
  171. // For Return and Space, fall through to WM_LBUTTONDOWN, which will toggle the square
  172. goto case;
  173. case WM_LBUTTONDOWN:
  174. SetWindowLongPtr(hwnd, 0, 1 ^ GetWindowLongPtr(hwnd, 0)); // toggle int
  175. SetFocus(hwnd);
  176. InvalidateRect(hwnd, NULL, FALSE);
  177. return 0;
  178. // For focus messages, invalidate the window for repainting
  179. case WM_SETFOCUS:
  180. // get child window ID (can ommit GWL_ID if using GetDlgCtrlID)
  181. idFocus = GetWindowLongPtr(hwnd, GWL_ID);
  182. goto case;
  183. // Fall through
  184. case WM_KILLFOCUS:
  185. InvalidateRect(hwnd, NULL, TRUE);
  186. return 0;
  187. case WM_PAINT:
  188. hdc = BeginPaint(hwnd, &ps);
  189. GetClientRect(hwnd, &rect);
  190. Rectangle(hdc, 0, 0, rect.right, rect.bottom);
  191. // Draw the "x" mark
  192. if (GetWindowLongPtr(hwnd, 0)) // get int state
  193. {
  194. MoveToEx(hdc, 0, 0, NULL);
  195. LineTo (hdc, rect.right, rect.bottom);
  196. MoveToEx(hdc, 0, rect.bottom, NULL);
  197. LineTo (hdc, rect.right, 0);
  198. }
  199. // Draw the "focus" rectangle
  200. if (hwnd == GetFocus()) // get hwnd of currently focused window, see if matches ours
  201. {
  202. rect.left += rect.right / 10;
  203. rect.right -= rect.left;
  204. rect.top += rect.bottom / 10;
  205. rect.bottom -= rect.top;
  206. SelectObject(hdc, GetStockObject(NULL_BRUSH));
  207. SelectObject(hdc, CreatePen(PS_DASH, 0, 0));
  208. Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
  209. DeleteObject(SelectObject(hdc, GetStockObject(BLACK_PEN)));
  210. }
  211. EndPaint(hwnd, &ps);
  212. return 0;
  213. default:
  214. }
  215. return DefWindowProc(hwnd, message, wParam, lParam);
  216. }