PageRenderTime 62ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/Samples/Extra/Superclass/Superclass.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 385 lines | 245 code | 68 blank | 72 comment | 14 complexity | 4e19b81d7fa9ad6bb6fbc166cb475656 MD5 | raw file
  1. module Subclass;
  2. pragma(lib, "gdi32.lib");
  3. import core.memory;
  4. import core.runtime;
  5. import core.thread;
  6. import core.stdc.string;
  7. import std.conv;
  8. import std.math;
  9. import std.range;
  10. import std.string;
  11. import std.utf;
  12. import core.sys.windows.windef;
  13. import core.sys.windows.winuser;
  14. import core.sys.windows.wingdi;
  15. import core.sys.windows.winbase;
  16. import core.sys.windows.commdlg;
  17. pragma(lib, "comdlg32.lib");
  18. import std.algorithm;
  19. import std.array;
  20. import std.stdio;
  21. import std.conv;
  22. import std.typetuple;
  23. import std.typecons;
  24. import std.traits;
  25. /*
  26. * Demonstrates a Superclassed Button Control.
  27. * Click on the upper-left button to get a
  28. * font selection dialog and select a new font.
  29. *
  30. * Note: Superclassing is also used in the DGUI and DFL libraries.
  31. *
  32. * Copyright © 2005-2006 Ken Fitlike.
  33. * http://winapi.foosyerdoos.org.uk/c ode/subsuperclass/htm/superclassedit.php
  34. *
  35. * Ported to D2 by Andrej Mitrovic, 2011.
  36. */
  37. // =============================================================================
  38. // SUPERCLASSED EDIT CONTROL - Copyright © 2003,2005 Ken Fitlike
  39. // =============================================================================
  40. // API functions used: CallWindowProc,ChooseFont,CreateFontIndirect,
  41. // CreateWindowEx,DefWindowProc,DeleteObject,DispatchMessage,FreeLibrary,
  42. // GetMessage,GetClassInfoEx,GetProcAddress,GetStockObject,GetSystemMetrics,
  43. // LoadImage,LoadLibrary,MessageBox,PostQuitMessage,RegisterClassEx,SendMessage,
  44. // SetFocus,SetWindowTheme,ShowWindow,UpdateWindow,TranslateMessage,WinMain.
  45. // =============================================================================
  46. // Demonstrates window superclassing. An edit control is superclassed to give
  47. // extra functionality in the form of an additional button that enables font
  48. // changes to be made.
  49. // =============================================================================
  50. auto toUTF16z(S) (S s)
  51. {
  52. return toUTFz!(const(wchar)*)(s);
  53. }
  54. extern (Windows)
  55. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  56. {
  57. int result;
  58. void exceptionHandler(Throwable e)
  59. {
  60. throw e;
  61. }
  62. try
  63. {
  64. Runtime.initialize();
  65. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  66. Runtime.terminate();
  67. }
  68. catch (Throwable o)
  69. {
  70. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  71. result = 0;
  72. }
  73. return result;
  74. }
  75. // setup some edit control id's
  76. enum
  77. {
  78. IDC_SUPERCLASSED_EDIT=200
  79. }
  80. WNDPROC wpOldProc;
  81. int myWinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmd)
  82. {
  83. string classname = "SIMPLEWND";
  84. WNDCLASSEX wcx ; // used for storing information about the wnd 'class'
  85. wcx.cbSize = WNDCLASSEX.sizeof;
  86. wcx.lpfnWndProc = &WndProc; // wnd Procedure pointer
  87. wcx.hInstance = hInst; // app instance
  88. // use 'LoadImage' to load wnd class icon and cursor as it supersedes the
  89. // obsolete functions 'LoadIcon' and 'LoadCursor', although these functions will
  90. // still work. Because the icon and cursor are loaded from system resources ie
  91. // they are shared, it is not necessary to free the image resources with either
  92. // 'DestroyIcon' or 'DestroyCursor'.
  93. wcx.hIcon = cast(HICON)(LoadImage(null, IDI_APPLICATION,
  94. IMAGE_ICON, 0, 0, LR_SHARED));
  95. wcx.hCursor = cast(HCURSOR)(LoadImage(null, IDC_ARROW,
  96. IMAGE_CURSOR, 0, 0, LR_SHARED));
  97. wcx.hbrBackground = cast(HBRUSH)(COLOR_BTNFACE + 1);
  98. wcx.lpszClassName = classname.toUTF16z;
  99. // the window 'class' (not c++ class) has to be registered with the system
  100. // before windows of that 'class' can be created
  101. if (!RegisterClassEx(&wcx))
  102. {
  103. ErrMsg(("Failed to register wnd class"));
  104. return -1;
  105. }
  106. int desktopwidth = GetSystemMetrics(SM_CXSCREEN);
  107. int desktopheight = GetSystemMetrics(SM_CYSCREEN);
  108. HWND hwnd = CreateWindowEx(0, // extended styles
  109. classname.toUTF16z, // name: wnd 'class'
  110. "Superclassed Window - Edit", // wnd title
  111. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, // wnd style
  112. desktopwidth / 4, // position:left
  113. desktopheight / 4, // position: top
  114. desktopwidth / 2, // width
  115. desktopheight / 2, // height
  116. null, // parent wnd handle
  117. null, // menu handle/wnd id
  118. hInst, // app instance
  119. null); // user defined info
  120. if (!hwnd)
  121. {
  122. ErrMsg("Failed to create wnd");
  123. return -1;
  124. }
  125. ShowWindow(hwnd, nCmd);
  126. UpdateWindow(hwnd);
  127. // start message loop - windows applications are 'event driven' waiting on user,
  128. // application or system signals to determine what action, if any, to take. Note
  129. // that an error may cause GetMessage to return a negative value so, ideally,
  130. // this result should be tested for and appropriate action taken to deal with
  131. // it(the approach taken here is to simply quit the application).
  132. MSG msg;
  133. while (GetMessage(&msg, null, 0, 0) > 0)
  134. {
  135. TranslateMessage(&msg);
  136. DispatchMessage(&msg);
  137. }
  138. return cast(int)(msg.wParam);
  139. }
  140. // Main window message processing functions
  141. extern(Windows)
  142. LRESULT WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  143. {
  144. switch (uMsg)
  145. {
  146. case WM_PARENTNOTIFY:
  147. {
  148. OnParentNotify(hwnd, LOWORD(wParam), cast(HWND)(lParam));
  149. return 0;
  150. }
  151. case WM_CREATE:
  152. return OnCreate(hwnd, cast(CREATESTRUCT*)(lParam));
  153. case WM_DESTROY:
  154. PostQuitMessage(0);
  155. return 0;
  156. default:
  157. }
  158. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  159. }
  160. int OnCreate(HWND hwnd, CREATESTRUCT* cs)
  161. {
  162. // handles the WM_CREATE message of the main, parent window; return -1 to fail
  163. // window creation
  164. RECT rc = RECT(60, 10, 200, 70);
  165. // the various edit control types are created by simply varying the style bits
  166. CreateEdit(hwnd, cs.hInstance, ES_MULTILINE | WS_VSCROLL | WS_CLIPCHILDREN, rc,
  167. IDC_SUPERCLASSED_EDIT, ("Superclassed Edit"));
  168. return 0;
  169. }
  170. void OnParentNotify(HWND hwnd, UINT uMsg, HWND hChild)
  171. {
  172. // handles parent window's WM_PARENTNOTIFY message
  173. if (uMsg == WM_CREATE)
  174. {
  175. // attempting to set the formatting rectangle in the superclassed edit
  176. // control's own WM_CREATE handler fails so do it here instead. Note that the
  177. // superclassed edit control's WM_CREATE message is issued prior to the
  178. // parent's WM_PARENTNOTIFY message by the system.
  179. SetFormattingRect(hChild);
  180. }
  181. }
  182. // superclassed edit control message functions
  183. extern(Windows)
  184. LRESULT EditProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  185. {
  186. switch (uMsg)
  187. {
  188. case WM_COMMAND:
  189. CallWindowProc(wpOldProc, hwnd, uMsg, wParam, lParam);
  190. OnCommandEdit(hwnd, LOWORD(wParam), HIWORD(wParam),
  191. cast(HWND)(lParam));
  192. return 0;
  193. case WM_CREATE:
  194. // get default creation first
  195. CallWindowProc(wpOldProc, hwnd, uMsg, wParam, lParam);
  196. return OnCreateEdit(hwnd, cast(CREATESTRUCT*)(lParam));
  197. default:
  198. }
  199. return CallWindowProc(wpOldProc, hwnd, uMsg, wParam, lParam);
  200. }
  201. void OnCommandEdit(HWND hwnd, int id, int nNotify, HWND hChild)
  202. {
  203. // handles WM_COMMAND message of the superclassed edit control
  204. if (hChild && nNotify == BN_CLICKED)
  205. {
  206. HFONT hFont = ChangeFont(hwnd);
  207. if (hFont)
  208. {
  209. // change the superclassed edit control font and destroy the existing one
  210. DeleteObject(cast(HFONT)(SendMessage(hwnd, WM_SETFONT,
  211. cast(WPARAM)(hFont), 0)));
  212. SetFormattingRect(hwnd);
  213. }
  214. // restore focus to parent superclassed edit control
  215. SetFocus(hwnd);
  216. }
  217. }
  218. int OnCreateEdit(HWND hwnd, CREATESTRUCT* cs)
  219. {
  220. // handles the WM_CREATE message of the superclassed edit control; return -1 to
  221. // fail window creation
  222. // change to gui font
  223. SendMessage(hwnd, WM_SETFONT, cast(WPARAM)(GetStockObject(DEFAULT_GUI_FONT)), 0);
  224. // create a small button and place it in top-left corner of edit control
  225. HWND hBtn = CreateWindowEx(0, "button", null,
  226. WS_CHILD | WS_VISIBLE,
  227. 0, 0, 10, 10,
  228. hwnd,
  229. null,
  230. cs.hInstance,
  231. null);
  232. // if winxp themes are used the button will be obscured so turn off themes for
  233. // button control but use dynamic linking so that code still works with
  234. // pre-winxp systems
  235. HINSTANCE hLib = LoadLibrary(("UxTheme.dll"));
  236. if (hLib)
  237. {
  238. alias extern(Windows) HRESULT function(HWND, LPCWSTR, LPCWSTR) DllSetWindowTheme;
  239. auto SetWindowTheme = cast(DllSetWindowTheme)GetProcAddress(hLib, "SetWindowTheme");
  240. SetWindowTheme(hBtn, " ", " ");
  241. FreeLibrary(hLib);
  242. }
  243. // select all the text in the edit control
  244. SendMessage(hwnd, EM_SETSEL, 0, cast(LPARAM)(-1));
  245. SetFocus(hwnd);
  246. return 0;
  247. }
  248. HFONT ChangeFont(HWND hwnd)
  249. {
  250. // display font common dialog and return any created font based on user
  251. // selection
  252. CHOOSEFONT cf;
  253. LOGFONT lf ;
  254. cf.lStructSize = CHOOSEFONT.sizeof;
  255. cf.hwndOwner = hwnd;
  256. cf.lpLogFont = &lf;
  257. cf.Flags = CF_SCREENFONTS;
  258. // display the font common dialog box
  259. if (ChooseFont(&cf))
  260. {
  261. return CreateFontIndirect(cf.lpLogFont);
  262. }
  263. return null;
  264. }
  265. HWND CreateEdit(HWND hParent, HINSTANCE hInst, DWORD dwStyle,
  266. ref RECT rc, int id, string caption)
  267. {
  268. // superclass the edit control, register the new edit control class and then
  269. // create a control of that control class.
  270. WNDCLASSEX wcx;
  271. wcx.cbSize = wcx.sizeof;
  272. // fill out the WNDCLASSEX with system class info for edit control
  273. GetClassInfoEx(null, "edit", &wcx);
  274. // save important information
  275. wpOldProc = wcx.lpfnWndProc; // save original wndproc
  276. // now change information to suit requirements
  277. string classname = "superclassed_edit";
  278. wcx.lpszClassName = classname.toUTF16z; // unique wnd class name
  279. wcx.lpfnWndProc = &EditProc; // new edit wndproc
  280. wcx.hInstance = hInst;
  281. // and register the new class with the system
  282. if (!RegisterClassEx(&wcx))
  283. {
  284. ErrMsg(("Failed to register edit control superclass"));
  285. return null;
  286. }
  287. dwStyle |= WS_CHILD | WS_VISIBLE;
  288. return CreateWindowEx(WS_EX_CLIENTEDGE, // extended styles
  289. classname.toUTF16z, // control 'class' name
  290. caption.toUTF16z, // control caption
  291. dwStyle, // control style
  292. rc.left, // position: left
  293. rc.top, // position: top
  294. rc.right, // width
  295. rc.bottom, // height
  296. hParent, // parent window handle
  297. // control's ID
  298. cast(HMENU)(cast(INT_PTR)(id)),
  299. hInst, // application instance
  300. null); // user defined info
  301. }
  302. int ErrMsg(string s)
  303. {
  304. return MessageBox(null, s.toUTF16z, "ERROR", MB_OK | MB_ICONEXCLAMATION);
  305. }
  306. void SetFormattingRect(HWND hwnd)
  307. {
  308. // sets the formatting rectangle for the superclassed edit control ie the
  309. // dimensions used to display text.
  310. int MARGIN_X = 10;
  311. int MARGIN_Y = 10;
  312. RECT rc;
  313. SendMessage(hwnd, EM_GETRECT, 0, cast(LPARAM)(&rc));
  314. rc.left += MARGIN_X;
  315. rc.top += MARGIN_Y;
  316. SendMessage(hwnd, EM_SETRECT, 0, cast(LPARAM)(&rc));
  317. }