/platform/win/gui/apploop.d

http://github.com/wilkie/djehuty · D · 1156 lines · 647 code · 313 blank · 196 comment · 96 complexity · 7d22a65c6cdd7ff1182eae896ecaa9f7 MD5 · raw file

  1. /*
  2. * apploop.d
  3. *
  4. * This is the Windows GUI apploop.
  5. *
  6. * Author: Dave Wilkinson
  7. * Originated: July 20th, 2009
  8. *
  9. */
  10. module gui.apploop;
  11. pragma(lib, "comctl32.lib");
  12. import binding.win32.windef;
  13. import binding.win32.winnt;
  14. import binding.win32.winbase;
  15. import binding.win32.wingdi;
  16. import binding.win32.winuser;
  17. import binding.win32.winerror;
  18. import Gdiplus = binding.win32.gdiplus;
  19. import binding.win32.uxtheme;
  20. import platform.win.widget;
  21. import platform.win.main;
  22. import scaffold.console;
  23. import platform.application;
  24. import platform.vars.window;
  25. import platform.vars.font;
  26. import platform.vars.view;
  27. import gui.application;
  28. import gui.window;
  29. import resource.menu;
  30. import opengl.window;
  31. import graphics.view;
  32. import graphics.font;
  33. import core.application;
  34. import core.definitions;
  35. import io.console;
  36. class GuiApplicationController {
  37. // The initial entry for the gui application
  38. this() {
  39. // Initialize GDI+
  40. Gdiplus.GdiplusStartupInput gdiplusStartupInput;
  41. Gdiplus.GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, null);
  42. }
  43. void start() {
  44. // Register the class that a window will be created with
  45. registerWindowClass();
  46. // Recognize theme information
  47. loadThemingData();
  48. // Hooks
  49. ubyte* bleh; uint dontcare;
  50. //Hook("USER32.DLL\0"c.ptr, "BeginPaint\0"c.ptr, syscall_BeginPaint, bleh, cast(void*)&HookBeginPaint);
  51. //pBeginPaint = cast(BeginPaintFunc)bleh;
  52. //Hook("USER32.DLL\0"c.ptr, "EndPaint\0"c.ptr, syscall_EndPaint, bleh, cast(void*)&HookEndPaint);
  53. //pEndPaint = cast(EndPaintFunc)bleh;
  54. //Hook("USER32.DLL\0"c.ptr, "IsWindowVisible\0"c.ptr, syscall_IsWindowVisible, bleh, cast(void*)&HookIsWindowVisible);
  55. //pIsWindowVisible = cast(IsWindowVisibleFunc)bleh;
  56. //Hook("USER32.DLL\0"c.ptr, "WindowFromPoint\0"c.ptr, dontcare, bleh, cast(void*)&HookWindowFromPoint);
  57. //Hook("USER32.DLL\0"c.ptr, "GetWindowRect\0"c.ptr, dontcare, bleh, cast(void*)&HookGetWindowRect);
  58. //Hook("USER32.DLL\0"c.ptr, "GetClientRect\0"c.ptr, dontcare, bleh, cast(void*)&HookGetClientRect);
  59. Hook("UXTHEME.DLL\0"c.ptr, "BufferedPaintRenderAnimation\0"c.ptr, dontcare, bleh, cast(void*)&HookBufferedPaintRenderAnimation);
  60. pBufferedPaintRenderAnimation = cast(void*)bleh;
  61. /*Hook("UXTHEME.DLL\0"c.ptr, "BeginBufferedPaint\0"c.ptr, dontcare, bleh, cast(void*)&HookBeginBufferedPaint);
  62. pBeginBufferedPaint = cast(void*)bleh;
  63. Hook("UXTHEME.DLL\0"c.ptr, "EndBufferedAnimation\0"c.ptr, dontcare, bleh, cast(void*)&HookEndBufferedAnimation);
  64. pEndBufferedAnimation = cast(void*)bleh;
  65. Hook("UXTHEME.DLL\0"c.ptr, "BeginBufferedAnimation\0"c.ptr, dontcare, bleh, cast(void*)&HookBeginBufferedAnimation);
  66. pBeginBufferedAnimation = cast(void*)bleh;*/
  67. mainloop();
  68. }
  69. void end(uint code) {
  70. Gdiplus.GdiplusShutdown(gdiplusToken);
  71. _appEnd = true;
  72. ApplicationController.instance.exitCode = code;
  73. }
  74. private:
  75. // GDI+ Instance
  76. ULONG_PTR gdiplusToken;
  77. bool _appEnd = false;
  78. const int WM_MOUSECAPTURE = 0xffff;
  79. const wchar[] djehutyClassName = "djehutyApp\0"w;
  80. void registerWindowClass() {
  81. WNDCLASSW wc;
  82. wc.lpszClassName = djehutyClassName.ptr;
  83. wc.style = CS_PARENTDC;//CS_OWNDC;//| CS_HREDRAW | CS_VREDRAW;
  84. wc.lpfnWndProc = &DefaultProc;
  85. wc.hInstance = null;
  86. wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
  87. wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
  88. wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
  89. wc.lpszMenuName = null;
  90. wc.cbClsExtra = wc.cbWndExtra = 0;
  91. auto a = RegisterClassW(&wc);
  92. assert(a);
  93. }
  94. void mainloop() {
  95. // HOW AWFUL IS THIS: ?!
  96. while(!_appEnd) {
  97. Sleep(1);
  98. }
  99. // THIS CODE PRINTS TO THE CONSOLE WINDOW USING GDI
  100. /*HWND hwndConsole = GetConsoleWindow();
  101. HDC dc = GetDC(hwndConsole);
  102. CONSOLE_FONT_INFO cfi ;
  103. COORD fsize ;
  104. HANDLE hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
  105. GetCurrentConsoleFont(hConsoleOut, FALSE, &cfi);
  106. Font fnt = new Font("Terminal", 10, 400, false, false, false);
  107. FontPlatformVars* fvars = FontGetPlatformVars(fnt);
  108. SetBkMode(dc, OPAQUE);
  109. SetBkColor(dc, 0x339933);
  110. SetTextColor(dc, 0xf800f8);
  111. SelectObject(dc, fvars.fontHandle);
  112. */
  113. ConsoleUninit();
  114. ApplicationController.instance.end;
  115. }
  116. static:
  117. int win_osVersion = -1;
  118. alias extern(C) HDC function(HWND, LPPAINTSTRUCT) BeginPaintFunc;
  119. BeginPaintFunc pBeginPaint;
  120. uint syscall_BeginPaint;
  121. alias extern(C) BOOL function(HWND, LPPAINTSTRUCT) EndPaintFunc;
  122. EndPaintFunc pEndPaint;
  123. uint syscall_EndPaint;
  124. alias extern(C) BOOL function(HWND) IsWindowVisibleFunc;
  125. IsWindowVisibleFunc pIsWindowVisible;
  126. uint syscall_IsWindowVisible;
  127. void* pBufferedPaintRenderAnimation;
  128. void* pBeginBufferedPaint;
  129. void* pEndBufferedAnimation;
  130. void* pBeginBufferedAnimation;
  131. bool Hook(char* mod, char* proc, ref uint syscall_id, ref ubyte* pProc, void* pNewProc) {
  132. HINSTANCE hMod = GetModuleHandleA(mod);
  133. if (hMod is null) {
  134. hMod = LoadLibraryA(mod);
  135. Console.putln("not loaded");
  136. if (hMod is null) {
  137. Console.putln("bad");
  138. return false;
  139. }
  140. }
  141. pProc = cast(ubyte*)GetProcAddress(hMod, proc);
  142. if (pProc is null) {
  143. Console.putln("procnotfound");
  144. return false;
  145. }
  146. ubyte[5] oldCode;
  147. oldCode[0..5] = pProc[0..5];
  148. if ( true || pProc[0] == 0xB8 ) {
  149. syscall_id = *cast(uint*)(pProc + 1);
  150. DWORD flOldProtect;
  151. VirtualProtect(pProc, 5, PAGE_EXECUTE_READWRITE, & flOldProtect);
  152. pProc[0] = 0xE9;
  153. *cast(uint*)(pProc+1) = cast(uint)pNewProc - cast(uint)(pProc+5);
  154. pProc += 5;
  155. VirtualProtect(pProc, 5, flOldProtect, & flOldProtect);
  156. return true;
  157. }
  158. else {
  159. return false;
  160. }
  161. }
  162. extern(C) HDC HookBeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) {
  163. HDC ret;
  164. // normal operations:
  165. // abnormal operations:
  166. /* if (hWnd != button_hWnd) {
  167. asm {
  168. mov EAX, syscall_BeginPaint;
  169. push lpPaint;
  170. push hWnd;
  171. call pBeginPaint;
  172. mov ret, EAX;
  173. }
  174. return ret;
  175. }*/
  176. lpPaint.fErase = 0;
  177. lpPaint.rcPaint.left = 0;
  178. // lpPaint.rcPaint.right = button_width;
  179. lpPaint.rcPaint.top = 0;
  180. // lpPaint.rcPaint.bottom = button_height;
  181. lpPaint.fIncUpdate = 0;
  182. lpPaint.fRestore = 0;
  183. // lpPaint.hdc = button_hdc;
  184. return null; //button_hdc;
  185. }
  186. extern(C) BOOL HookIsWindowVisible() {
  187. asm {
  188. naked;
  189. mov EAX, 1;
  190. ret 4;
  191. }
  192. }
  193. extern(C) BOOL HookWindowFromPoint(POINT pnt) {
  194. asm {
  195. naked;
  196. // mov EAX, button_hWnd;
  197. ret 8;
  198. }
  199. }
  200. extern(C) BOOL HookGetWindowRect(HWND hWnd, RECT* rt) {
  201. Console.putln("GetWindowRect ", hWnd);
  202. if (rt !is null) {
  203. // rt.left = button_x;
  204. // rt.right = button_x + button_width;
  205. rt.top = 299;
  206. // rt.bottom = 299 + button_height;
  207. }
  208. asm {
  209. mov EAX, 1;
  210. }
  211. return 1;
  212. }
  213. extern(C) BOOL HookGetClientRect(HWND hWnd, RECT* rt) {
  214. asm {
  215. naked;
  216. mov EAX, 1;
  217. ret 8;
  218. }
  219. }
  220. void HookBeginPaintImpl() {
  221. asm {
  222. mov EAX, syscall_BeginPaint;
  223. call pBeginPaint;
  224. ret;
  225. }
  226. }
  227. template UXThemePrologue() {
  228. const char[] UXThemePrologue =
  229. `
  230. asm {
  231. naked;
  232. mov EDI,EDI;
  233. push EBP;
  234. mov EBP,ESP;
  235. }
  236. `;
  237. }
  238. extern(C) void HookBeginBufferedPaint() {
  239. mixin(UXThemePrologue!());
  240. //Console.putln("BeginBufferedPaint");
  241. asm {
  242. jmp pBeginBufferedPaint;
  243. }
  244. return;
  245. }
  246. extern(C) void HookBeginBufferedAnimation() {
  247. mixin(UXThemePrologue!());
  248. //Console.putln("BeginBufferedAnimation");
  249. asm {
  250. //mov EAX, button_hdc;
  251. //mov [EBP+12], EAX;
  252. }
  253. asm {
  254. jmp pBeginBufferedAnimation;
  255. }
  256. return;
  257. }
  258. extern(C) void HookEndBufferedAnimation() {
  259. mixin(UXThemePrologue!());
  260. //Console.putln("EndBufferedAnimation");
  261. asm {
  262. jmp pEndBufferedAnimation;
  263. }
  264. return;
  265. }
  266. extern(C) void HookBufferedPaintRenderAnimation(HWND hWnd, HDC hdcTarget) {
  267. mixin(UXThemePrologue!());
  268. void* ctrl_in = cast(void*)GetWindowLongW(hWnd, GWLP_USERDATA);
  269. if (ctrl_in !is null) {
  270. WinWidget _ctrlvars = cast(WinWidget)ctrl_in;
  271. hdcTarget = GetBaseDC(_ctrlvars);
  272. }
  273. // asm {
  274. // mov EAX, button_hdc;
  275. // mov [EBP+12], EAX;
  276. // }
  277. asm {
  278. jmp pBufferedPaintRenderAnimation;
  279. }
  280. return;
  281. }
  282. extern(C) BOOL HookEndPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) {
  283. // abnormal operations:
  284. // if (hWnd == button_hWnd) {
  285. //Console.putln("End Paint");
  286. // return true;
  287. // }
  288. // normal operations:
  289. asm {
  290. mov EAX, syscall_EndPaint;
  291. push lpPaint;
  292. push hWnd;
  293. call pEndPaint;
  294. }
  295. }
  296. extern(Windows)
  297. int DefaultProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
  298. // Console.putln("def proc");
  299. CREATESTRUCTW* cs = cast(CREATESTRUCTW*)lParam;
  300. if (uMsg == WM_CREATE) {
  301. Window w = cast(Window)cs.lpCreateParams;
  302. SetWindowLongW(hWnd, GWLP_WNDPROC, cast(LONG)&WindowProc);
  303. SetWindowLongW(hWnd, GWLP_USERDATA, cast(LONG)cs.lpCreateParams);
  304. return 0;
  305. }
  306. else if (uMsg == WM_UNICHAR) {
  307. return 1;
  308. }
  309. return DefWindowProcW(hWnd, uMsg, wParam, lParam);
  310. }
  311. extern(Windows)
  312. int CtrlProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
  313. // Console.putln("ctrl proc");
  314. void* ctrl_in = cast(void*)GetWindowLongW(hWnd, GWLP_USERDATA);
  315. if (ctrl_in !is null) {
  316. WinWidget _ctrlvars = cast(WinWidget)ctrl_in;
  317. return CallAppLoopMessage(_ctrlvars, uMsg, wParam, lParam);
  318. }
  319. return 0;
  320. }
  321. void _TestNumberOfClicks(ref Window w, ref WindowPlatformVars* windowVars, int x, int y, int clickType) {
  322. //check for double click first and within close proximity
  323. //of the last click
  324. if (windowVars.doubleClickTimerSet != 0) {
  325. KillTimer(windowVars.hWnd, 1);
  326. }
  327. // checks whether within tolerance region
  328. if ( (windowVars.doubleClickTimerSet == clickType) &&
  329. (x <= windowVars.doubleClickX + 1) &&
  330. (x >= windowVars.doubleClickX - 1) &&
  331. (y <= windowVars.doubleClickY + 1) &&
  332. (y >= windowVars.doubleClickY - 1) ) {
  333. // disable timer, inside tolerance
  334. windowVars.doubleClickAmount++;
  335. KillTimer(windowVars.hWnd, 1);
  336. }
  337. else {
  338. //reset timer stats, start over with one click
  339. windowVars.doubleClickTimerSet = clickType;
  340. windowVars.doubleClickAmount = 1;
  341. }
  342. //set up double click tolerance region
  343. windowVars.doubleClickX = x;
  344. windowVars.doubleClickY = y;
  345. SetTimer(windowVars.hWnd, 1, GetDoubleClickTime(), null);
  346. w.mouseProps.clicks = windowVars.doubleClickAmount;
  347. }
  348. void _TestNumberOfClicksUp(ref Window w, ref WindowPlatformVars* windowVars, int clickType) {
  349. if (windowVars.doubleClickTimerSet == clickType) {
  350. //double click may have occured
  351. w.mouseProps.clicks = windowVars.doubleClickAmount;
  352. }
  353. else {
  354. w.mouseProps.clicks = 1;
  355. }
  356. }
  357. bool win_hasVisualStyles = false;
  358. HFONT win_button_font;
  359. HMODULE win_uxThemeMod;
  360. // Theming Libraries
  361. extern (Windows) alias HTHEME (*OpenThemeDataFunc)(HWND, LPCWSTR);
  362. extern (Windows) alias HRESULT (*GetThemeSysFontFunc)(HTHEME, int, LOGFONTW*);
  363. extern (Windows) alias HRESULT (*CloseThemeDataFunc)(HTHEME);
  364. OpenThemeDataFunc OpenThemeDataDLL;
  365. GetThemeSysFontFunc GetThemeSysFontDLL;
  366. CloseThemeDataFunc CloseThemeDataDLL;
  367. void loadThemingData() {
  368. const int TMT_MSGBOXFONT = 805;
  369. // Do we have visual styles?
  370. // Load the theming library: uxTheme, if applicable
  371. if (win_osVersion >= OsVersionWindowsXp) {
  372. //using visual styles
  373. //look up uxTheme.dll
  374. win_uxThemeMod = LoadLibraryW("UxTheme.DLL");
  375. if (win_uxThemeMod == null) {
  376. //does not exist...
  377. win_hasVisualStyles = false;
  378. }
  379. else {
  380. //get proc addresses of important functions
  381. OpenThemeDataDLL = cast(OpenThemeDataFunc)GetProcAddress(win_uxThemeMod, "OpenThemeData");
  382. CloseThemeDataDLL = cast(CloseThemeDataFunc)GetProcAddress(win_uxThemeMod, "CloseThemeData");
  383. GetThemeSysFontDLL = cast(GetThemeSysFontFunc)GetProcAddress(win_uxThemeMod, "GetThemeSysFont");
  384. //apply visual styles if the application is allowed
  385. win_hasVisualStyles = true;
  386. }
  387. }
  388. else {
  389. //no visual styles
  390. win_uxThemeMod = null;
  391. win_hasVisualStyles = false;
  392. }
  393. HDC dcz = GetDC(null);
  394. if (win_hasVisualStyles) {
  395. HTHEME hTheme;
  396. hTheme = OpenThemeDataDLL(null, "WINDOW");
  397. LOGFONTW lfnt = { 0 };
  398. HRESULT hr = GetThemeSysFontDLL(hTheme, TMT_MSGBOXFONT, &lfnt);
  399. if (hr != S_OK) {
  400. win_button_font = CreateFontW(-MulDiv(8, GetDeviceCaps(dcz, 90), 72), 0, 0, 0, 400, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH, "Microsoft Sans Serif");
  401. }
  402. else {
  403. win_button_font = CreateFontIndirectW(&lfnt);
  404. }
  405. CloseThemeDataDLL(hTheme);
  406. }
  407. else {
  408. win_button_font = CreateFontW(-MulDiv(8, GetDeviceCaps(dcz, 90), 72),0,0,0, 400, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH, "MS Sans Serif");
  409. }
  410. ReleaseDC(null, dcz);
  411. }
  412. extern(Windows)
  413. static int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
  414. // resolve the window class reference:
  415. void* wind_in = cast(void*)GetWindowLongW(hWnd, GWLP_USERDATA);
  416. Window w = cast(Window)(wind_in);
  417. WindowPlatformVars* windowVars = &w._pfvars;
  418. Window viewW;
  419. int ret = IsWindowUnicode(windowVars.hWnd);
  420. if (true) {
  421. viewW = cast(Window)w;
  422. }
  423. else {
  424. viewW = null;
  425. }
  426. switch (uMsg) {
  427. // FOR CONTROLS AND MENUS //
  428. case WM_VSCROLL:
  429. case WM_HSCROLL:
  430. case WM_COMMAND:
  431. if (lParam == 0) {
  432. // menu
  433. Menu mnuNow = cast(Menu)cast(void*)wParam;
  434. if (viewW !is null) {
  435. viewW.onMenu(mnuNow);
  436. }
  437. }
  438. else {
  439. // native control
  440. wind_in = cast(void*)GetWindowLongW(cast(HWND)lParam, GWLP_USERDATA);
  441. WinWidget ctrl = cast(WinWidget)wind_in;
  442. wParam &= 0xFFFF;
  443. // ctrl._AppLoopMessage(uMsg, wParam, lParam);
  444. return CallAppLoopMessage(ctrl, uMsg, wParam, lParam);
  445. }
  446. break;
  447. case WM_CTLCOLORDLG:
  448. case WM_CTLCOLORBTN:
  449. case WM_CTLCOLORSTATIC:
  450. /* Console.putln("ctrl back");
  451. wind_in = cast(void*)GetWindowLongW(cast(HWND)lParam, GWLP_USERDATA);
  452. WinWidget ctrl = cast(WinWidget)wind_in;
  453. // SET FOREGROUND AND BACKGROUND COLORS FOR CONTROLS HERE:
  454. // TO SUPPORT BACKGROUND AND FOREGROUND CHANGES
  455. SetBkMode(cast(HDC)wParam, TRANSPARENT);
  456. // Lock Display
  457. int x, y, width, height;
  458. View ctrl_view = CallReturnView(ctrl,x,y,width,height); //ctrl._ReturnView(x, y, width, height);
  459. if (!indraw) {
  460. ctrl_view.lockDisplay();
  461. }
  462. ViewPlatformVars* viewVars = ViewGetPlatformVars(ctrl_view);
  463. BitBlt(
  464. cast(HDC)wParam,
  465. 0, 0,
  466. width, height,
  467. viewVars.dc,
  468. x, y,
  469. SRCCOPY);
  470. if (!indraw) {
  471. ctrl_view.unlockDisplay();
  472. }*/
  473. return cast(LRESULT)GetStockObject(NULL_BRUSH);
  474. case WM_DRAWITEM:
  475. DRAWITEMSTRUCT* pDIS = cast(DRAWITEMSTRUCT*)lParam;
  476. View view = w._view;
  477. ViewPlatformVars* viewVars = w._viewVars;
  478. RECT rt;
  479. GetClientRect(pDIS.hwndItem, &rt);
  480. BitBlt(pDIS.hDC, 0, 0, w.width, w.height, viewVars.dc, 0, 0, SRCCOPY);
  481. //Rectangle(pDIS.hDC, 0, 0, rt.right, rt.bottom);
  482. break;
  483. case WM_ERASEBKGND:
  484. break;
  485. case WM_PAINT:
  486. View view = w._view;
  487. ViewPlatformVars* viewVars = w._viewVars;
  488. viewW.onDraw();
  489. view.lock();
  490. PAINTSTRUCT ps;
  491. HDC dc = BeginPaint(hWnd, &ps);
  492. BitBlt(ps.hdc, 0, 0, w.width, w.height, viewVars.dc, 0, 0, SRCCOPY);
  493. EndPaint(hWnd, &ps);
  494. view.unlock();
  495. break;
  496. case WM_DESTROY:
  497. w.uninitialize();
  498. break;
  499. /* FOCUS */
  500. case WM_ACTIVATE:
  501. int x, y;
  502. //activation type
  503. x = wParam & 0xffff;
  504. //minimization status
  505. y = (wParam >> 16) & 0xffff;
  506. if (x == WA_INACTIVE) {
  507. //losing focus
  508. w.onLostFocus();
  509. }
  510. else if (x == WA_ACTIVE || x == WA_CLICKACTIVE) {
  511. //gaining focus
  512. w.onGotFocus();
  513. }
  514. if (y != 0) {
  515. //minimized
  516. }
  517. break;
  518. case WM_INPUT:
  519. break;
  520. case WM_CAPTURECHANGED:
  521. break;
  522. case WM_LBUTTONDOWN:
  523. SetFocus(hWnd);
  524. SetCapture(hWnd);
  525. //uint lp = GetMessageExtraInfo();
  526. //if ((lp & SIGNATURE_MASK) == MI_WP_SIGNATURE) {
  527. //writefln("pen");
  528. //}
  529. //writefln("down : ", lp, " ... ", lp & SIGNATURE_MASK, " == ", MI_WP_SIGNATURE);
  530. // FILL THE MOUSEPROPERTIES STRUCTURE FOR THE WINDOW
  531. //w.mouseProps.rightDown = 1;
  532. //check bounds for the controls
  533. int x, y;
  534. x = lParam & 0xffff;
  535. w.mouseProps.x = x;
  536. y = (lParam >> 16) & 0xffff;
  537. w.mouseProps.y = y;
  538. w.mouseProps.leftDown = true;
  539. w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
  540. w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
  541. _TestNumberOfClicks(w,windowVars,x,y,1);
  542. w.onPrimaryMouseDown();
  543. break;
  544. case WM_LBUTTONUP:
  545. ReleaseCapture();
  546. //window.mouseProps.rightDown = 0;
  547. //check for double click first
  548. _TestNumberOfClicksUp(w,windowVars,1);
  549. //fill _mouseProps
  550. int x, y;
  551. x = lParam & 0xffff;
  552. w.mouseProps.x = x;
  553. y = (lParam >> 16) & 0xffff;
  554. w.mouseProps.y = y;
  555. w.mouseProps.leftDown = false;
  556. w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
  557. w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
  558. w.onPrimaryMouseUp();
  559. break;
  560. case WM_RBUTTONDOWN:
  561. SetFocus(hWnd);
  562. SetCapture(hWnd);
  563. // FILL THE MOUSEPROPERTIES STRUCTURE FOR THE WINDOW
  564. //w.mouseProps.rightDown = 1;
  565. //check bounds for the controls
  566. int x, y;
  567. x = lParam & 0xffff;
  568. w.mouseProps.x = x;
  569. y = (lParam >> 16) & 0xffff;
  570. w.mouseProps.y = y;
  571. w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
  572. w.mouseProps.rightDown = true;
  573. w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
  574. _TestNumberOfClicks(w,windowVars,x,y,2);
  575. w.onSecondaryMouseDown();
  576. break;
  577. case WM_RBUTTONUP:
  578. ReleaseCapture();
  579. //window.mouseProps.rightDown = 0;
  580. //check for double click first
  581. _TestNumberOfClicksUp(w,windowVars,2);
  582. //fill _mouseProps
  583. int x, y;
  584. x = lParam & 0xffff;
  585. w.mouseProps.x = x;
  586. y = (lParam >> 16) & 0xffff;
  587. w.mouseProps.y = y;
  588. w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
  589. w.mouseProps.rightDown = false;
  590. w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
  591. w.onSecondaryMouseUp();
  592. break;
  593. case WM_MBUTTONDOWN:
  594. SetFocus(hWnd);
  595. SetCapture(hWnd);
  596. // FILL THE MOUSEPROPERTIES STRUCTURE FOR THE WINDOW
  597. //w.mouseProps.rightDown = 1;
  598. //check bounds for the controls
  599. int x, y;
  600. x = lParam & 0xffff;
  601. w.mouseProps.x = x;
  602. y = (lParam >> 16) & 0xffff;
  603. w.mouseProps.y = y;
  604. w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
  605. w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
  606. w.mouseProps.middleDown = true;
  607. _TestNumberOfClicks(w,windowVars,x,y,3);
  608. w.onTertiaryMouseDown();
  609. break;
  610. case WM_MBUTTONUP:
  611. ReleaseCapture();
  612. //window.mouseProps.rightDown = 0;
  613. //check for double click first
  614. _TestNumberOfClicksUp(w,windowVars,3);
  615. //fill _mouseProps
  616. int x, y;
  617. x = lParam & 0xffff;
  618. w.mouseProps.x = x;
  619. y = (lParam >> 16) & 0xffff;
  620. w.mouseProps.y = y;
  621. w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
  622. w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
  623. w.mouseProps.middleDown = false;
  624. w.onTertiaryMouseUp();
  625. break;
  626. case WM_XBUTTONDOWN:
  627. SetFocus(hWnd);
  628. SetCapture(hWnd);
  629. // FILL THE MOUSEPROPERTIES STRUCTURE FOR THE WINDOW
  630. //w.mouseProps.rightDown = 1;
  631. //check bounds for the controls
  632. int x, y;
  633. x = lParam & 0xffff;
  634. w.mouseProps.x = x;
  635. y = (lParam >> 16) & 0xffff;
  636. w.mouseProps.y = y;
  637. wParam >>= 16;
  638. if (wParam) {
  639. wParam--;
  640. _TestNumberOfClicks(w,windowVars,x,y,4 + cast(uint)wParam);
  641. w.onOtherMouseDown(cast(uint)wParam);
  642. }
  643. break;
  644. case WM_XBUTTONUP:
  645. ReleaseCapture();
  646. //window.mouseProps.rightDown = 0;
  647. //fill _mouseProps
  648. int x, y;
  649. x = lParam & 0xffff;
  650. w.mouseProps.x = x;
  651. y = (lParam >> 16) & 0xffff;
  652. w.mouseProps.y = y;
  653. wParam >>= 16;
  654. if (wParam) {
  655. wParam--;
  656. //check for double click
  657. _TestNumberOfClicksUp(w,windowVars,4 + cast(uint)wParam);
  658. w.onOtherMouseUp(cast(uint)wParam);
  659. }
  660. break;
  661. case WM_MOUSEHWHEEL:
  662. w.onMouseWheelX(0);
  663. break;
  664. case WM_MOUSEWHEEL:
  665. w.onMouseWheelY(0);
  666. break;
  667. case WM_MOUSEMOVE:
  668. int x, y;
  669. x = lParam & 0xffff;
  670. w.mouseProps.x = x;
  671. y = (lParam >> 16) & 0xffff;
  672. w.mouseProps.y = y;
  673. // Console.putln("mouse move window! x:", x, "y:", y);
  674. w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
  675. w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
  676. w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
  677. if (windowVars.hoverTimerSet==0) {
  678. SetTimer(hWnd, 0, 55, null);
  679. windowVars.hoverTimerSet = 1;
  680. }
  681. w.onMouseMove();
  682. break;
  683. // Internal Timing Functions
  684. case WM_MOUSELEAVE:
  685. w.onMouseLeave();
  686. break;
  687. case WM_MOUSECAPTURE: //made up event
  688. if (windowVars.hoverTimerSet == 1) {
  689. KillTimer(hWnd, 0);
  690. windowVars.hoverTimerSet = 0;
  691. }
  692. SetCapture(hWnd);
  693. break;
  694. case WM_MOVE:
  695. RECT rt;
  696. GetWindowRect(hWnd, &rt);
  697. if (!windowVars.supress_WM_MOVE) {
  698. w._x = rt.left;
  699. w._y = rt.top;
  700. w.onMove();
  701. windowVars.supress_WM_MOVE = false;
  702. }
  703. break;
  704. case WM_KEYDOWN:
  705. Key key;
  706. key.code = cast(uint)wParam;
  707. w.onKeyDown(key);
  708. break;
  709. //might have to translate these keys
  710. case WM_CHAR:
  711. if ((wParam == Key.Backspace)
  712. || (wParam == Key.Return)
  713. || (wParam == Key.Tab)) {
  714. break;
  715. }
  716. ushort stuff[2] = (cast(ushort*)&wParam)[0 .. 2];
  717. //printf("%x %x", stuff[0], stuff[1]);
  718. w.onKeyChar(cast(dchar)wParam);
  719. break;
  720. case WM_DEADCHAR:
  721. ushort stuff[2] = (cast(ushort*)&wParam)[0 .. 2];
  722. //printf("%x %x", stuff[0], stuff[1]);
  723. break;
  724. case WM_UNICHAR:
  725. if (wParam == 0xFFFF) {
  726. return 1;
  727. }
  728. ushort stuff[2] = (cast(ushort*)&wParam)[0 .. 2];
  729. //printf("%x %x", stuff[0], stuff[1]);
  730. w.onKeyChar(cast(dchar)wParam);
  731. break;
  732. case WM_KEYUP:
  733. Key key;
  734. key.code = cast(uint)wParam;
  735. w.onKeyUp(key);
  736. break;
  737. case WM_SIZE:
  738. RECT rt;
  739. GetClientRect(hWnd, &rt);
  740. if (!windowVars.supress_WM_SIZE) {
  741. w._width = rt.right;
  742. w._height = rt.bottom;
  743. w.onResize();
  744. if (cast(GLWindow)w !is null) {
  745. windowVars.gameLoopCallResize();
  746. }
  747. windowVars.supress_WM_SIZE = false;
  748. }
  749. // was it minimized? maximized?
  750. if (w.state != WindowState.Fullscreen) {
  751. if (wParam == SIZE_MAXIMIZED && w.state != WindowState.Minimized) {
  752. if (!windowVars.supress_WM_SIZE_state) {
  753. w.state = WindowState.Maximized;
  754. w.onStateChange();
  755. windowVars.supress_WM_SIZE_state = false;
  756. }
  757. }
  758. else if (wParam == SIZE_MINIMIZED && w.state != WindowState.Maximized) {
  759. if (!windowVars.supress_WM_SIZE_state) {
  760. w.state = WindowState.Minimized;
  761. w.onStateChange();
  762. windowVars.supress_WM_SIZE_state = false;
  763. }
  764. }
  765. else if (wParam == SIZE_RESTORED && w.state != WindowState.Normal) {
  766. if (!windowVars.supress_WM_SIZE_state) {
  767. w.state = WindowState.Normal;
  768. w.onStateChange();
  769. windowVars.supress_WM_SIZE_state = false;
  770. }
  771. }
  772. }
  773. break;
  774. case WM_TIMER:
  775. if (wParam == 0) {
  776. //Internal Timer (mouse hover)
  777. POINT pt;
  778. GetCursorPos(&pt);
  779. if (WindowFromPoint(pt) != hWnd) {
  780. KillTimer(hWnd, 0);
  781. windowVars.hoverTimerSet = 0;
  782. SendMessageW(hWnd, WM_MOUSELEAVE, 0,0);
  783. }
  784. else {
  785. POINT pnt[2];
  786. pnt[0].x = 0;
  787. pnt[0].y = 0;
  788. pnt[1].x = w.width-1;
  789. pnt[1].y = w.height-1;
  790. ClientToScreen(hWnd, &pnt[0]);
  791. ClientToScreen(hWnd, &pnt[1]);
  792. if (pt.x < pnt[0].x || pt.y < pnt[0].y || pt.x > pnt[1].x || pt.y > pnt[1].y) {
  793. KillTimer(hWnd,0);
  794. windowVars.hoverTimerSet = 0;
  795. SendMessageW(hWnd, WM_MOUSELEAVE, 0, 0);
  796. }
  797. }
  798. //KillTimer(hWnd, 0);
  799. }
  800. else if (wParam == 1) {
  801. //Internal Timer (double click test)
  802. //kill the timer
  803. windowVars.doubleClickTimerSet = -windowVars.doubleClickTimerSet;
  804. KillTimer(hWnd, 1);
  805. }
  806. break;
  807. // These are Djehuty Protocol Requests
  808. // They do not belong in the final release
  809. case WM_USER + 0xff00:
  810. SendMessageW(cast(HWND)lParam, WM_USER+0xf000, 0,0);
  811. break;
  812. case WM_USER + 0xff01:
  813. // create window 1
  814. // p1 : width
  815. // p2 : height
  816. break;
  817. case WM_USER + 0xff02:
  818. // create window 2
  819. // p1: x
  820. // p2: y
  821. break;
  822. default:
  823. return DefWindowProcW(hWnd, uMsg, wParam, lParam);
  824. }
  825. return 0;
  826. }
  827. }