PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Extra/ThemedWakeUp/ThemedWakeUp.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 404 lines | 280 code | 83 blank | 41 comment | 20 complexity | 4dfa25e5b0ebf11d7966618cf6cac3c0 MD5 | raw file
  1. module ThemedWakeUp;
  2. // Same as Samples\Chap22\WakeUp, except the "Turn Off" button has
  3. // the current visual styled applied to it.
  4. import core.memory;
  5. import core.runtime;
  6. import core.thread;
  7. import std.conv;
  8. import std.math;
  9. import std.range;
  10. import std.string;
  11. import std.utf;
  12. auto toUTF16z(S)(S s)
  13. {
  14. return toUTFz!(const(wchar)*)(s);
  15. }
  16. pragma(lib, "gdi32.lib");
  17. pragma(lib, "comdlg32.lib");
  18. pragma(lib, "winmm.lib");
  19. pragma(lib, "comctl32.lib");
  20. import core.sys.windows.windef;
  21. import core.sys.windows.winuser;
  22. import core.sys.windows.wingdi;
  23. import core.sys.windows.winbase;
  24. import core.sys.windows.commdlg;
  25. import core.sys.windows.mmsystem;
  26. import core.sys.windows.commctrl;
  27. import VisualStyles;
  28. string appName = "WakeUp";
  29. string description = "WakeUp";
  30. HINSTANCE hinst;
  31. extern (Windows)
  32. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  33. {
  34. int result;
  35. try
  36. {
  37. Runtime.initialize();
  38. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  39. Runtime.terminate();
  40. }
  41. catch (Throwable o)
  42. {
  43. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  44. result = 0;
  45. }
  46. return result;
  47. }
  48. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  49. {
  50. enableVisualStyles();
  51. hinst = hInstance;
  52. HACCEL hAccel;
  53. HWND hwnd;
  54. MSG msg;
  55. WNDCLASS wndclass;
  56. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  57. wndclass.lpfnWndProc = &WndProc;
  58. wndclass.cbClsExtra = 0;
  59. wndclass.cbWndExtra = 0;
  60. wndclass.hInstance = hInstance;
  61. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  62. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  63. wndclass.hbrBackground = cast(HBRUSH) GetStockObject(WHITE_BRUSH);
  64. wndclass.lpszMenuName = appName.toUTF16z;
  65. wndclass.lpszClassName = appName.toUTF16z;
  66. if (!RegisterClass(&wndclass))
  67. {
  68. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  69. return 0;
  70. }
  71. hwnd = CreateWindow(appName.toUTF16z, // window class name
  72. description.toUTF16z, // window caption
  73. WS_OVERLAPPEDWINDOW, // window style
  74. CW_USEDEFAULT, // initial x position
  75. CW_USEDEFAULT, // initial y position
  76. CW_USEDEFAULT, // initial x size
  77. CW_USEDEFAULT, // initial y size
  78. NULL, // parent window handle
  79. NULL, // window menu handle
  80. hInstance, // program instance handle
  81. NULL); // creation parameters
  82. ShowWindow(hwnd, iCmdShow);
  83. UpdateWindow(hwnd);
  84. while (GetMessage(&msg, NULL, 0, 0))
  85. {
  86. TranslateMessage(&msg);
  87. DispatchMessage(&msg);
  88. }
  89. return msg.wParam;
  90. }
  91. // ID values for 3 child windows
  92. enum ID_TIMEPICK = 0;
  93. enum ID_CHECKBOX = 1;
  94. enum ID_PUSHBTN = 2;
  95. // Timer ID
  96. enum ID_TIMER = 1;
  97. // Number of 100-nanosecond increments (ie FILETIME ticks) in an hour
  98. enum FTTICKSPERHOUR = (60 * 60 * cast(LONGLONG)10000000);
  99. // Defines and structure for waveform "file"
  100. enum SAMPRATE = 11025;
  101. enum NUMSAMPS = (3 * SAMPRATE);
  102. enum HALFSAMPS = (NUMSAMPS / 2);
  103. struct WAVEFORM
  104. {
  105. char[4] chRiff;
  106. DWORD dwRiffSize;
  107. char[4] chWave;
  108. char[4] chFmt;
  109. DWORD dwFmtSize;
  110. PCMWAVEFORMAT pwf;
  111. char[4] chData;
  112. DWORD dwDataSize;
  113. BYTE[HALFSAMPS] byData;
  114. }
  115. // Original window procedure addresses for the subclassed windows
  116. WNDPROC[3] SubbedProc;
  117. // The current child window with the input focus
  118. HWND hwndFocus;
  119. extern (Windows)
  120. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  121. {
  122. scope (failure) assert(0);
  123. static HWND hwndDTP, hwndCheck, hwndPush;
  124. static WAVEFORM waveform = WAVEFORM("RIFF", NUMSAMPS + 0x24, "WAVE", "fmt ",
  125. PCMWAVEFORMAT.sizeof, PCMWAVEFORMAT(WAVEFORMAT(1, 1, SAMPRATE,
  126. SAMPRATE, 1), 8), "data", NUMSAMPS);
  127. FILETIME ft;
  128. HINSTANCE hInstance;
  129. INITCOMMONCONTROLSEX icex;
  130. int i, cxChar, cyChar;
  131. LARGE_INTEGER li;
  132. SYSTEMTIME st;
  133. switch (message)
  134. {
  135. case WM_CREATE:
  136. // Some initialization stuff
  137. hInstance = cast(HINSTANCE)GetWindowLongPtr(hwnd, GWL_HINSTANCE);
  138. icex.dwSize = icex.sizeof;
  139. icex.dwICC = ICC_DATE_CLASSES;
  140. InitCommonControlsEx(&icex);
  141. // Create the waveform file with alternating square waves
  142. //~ waveform = cast(typeof(waveform))GC.malloc(WAVEFORM.sizeof + NUMSAMPS);
  143. //~ *waveform = waveform;
  144. for (i = 0; i < HALFSAMPS; i++)
  145. {
  146. if (i % 600 < 300)
  147. {
  148. if (i % 16 < 8)
  149. waveform.byData[i] = 25;
  150. else
  151. waveform.byData[i] = 230;
  152. }
  153. else if (i % 8 < 4)
  154. waveform.byData[i] = 25;
  155. else
  156. waveform.byData[i] = 230;
  157. }
  158. // Get character size and set a fixed window size.
  159. cxChar = LOWORD(GetDialogBaseUnits());
  160. cyChar = HIWORD(GetDialogBaseUnits());
  161. SetWindowPos(hwnd, NULL, 0, 0,
  162. 42 * cxChar,
  163. 10 * cyChar / 3 + 2 * GetSystemMetrics(SM_CYBORDER) +
  164. GetSystemMetrics(SM_CYCAPTION),
  165. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  166. // Create the three child windows
  167. hwndDTP = CreateWindow((DATETIMEPICK_CLASS ~ 0).ptr, "",
  168. WS_BORDER | WS_CHILD | WS_VISIBLE | DTS_TIMEFORMAT,
  169. 2 * cxChar, cyChar, 12 * cxChar, 4 * cyChar / 3,
  170. hwnd, cast(HMENU)ID_TIMEPICK, hInstance, NULL);
  171. hwndCheck = CreateWindow("Button", "Set Alarm",
  172. WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
  173. 16 * cxChar, cyChar, 12 * cxChar, 4 * cyChar / 3,
  174. hwnd, cast(HMENU)ID_CHECKBOX, hInstance, NULL);
  175. hwndPush = CreateWindow("Button", "Turn Off",
  176. WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
  177. 28 * cxChar, cyChar, 12 * cxChar, 4 * cyChar / 3,
  178. hwnd, cast(HMENU)ID_PUSHBTN, hInstance, NULL);
  179. hwndFocus = hwndDTP;
  180. // Subclass the three child windows
  181. SubbedProc[ID_TIMEPICK] = cast(WNDPROC)SetWindowLongPtr(hwndDTP, GWL_WNDPROC, cast(LONG)&SubProc);
  182. SubbedProc[ID_CHECKBOX] = cast(WNDPROC)SetWindowLongPtr(hwndCheck, GWL_WNDPROC, cast(LONG)&SubProc);
  183. SubbedProc[ID_PUSHBTN] = cast(WNDPROC)SetWindowLongPtr(hwndPush, GWL_WNDPROC, cast(LONG)&SubProc);
  184. // Set the date and time picker control to the current time
  185. // plus 9 hours, rounded down to next lowest hour
  186. GetLocalTime(&st);
  187. SystemTimeToFileTime(&st, &ft);
  188. li = *cast(LARGE_INTEGER*) & ft;
  189. li.QuadPart += 9 * FTTICKSPERHOUR;
  190. ft = *cast(FILETIME*) & li;
  191. FileTimeToSystemTime(&ft, &st);
  192. st.wMinute = st.wSecond = st.wMilliseconds = 0;
  193. SendMessage(hwndDTP, DTM_SETSYSTEMTIME, 0, cast(LPARAM)&st);
  194. return 0;
  195. case WM_SETFOCUS:
  196. SetFocus(hwndFocus);
  197. return 0;
  198. case WM_COMMAND:
  199. switch (LOWORD(wParam)) // control ID
  200. {
  201. case ID_CHECKBOX:
  202. // When the user checks the "Set Alarm" button, get the
  203. // time in the date and time control and subtract from
  204. // it the current PC time.
  205. if (SendMessage(hwndCheck, BM_GETCHECK, 0, 0))
  206. {
  207. SendMessage(hwndDTP, DTM_GETSYSTEMTIME, 0, cast(LPARAM)&st);
  208. SystemTimeToFileTime(&st, &ft);
  209. li = *cast(LARGE_INTEGER*)&ft;
  210. GetLocalTime(&st);
  211. SystemTimeToFileTime(&st, &ft);
  212. li.QuadPart -= (cast(LARGE_INTEGER*)&ft).QuadPart;
  213. // Make sure the time is between 0 and 24 hours!
  214. // These little adjustments let us completely ignore
  215. // the date part of the SYSTEMTIME structures.
  216. while (li.QuadPart < 0)
  217. li.QuadPart += 24 * FTTICKSPERHOUR;
  218. li.QuadPart %= 24 * FTTICKSPERHOUR;
  219. // Set a one-shot timer! (See you in the morning.)
  220. SetTimer(hwnd, ID_TIMER, cast(int)(li.QuadPart / 10000), null);
  221. }
  222. else
  223. {
  224. // If button is being unchecked, kill the timer.
  225. KillTimer(hwnd, ID_TIMER);
  226. }
  227. return 0;
  228. // The "Turn Off" button turns off the ringing alarm, and also
  229. // unchecks the "Set Alarm" button and disables itself.
  230. case ID_PUSHBTN:
  231. PlaySound(NULL, NULL, 0);
  232. SendMessage(hwndCheck, BM_SETCHECK, 0, 0);
  233. EnableWindow(hwndDTP, TRUE);
  234. EnableWindow(hwndCheck, TRUE);
  235. EnableWindow(hwndPush, FALSE);
  236. SetFocus(hwndDTP);
  237. return 0;
  238. default:
  239. }
  240. return 0;
  241. // The WM_NOTIFY message comes from the date and time picker.
  242. // If the user has checked "Set Alarm" and then gone back to
  243. // change the alarm time, there might be a discrepancy between
  244. // the displayed time and the one-shot timer. So the program
  245. // unchecks "Set Alarm" and kills any outstanding timer.
  246. case WM_NOTIFY:
  247. switch (wParam) // control ID
  248. {
  249. case ID_TIMEPICK:
  250. switch ((cast(NMHDR*)lParam).code) // notification code
  251. {
  252. case DTN_DATETIMECHANGE:
  253. if (SendMessage(hwndCheck, BM_GETCHECK, 0, 0))
  254. {
  255. KillTimer(hwnd, ID_TIMER);
  256. SendMessage(hwndCheck, BM_SETCHECK, 0, 0);
  257. }
  258. return 0;
  259. default:
  260. }
  261. break;
  262. default:
  263. }
  264. return 0;
  265. // The WM_COMMAND message comes from the two buttons.
  266. case WM_TIMER:
  267. // When the timer message comes, kill the timer (because we only
  268. // want a one-shot) and start the annoying alarm noise going.
  269. KillTimer(hwnd, ID_TIMER);
  270. PlaySound(cast(PTSTR)&waveform, NULL,
  271. SND_MEMORY | SND_LOOP | SND_ASYNC);
  272. // Let the sleepy user turn off the timer by slapping the
  273. // space bar. If the window is minimized, it's restored; then it's
  274. // brought to the forefront; then the pushbutton is enabled and
  275. // given the input focus.
  276. EnableWindow(hwndDTP, FALSE);
  277. EnableWindow(hwndCheck, FALSE);
  278. EnableWindow(hwndPush, TRUE);
  279. hwndFocus = hwndPush;
  280. ShowWindow(hwnd, SW_RESTORE);
  281. SetForegroundWindow(hwnd);
  282. return 0;
  283. // Clean up if the alarm is ringing or the timer is still set.
  284. case WM_DESTROY:
  285. //~ GC.free(waveform);
  286. if (IsWindowEnabled(hwndPush))
  287. PlaySound(NULL, NULL, 0);
  288. if (SendMessage(hwndCheck, BM_GETCHECK, 0, 0))
  289. KillTimer(hwnd, ID_TIMER);
  290. PostQuitMessage(0);
  291. return 0;
  292. default:
  293. }
  294. return DefWindowProc(hwnd, message, wParam, lParam);
  295. }
  296. extern (Windows)
  297. LRESULT SubProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  298. {
  299. int idNext, id = GetWindowLongPtr(hwnd, GWL_ID);
  300. switch (message)
  301. {
  302. case WM_CHAR:
  303. if (wParam == '\t')
  304. {
  305. idNext = id;
  306. do
  307. {
  308. idNext = (idNext + (GetKeyState(VK_SHIFT) < 0 ? 2 : 1)) % 3;
  309. }
  310. while (!IsWindowEnabled(GetDlgItem(GetParent(hwnd), idNext)));
  311. SetFocus(GetDlgItem(GetParent(hwnd), idNext));
  312. return 0;
  313. }
  314. break;
  315. case WM_SETFOCUS:
  316. hwndFocus = hwnd;
  317. break;
  318. default:
  319. }
  320. return CallWindowProc(SubbedProc[id], hwnd, message, wParam, lParam);
  321. }