PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Extra/VisualStyles2/VisualStyles2.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 300 lines | 232 code | 51 blank | 17 comment | 13 complexity | 094510f12fb4c9c00ca7ea125eb08e8a MD5 | raw file
  1. /+
  2. + Copyright Andrej Mitrovic 2011.
  3. + Distributed under the Boost Software License, Version 1.0.
  4. + (See accompanying file LICENSE_1_0.txt or copy at
  5. + http://www.boost.org/LICENSE_1_0.txt)
  6. +
  7. + Similar as Extra\VisualStyles, but adds hit testing.
  8. +/
  9. module VisualStyles;
  10. import core.memory;
  11. import core.runtime;
  12. import core.thread;
  13. import std.conv;
  14. import std.math;
  15. import std.range;
  16. import std.string;
  17. import std.traits;
  18. import std.utf;
  19. auto toUTF16z(S)(S s)
  20. {
  21. return toUTFz!(const(wchar)*)(s);
  22. }
  23. pragma(lib, "gdi32.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 uxSchema;
  29. import uxTheme;
  30. string appName = "VisualStyles";
  31. string description = "VisualStyles Demo";
  32. HINSTANCE hinst;
  33. extern (Windows)
  34. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  35. {
  36. int result;
  37. try
  38. {
  39. Runtime.initialize();
  40. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  41. Runtime.terminate();
  42. }
  43. catch (Throwable o)
  44. {
  45. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  46. result = 0;
  47. }
  48. return result;
  49. }
  50. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  51. {
  52. hinst = hInstance;
  53. HACCEL hAccel;
  54. HWND hwnd;
  55. MSG msg;
  56. WNDCLASS wndclass;
  57. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  58. wndclass.lpfnWndProc = &WndProc;
  59. wndclass.cbClsExtra = 0;
  60. wndclass.cbWndExtra = 0;
  61. wndclass.hInstance = hInstance;
  62. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  63. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  64. //~ wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  65. wndclass.hbrBackground = null; // don't send WM_ERASEBKND messages
  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. enum Control
  94. {
  95. Button
  96. }
  97. template isOneOf(X, T...)
  98. {
  99. static if (!T.length)
  100. enum bool isOneOf = false;
  101. else static if (is (X == T[0]))
  102. enum bool isOneOf = true;
  103. else
  104. enum bool isOneOf = isOneOf!(Unqual!X, T[1..$]);
  105. }
  106. auto get(T)(LPARAM lParam)
  107. if (isOneOf!(T, SIZE, POINT))
  108. {
  109. return T(cast(short)LOWORD(lParam),
  110. cast(short)HIWORD(lParam));
  111. }
  112. extern (Windows)
  113. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  114. {
  115. scope (failure) assert(0);
  116. static int cxClient, cyClient, cxSource, cySource;
  117. int x, y;
  118. HDC hdc;
  119. PAINTSTRUCT ps;
  120. static POINT hitPoint;
  121. static bool mouseLDown;
  122. static HDC hdcMem;
  123. static HBITMAP hbmMem;
  124. static HANDLE hOld;
  125. RECT rect;
  126. switch (message)
  127. {
  128. case WM_LBUTTONDOWN:
  129. {
  130. hitPoint = get!POINT(lParam);
  131. mouseLDown = true;
  132. InvalidateRect(hwnd, NULL, TRUE);
  133. return 0;
  134. }
  135. case WM_LBUTTONUP:
  136. {
  137. hitPoint = get!POINT(lParam);
  138. mouseLDown = false;
  139. InvalidateRect(hwnd, NULL, TRUE);
  140. return 0;
  141. }
  142. case WM_MOUSEMOVE:
  143. {
  144. hitPoint = get!POINT(lParam);
  145. InvalidateRect(hwnd, NULL, TRUE);
  146. return 0;
  147. }
  148. case WM_SIZE:
  149. cxClient = LOWORD(lParam);
  150. cyClient = HIWORD(lParam);
  151. return 0;
  152. // When you set 'hbrBackground = null' it prevents
  153. // the WM_ERASEBKND message to be sent.
  154. case WM_ERASEBKGND:
  155. return 1;
  156. case WM_PAINT:
  157. {
  158. // Get DC for window
  159. hdc = BeginPaint(hwnd, &ps);
  160. // Create an off-screen DC for double-buffering
  161. hdcMem = CreateCompatibleDC(hdc);
  162. hbmMem = CreateCompatibleBitmap(hdc, cxClient, cyClient);
  163. hOld = SelectObject(hdcMem, hbmMem);
  164. //~ writeln(buttonState);
  165. auto buttonRect = RECT(100, 100, 190, 130);
  166. DrawControl(hwnd, hdcMem, buttonRect, Control.Button, mouseLDown, hitPoint);
  167. // Transfer the off-screen DC to the screen
  168. BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY);
  169. // Free-up the off-screen DC
  170. SelectObject(hdcMem, hOld);
  171. DeleteObject(hbmMem);
  172. DeleteDC (hdcMem);
  173. EndPaint(hwnd, &ps);
  174. return 0;
  175. }
  176. case WM_DESTROY:
  177. PostQuitMessage(0);
  178. return 0;
  179. default:
  180. }
  181. return DefWindowProc(hwnd, message, wParam, lParam);
  182. }
  183. void DrawControl(HWND hwnd, HDC hdcMem, RECT rect, Control control, bool mouseLDown, POINT hitPoint)
  184. {
  185. HTHEME hTheme = OpenThemeData(hwnd, "Button");
  186. scope(exit)
  187. {
  188. if (hTheme !is null)
  189. CloseThemeData(hTheme);
  190. }
  191. final switch (control)
  192. {
  193. case Control.Button:
  194. {
  195. if (hTheme is null)
  196. {
  197. DrawCustomButton(hdcMem, rect, mouseLDown, hitPoint);
  198. }
  199. else
  200. {
  201. DrawThemedButton(hTheme, hdcMem, rect, mouseLDown, hitPoint);
  202. }
  203. break;
  204. }
  205. }
  206. }
  207. import std.utf : count;
  208. import std.exception;
  209. import std.stdio;
  210. void DrawCustomButton(HDC hDC, RECT rc, bool mouseLDown, POINT hitPoint)
  211. {
  212. SIZE size;
  213. auto text = "My button";
  214. FillRect(hDC, &rc, cast(HBRUSH)GetStockObject(GRAY_BRUSH));
  215. FrameRect(hDC, &rc, cast(HBRUSH)GetStockObject(LTGRAY_BRUSH));
  216. // calculate center
  217. GetTextExtentPoint32(hDC, text.toUTF16z, text.count, &size);
  218. auto rectWidth = (rc.right - rc.left);
  219. auto textWidth = (size.cx);
  220. auto xPos = rc.left + ((rectWidth - textWidth) / 2);
  221. auto rectHeight = (rc.bottom - rc.top);
  222. auto textHeight = (size.cy);
  223. auto yPos = rc.top + ((rectHeight - textHeight) / 2);
  224. TextOut(hDC, xPos, yPos, text.toUTF16z, text.count);
  225. }
  226. void DrawThemedButton(HTHEME hTheme, HDC hDC, RECT rc, bool mouseLDown, POINT hitPoint)
  227. {
  228. RECT rcContent;
  229. HRESULT hr;
  230. int state;
  231. auto text = "My button";
  232. WORD hitResult;
  233. HitTestThemeBackground(hTheme, hDC, BP_PUSHBUTTON, state,
  234. HTTB_BACKGROUNDSEG, &rc, null, hitPoint, &hitResult);
  235. if (hitResult == HTNOWHERE)
  236. {
  237. state = PBS_NORMAL;
  238. }
  239. else
  240. {
  241. state = mouseLDown ? PBS_PRESSED : PBS_HOT;
  242. }
  243. DrawThemeBackground(hTheme, hDC, BP_PUSHBUTTON, state, &rc, null);
  244. GetThemeBackgroundContentRect(hTheme, hDC, BP_PUSHBUTTON, state, &rc, &rcContent);
  245. DrawThemeText(hTheme, hDC, BP_PUSHBUTTON, state,
  246. text.toUTF16z, text.count,
  247. DT_CENTER | DT_VCENTER | DT_SINGLELINE,
  248. 0, &rcContent);
  249. }