1 namespace gui::drivers;
12 #define _WIN32_WINNT 0x0501
19 #define WIN32_LEAN_AND_MEAN
20 #define Method _Method
23 #define String _String
25 #define Platform _Platform
31 #if defined(ECERE_VANILLA)
32 #define ECERE_NOJOYSTICK
35 #ifndef ECERE_NODINPUT
36 #ifndef ECERE_NOJOYSTICK
37 #define DIRECTINPUT_VERSION 0x700
40 #define DIRECTINPUT_VERSION 0x300
50 #define VK_EQUALS 0xBB
53 #define VK_PERIOD 0xBE
56 #define VK_LBRACKET 0xDB
57 #define VK_BACK_SLASH 0xDC
58 #define VK_RBRACKET 0xDD
62 #define WM_MOUSEWHEEL 0x20A
66 #define IDC_HAND (char *)0x7F89
71 #define LWA_COLORKEY 0x00000001
72 #define LWA_ALPHA 0x00000002
74 #define WS_EX_LAYERED 0x00080000
79 SetLayeredWindowAttributes(
97 #define ECERE_NODINPUT
98 #define ECERE_NOJOYSTICK
99 #define ECERE_NOBLENDING
102 static byte key2VK[256] =
104 0,VK_ESCAPE,'1','2','3','4','5','6','7','8','9','0',VK_MINUS,VK_EQUALS,VK_BACK,VK_TAB,
105 'Q','W','E','R','T','Y','U','I','O','P',VK_LBRACKET,VK_RBRACKET,VK_RETURN,VK_LCONTROL,'A','S',
106 'D','F','G','H','J','K','L',VK_SEMI,VK_QUOTE,VK_TILDE,VK_LSHIFT,VK_BACK_SLASH,'Z','X','C','V',
107 'B','N','M',VK_COMMA,VK_PERIOD,VK_DIVIDE,VK_RSHIFT,VK_MULTIPLY,VK_LMENU,VK_SPACE,VK_CAPITAL,VK_F1,VK_F2,VK_F3,VK_F4,VK_F5,
108 VK_F6,VK_F7,VK_F8,VK_F9,VK_F10,VK_NUMLOCK,VK_SCROLL,VK_NUMPAD7,VK_NUMPAD8,VK_NUMPAD9,VK_SUBTRACT,VK_NUMPAD4,VK_NUMPAD5,VK_NUMPAD6,VK_ADD,VK_NUMPAD1,
109 VK_NUMPAD2,VK_NUMPAD3,VK_NUMPAD0,VK_DELETE,0,0,0,VK_F11,VK_F12,0,0,0,0,0,0,0,
110 0,VK_RCONTROL,0,0,VK_RMENU,0,VK_HOME,VK_UP,VK_PRIOR,VK_LEFT,VK_RIGHT,VK_END,VK_DOWN,VK_NEXT,VK_INSERT,VK_DELETE
112 static const uint16 className[] = L"Ecere Application";
113 static HINSTANCE hInstance;
115 static DEVMODE devMode;
116 #ifndef ECERE_NODINPUT
117 static HWND acquiredWindow = null;
119 static HCURSOR systemCursors[SystemCursor];
120 static bool fullScreenMode;
121 static int desktopX = 0, desktopY = 0, desktopW = 0, desktopH = 0;
122 static DWORD hiResTimer;
123 // static HWND topWindow;
125 static HWND startBar;
127 #ifndef ECERE_NODINPUT
129 static HMODULE dInputDll = null;
130 static BOOL * (WINAPI * directInputCreate)(HINSTANCE, DWORD, IDirectInput **, void *);
131 static IDirectInput * dInput = null;
132 static IDirectInputDevice * directMouse = null;
133 #ifndef ECERE_NOJOYSTICK
134 static int numJoysticks = 0;
135 static IDirectInputDevice2 * directJoysticks[NUMJOY] = {null,null,null,null};
140 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
141 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp;
142 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
143 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
144 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;
145 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
146 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
147 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;
148 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
149 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
150 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
151 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick;
152 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown;
153 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
157 static Box lastMonitorAreas[32];
158 static Box monitorAreas[32];
161 static bool EnumerateMonitors(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
163 MONITORINFO info = { 0 };
164 info.cbSize = sizeof(MONITORINFO);
165 GetMonitorInfo(hMonitor, &info);
166 monitorAreas[monitor] = { info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom };
171 static bool externalDisplayChange;
173 static int taskBarState;
174 static WINDOWPLACEMENT taskBarPlacement;
175 static bool activateApp;
177 static SystemCursor lastCursor = (SystemCursor)-1;
179 void AeroSnapPosition(Window window, int x, int y, int w, int h)
181 int oldX = window.absPosition.x;
183 // To prevent having a window < minClientSize with Aero Snap, because we don't receive a WM_SIZING!
184 // The sensible implementation of this is in WM_SIZING
188 window.GetDecorationsSize(&ew, &eh);
196 gw = Max(gw, window.minSize.w);
197 gh = Max(gh, window.minSize.h);
198 gw = Min(gw, window.maxSize.w);
199 gh = Min(gh, window.maxSize.h);
201 if(!window.OnResizing(&gw, &gh))
203 gw = window.clientSize.w;
204 gh = window.clientSize.h;
207 gw = Max(gw, window.skinMinSize.w);
208 gh = Max(gh, window.skinMinSize.h);
213 if(w != gw || h != gh)
216 // Adjust x position if we resized from top or bottom left corner
224 guiApp.interfaceDriver.PositionRootWindow(window, x, y, w, h, move, true);
227 window.ExternalPosition(x, y, w, h);
230 class Win32Interface : Interface
232 class_property(name) = "Win32";
234 void ::RepositionDesktop(bool updateChildren)
237 static double lastTime = 0, time;
240 //static Size lastScreen;
241 //static Point lastScreenPos;
242 static double lastAutoHideCheck = 0;
243 int newTaskBarState = taskBarState;
244 HMONITOR primaryMonitor = 0;
247 if(time - lastTime < 0.1) return;
250 // Every sec, check for the auto hide property
251 if(time - lastAutoHideCheck > 1)
253 APPBARDATA appBarData = { 0 };
254 newTaskBarState = (int)SHAppBarMessage(ABM_GETSTATE, &appBarData);
255 lastAutoHideCheck = time;
259 EnumDisplayMonitors(null, null, EnumerateMonitors, 0);
260 for(c = 0; c<monitor; c++)
262 if(monitorAreas[c].left != lastMonitorAreas[c].left ||
263 monitorAreas[c].top != lastMonitorAreas[c].top ||
264 monitorAreas[c].right != lastMonitorAreas[c].right ||
265 monitorAreas[c].bottom != lastMonitorAreas[c].bottom)
271 memcpy(lastMonitorAreas, monitorAreas, sizeof(monitorAreas));
273 guiApp.virtualScreen =
275 GetSystemMetrics(SM_CXVIRTUALSCREEN),
276 GetSystemMetrics(SM_CYVIRTUALSCREEN)
278 guiApp.virtualScreenPos =
280 x = GetSystemMetrics(SM_XVIRTUALSCREEN),
281 y = GetSystemMetrics(SM_YVIRTUALSCREEN)
285 HMONITOR monitor = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY);
288 MONITORINFO info = { 0 };
289 info.cbSize = sizeof(MONITORINFO);
290 primaryMonitor = monitor;
291 GetMonitorInfo(monitor, &info);
292 x = info.rcMonitor.left;
293 y = info.rcMonitor.top;
294 w = info.rcMonitor.right - info.rcWork.left;
295 h = info.rcMonitor.bottom - info.rcWork.top;
300 WINDOWPLACEMENT placement = { 0 };
301 placement.length = sizeof(WINDOWPLACEMENT);
303 if(!GetWindowPlacement(startBar, &placement))
305 startBar = FindWindowA("Shell_TrayWnd", null);
306 GetWindowPlacement(startBar, &placement);
309 HMONITOR taskBarMonitor = MonitorFromWindow(startBar, MONITOR_DEFAULTTONEAREST);
310 if(primaryMonitor == taskBarMonitor)
312 if(placement.rcNormalPosition.top <= 0 && placement.rcNormalPosition.bottom >= h - 1)
314 if(placement.rcNormalPosition.left <= 0)
316 x = (taskBarState & ABS_AUTOHIDE) ? 1 : placement.rcNormalPosition.right;
320 w = (taskBarState & ABS_AUTOHIDE) ? (w - 1) : Min(placement.rcNormalPosition.left, w);
322 else if(placement.rcNormalPosition.left <= 0 && placement.rcNormalPosition.right >= w - 1)
324 if(placement.rcNormalPosition.top <= 0)
326 y = (taskBarState & ABS_AUTOHIDE) ? 1 : placement.rcNormalPosition.bottom;
330 h = (taskBarState & ABS_AUTOHIDE) ? (h - 1) : Min(placement.rcNormalPosition.top, h);
336 placement.rcNormalPosition.left != taskBarPlacement.rcNormalPosition.left ||
337 placement.rcNormalPosition.top != taskBarPlacement.rcNormalPosition.top ||
338 placement.rcNormalPosition.right != taskBarPlacement.rcNormalPosition.right ||
339 placement.rcNormalPosition.bottom != taskBarPlacement.rcNormalPosition.bottom ||
340 newTaskBarState != taskBarState)
342 taskBarState = newTaskBarState;
343 guiApp.desktop.size.w = 0;
348 taskBarPlacement = placement;
349 guiApp.SetDesktopPosition(x, y, w, h, updateChildren);
352 //lastScreen = guiApp.virtualScreen;
353 //lastScreenPos = guiApp.virtualScreenPos;
357 /****************************************************************************
358 /// PRIVATE UTILITY FUNCTIONS /////////////
359 ****************************************************************************/
360 // --- Keyboard Input ---
361 bool ::ProcessKeyMessage(Window window, DWORD msg, WPARAM wParam, LPARAM lParam, unichar ch)
367 bool frenchShift = (ch < 0x10000) ? (((VkKeyScan((uint16)ch) >> 8) & 6) == 6) : false;
369 if(msg == WM_CHAR || msg == WM_DEADCHAR)
374 if(msg == WM_MOUSEWHEEL)
375 code = (((short) HIWORD(wParam)) < 0) ? wheelDown : wheelUp;
378 key = (byte)((lParam & 0xFF0000)>>16);
379 if(lParam & 0x1000000)
381 key = Interface::GetExtendedKey(key);
391 if(msg == WM_MOUSEWHEEL)
393 if(::GetAsyncKeyState(VK_SHIFT) & 0x80000)
395 if(::GetAsyncKeyState(VK_CONTROL) & 0x80000)
397 if(::GetAsyncKeyState(VK_MENU) & 0x80000)
400 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code, 0);
404 if(key != leftShift && key != rightShift && ::GetKeyState(VK_SHIFT) & 0x80000)
406 if(key != leftControl && key != rightControl && ::GetKeyState(VK_CONTROL) & 0x80000 && !frenchShift)
408 if(key != leftAlt && key != rightAlt && ::GetKeyState(VK_MENU) & 0x80000 && !frenchShift)
411 byte ch = Interface::TranslateKeykey, code.shift);
412 if(::GetKeyState(VK_CAPITAL))
416 if(msg == WM_KEYUP || msg == WM_SYSKEYUP)
418 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, code, ch);
422 if(!(lParam & 0x40000000))
427 Class * keyClass = eSystem_FindClass(__ecereModule, "Key");
428 code.OnGetString(string, null, null);
429 eSystem_Logf("%s\n", string);
433 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, code, ch);
436 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code,ch);
443 // --- Window procedure ---
444 DWORD CALLBACK ::ApplicationWindow(HWND windowHandle, UINT msg, WPARAM wParam, LPARAM lParam)
447 Window window = (Window)GetWindowLongPtr(windowHandle, GWLP_USERDATA);
449 Window window = (Window)GetWindowLong(windowHandle, GWL_USERDATA);
451 static Point lastPos;
458 case WM_QUERYNEWPALETTE:
459 case WM_PALETTECHANGED:
461 window.display.RestorePalette();
462 UpdateWindow(windowHandle);
466 if(!fullScreenMode && !guiApp.IsModeSwitching())
470 Window modalRoot = window.FindModal();
472 HWND modalWindow = modalRoot ? modalRoot.windowHandle : null;
474 FLASHWINFO flashInfo = { 0 };
475 flashInfo.cbSize = sizeof(FLASHWINFO);
476 flashInfo.hwnd = window.windowHandle;
477 flashInfo.uCount = 0;
478 flashInfo.dwFlags = FLASHW_STOP;
479 FlashWindowEx((void *)&flashInfo);
481 if(modalWindow && modalWindow != windowHandle)
482 modalRoot.ExternalActivate(true, true, window, null);
484 window.ExternalActivate(true, true, window, null);
491 foreground = GetForegroundWindow();
492 if(foreground == windowHandle && lParam)
493 foreground = (HWND)lParam;
495 GetWindowThreadProcessId(foreground, &id);
498 windowLong = (void*)GetWindowLongPtr(foreground, GWLP_WNDPROC);
500 windowLong = (void*)GetWindowLong(foreground, GWL_WNDPROC);
502 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
503 // The != ApplicationWindow check is for not recognizing the Console window as an Ecere Window
504 // That check causes a problem with the OpenGL driver which seems to popup a window of a different class
505 if(window.displaySystem && window.displaySystem.driver == class(OpenGLDisplayDriver))
506 windowLong = (void *)ApplicationWindow;
508 if(id != GetCurrentProcessId() || windowLong != (void *)ApplicationWindow)
509 window.ExternalActivate(false, true, window, null);
510 // DefWindowProc for WM_NCACTIVATE draws the decorations, make sure it's drawn in the right state
511 return (uint)DefWindowProc(windowHandle, msg, window.active, lParam);
516 for(window = guiApp.desktop.firstChild; window; window = window.next)
517 SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 0,0,0,0,
518 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW);
522 return (uint)DefWindowProc(windowHandle, msg, window ? window.active : wParam, lParam);
525 if(!guiApp.IsModeSwitching())
529 HDC hdc = GetDC(windowHandle);
532 guiApp.SetAppFocus(false);
533 ShowWindow(windowHandle, SW_MINIMIZE);
534 ChangeDisplaySettings(null,0);
535 SetSystemPaletteUse(hdc, SYSPAL_STATIC);
539 ChangeDisplaySettings(&devMode, CDS_FULLSCREEN);
540 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
542 window.display.RestorePalette();
543 ShowWindow(windowHandle, SW_SHOWNORMAL);
544 guiApp.SetAppFocus(true);
546 window.display.Resize(window.clientSize.w, window.clientSize.h);
549 ReleaseDC(windowHandle, hdc);
555 if(wParam && !guiApp.desktop.active /*&& lParam != GetCurrentThreadID()*/)
559 for(window = guiApp.desktop.firstChild; window; window = window.next)
560 SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 0,0,0,0,
561 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW);
564 guiApp.SetAppFocus((bool)wParam);
568 guiApp.SetAppFocus((bool)wParam);
572 if(!window.alphaBlend || window.display.pixelFormat != pixelFormat888)
577 #define ACCESS_ITEM(l, id) \
578 ((FastItem)(((id) == -1) ? null : (((byte *)((l).items)) + (id) * (l).itemSize)))
581 #define ACCESS_ITEM(l, id) \
584 BoxItem item = window.dirtyArea.count ? (BoxItem)ACCESS_ITEM(window.dirtyArea, window.dirtyArea.first) : null;
586 BeginPaint(windowHandle, &ps);
588 // Prevent flickering if we're going to update anyways
590 printf(" Paint message (%d, %d)-(%d, %d)\n",
591 item ? item.box.left : 0,
592 item ? item.box.top : 0,
593 item ? item.box.right : 0,
594 item ? item.box.bottom : 0);
596 // Causes redraw bug...
597 if(!window.manageDisplay || !item ||
600 item.box.right < window.size.w - 1 ||
601 item.box.bottom < window.size.h - 1)
603 Box box { ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-1, ps.rcPaint.bottom-1 };
604 window.UpdateDirty(box);
606 // TODO: Fix precompiler with
607 // window.UpdateDirty((Box *)&ps.rcPaint);
608 EndPaint(windowHandle, &ps);
612 case WM_DISPLAYCHANGE:
614 static int lastBits = 0;
615 static int lastRes = 0;
616 if(lastBits != wParam || lastRes != lParam)
618 lastBits = (int)wParam;
619 lastRes = (int)lParam;
621 externalDisplayChange = true;
622 if(guiApp.desktop.DisplayModeChanged())
625 if(!window.style.hidden)
626 ShowWindow(windowHandle, SW_SHOWNOACTIVATE /*SW_SHOWNORMAL*/);
627 window.FigureCaption(caption);
628 SetRootWindowCaption(window, caption);
630 externalDisplayChange = false;
643 DWORD min = 0, max = 0;
645 if(msg != WM_CHAR && window.composing)
650 case WM_SYSKEYDOWN: min = max = WM_SYSCHAR; break;
651 case WM_KEYDOWN: min = max = WM_CHAR; break;
652 case WM_SYSKEYUP: min = WM_SYSCHAR; max = WM_SYSDEADCHAR; break;
653 case WM_KEYUP: min = WM_CHAR; max = WM_DEADCHAR; break;
656 // This is very annoying.
657 // PeekMessage somehow invokes this function directly... don't know why.
658 // Only crashes when running through debug mode in visual studio
660 if(msg == WM_CHAR || msg == WM_DEADCHAR || PeekMessage(&charMsg, windowHandle, min, max, PM_REMOVE))
662 ch = (msg == WM_CHAR || msg == WM_DEADCHAR) ? (unichar)wParam : (unichar)charMsg.wParam;
663 // TOCHECK: What is this for again? Fixing some obscure activation status?
664 // -- I believe this was somehow allowing 'unmaximizing', but was causing problems
665 // as there was no way to prevent AltEnter from doing so (e.g. when it is used for a node property)
666 // Worked around by fixing ProcessHotKeys to properly check for sysButtons in parent.parent when sys buttons
667 // are placed inside a menu bar for a document
669 if(msg == WM_SYSKEYDOWN && ch == 13)
671 ShowWindow(window.windowHandle, window.state == maximized ? SW_MAXIMIZE : SW_SHOWNORMAL);
672 // This last line been commented out for a long time:
673 // window.ExternalActivate(true, true, window, null);
676 if(msg == WM_SYSKEYUP || msg == WM_KEYUP)
678 if(!ProcessKeyMessage(window, WM_KEYDOWN, 0x40000000, 0, ch))
684 ProcessKeyMessage(window, msg, wParam, lParam, ch);
685 if(window.composing && msg == WM_CHAR)
687 COMPOSITIONFORM form;
688 Window caretOwner = guiApp.caretOwner;
691 HIMC ctx = ImmGetContext(windowHandle);
692 form.dwStyle = CFS_POINT;
693 form.ptCurrentPos.x = caretOwner.caretPos.x - caretOwner.scroll.x + caretOwner.absPosition.x - window.absPosition.x + 4;
694 form.ptCurrentPos.y = caretOwner.caretPos.y - caretOwner.scroll.x + caretOwner.absPosition.y - window.absPosition.y + 2;
695 window.composing = true;
696 ImmSetCompositionWindow(ctx, &form);
697 ImmReleaseContext(windowHandle, ctx);
700 if(msg != WM_MOUSEWHEEL)
704 case WM_IME_STARTCOMPOSITION:
706 COMPOSITIONFORM form;
707 Window caretOwner = guiApp.caretOwner;
710 HIMC ctx = ImmGetContext(windowHandle);
711 form.dwStyle = CFS_POINT;
712 form.ptCurrentPos.x = caretOwner.caretPos.x - caretOwner.scroll.x + caretOwner.absPosition.x - window.absPosition.x + 4;
713 form.ptCurrentPos.y = caretOwner.caretPos.y - caretOwner.scroll.y + caretOwner.absPosition.y - window.absPosition.y + 2;
715 form.rcArea.left = window.caretPos.x;
716 form.rcArea.top = 250;
717 form.rcArea.right = 500;
718 form.rcArea.bottom = 300;
720 window.composing = true;
721 DefWindowProc(windowHandle, msg, wParam, lParam);
722 ImmSetCompositionWindow(ctx, &form);
723 ImmSetStatusWindowPos(ctx, &form.ptCurrentPos);
725 FontResource res = caretOwner.font;
726 LOGFONT font = { 0 };
728 int pixels = GetDeviceCaps(hdc, LOGPIXELSY);
730 font.lfHeight = -(int)((float)res.size * pixels / 72 + 0.5);
731 font.lfWeight = res.flags.bold ? FW_BOLD : FW_NORMAL;
732 font.lfItalic = res.flags.italic ? TRUE : FALSE,
733 font.lfUnderline = res.flags.underline ? TRUE : FALSE;
734 font.lfCharSet = DEFAULT_CHARSET;
735 font.lfOutPrecision = OUT_DEFAULT_PRECIS;
736 font.lfClipPrecision = CLIP_DEFAULT_PRECIS;
737 font.lfQuality = DEFAULT_QUALITY;
738 font.lfPitchAndFamily = (byte)(DEFAULT_PITCH|FF_DONTCARE); // TODO: Fix compiler 0 | 0 to produce byte, not int
739 UTF8toUTF16Buffer(res.faceName, font.lfFaceName, LF_FACESIZE);
741 ImmSetCompositionFont(ctx, &font);
742 ImmReleaseContext(windowHandle, ctx);
748 case WM_IME_ENDCOMPOSITION:
749 window.composing = false;
750 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
751 /*case WM_IME_COMPOSITION:
752 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
754 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
756 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
758 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
760 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
762 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
763 case WM_IME_SETCONTEXT:
764 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
766 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
768 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
769 case WM_IME_COMPOSITIONFULL:
770 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
773 if(window.nativeDecorations)
774 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
784 case WM_LBUTTONDBLCLK:
786 case WM_RBUTTONDBLCLK:
788 case WM_MBUTTONDBLCLK:
790 x = window.absPosition.x;
791 y = window.absPosition.y;
792 /*case WM_NCLBUTTONUP:
795 case WM_NCLBUTTONDOWN:
796 case WM_NCLBUTTONDBLCLK:
797 case WM_NCRBUTTONDOWN:
798 case WM_NCRBUTTONDBLCLK:
799 case WM_NCMBUTTONDOWN:
800 case WM_NCMBUTTONDBLCLK:*/
804 bool consequential = false;
806 x += (short)LOWORD(lParam);
807 y += (short)HIWORD(lParam);
809 if(window.nativeDecorations && msg != WM_NCMOUSEMOVE)
811 x += window.clientStart.x;
812 y += window.clientStart.y - (window.hasMenuBar ? skinMenuHeight : 0);
815 if(::GetKeyState(VK_SHIFT) & 0x80000) code.shift = true;
816 if(::GetKeyState(VK_CONTROL) & 0x80000) code.ctrl = true;
817 if(::GetKeyState(VK_MENU) & 0x80000) code.alt = true;
818 if(wParam & MK_LBUTTON) code.left = true;
819 if(wParam & MK_MBUTTON) code.middle = true;
820 if(wParam & MK_RBUTTON) code.right = true;
822 if(msg == WM_MOUSEMOVE)
824 if(lastPos.x == x && lastPos.y == y)
825 consequential = true;
835 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x,y,&code, consequential, false);
837 //case WM_NCLBUTTONDBLCLK:
838 case WM_LBUTTONDBLCLK:
839 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick, x,y,&code, false, true))
841 //case WM_NCLBUTTONDOWN:
843 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown,x,y,&code, false,
844 /*(msg == WM_LBUTTONDBLCLK) ? false: */true);
846 //case WM_NCLBUTTONUP:
847 case WM_LBUTTONUP: window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x,y,&code, false, false);break;
848 //case WM_NCMBUTTONDBLCLK:
849 case WM_MBUTTONDBLCLK:
850 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick, x,y,&code, false, false))
852 //case WM_NCMBUTTONDOWN:
854 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown, x,y,&code, false,
855 (msg == WM_LBUTTONDBLCLK) ? false: true);
857 //case WM_NCMBUTTONUP:
859 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp, x,y,&code, false, false);
861 //case WM_NCRBUTTONDBLCLK:
862 case WM_RBUTTONDBLCLK:
863 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick, x,y,&code, false, true))
865 //case WM_NCRBUTTONDOWN:
867 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown, x,y,&code, false,
868 (msg == WM_LBUTTONDBLCLK) ? false: true);
870 //case WM_NCRBUTTONUP:
872 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp, x,y,&code, false, false);
876 if(msg == WM_NCMOUSEMOVE)
877 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
882 if(window.nativeDecorations)
884 if(DefWindowProc(windowHandle, msg, wParam, lParam))
887 // SetCursor(systemCursors[0]);
888 SetCursor((lastCursor == (SystemCursor)-1) ? null : systemCursors[lastCursor]);
891 case WM_EXITMENULOOP:
892 case WM_EXITSIZEMOVE:
893 // We had some DirectInput stuff in here
895 case WM_ENTERMENULOOP:
896 case WM_ENTERSIZEMOVE:
897 // We had some DirectInput stuff in here
907 WINDOWPLACEMENT placement = { 0 };
909 placement.length = sizeof(WINDOWPLACEMENT);
910 GetWindowRect(windowHandle, &rcWindow);
911 GetWindowPlacement(windowHandle, &placement);
913 x = rcWindow.left - desktopX;
914 y = rcWindow.top - desktopY;
915 w = rcWindow.right - rcWindow.left;
916 h = rcWindow.bottom - rcWindow.top;
918 AeroSnapPosition(window, x, y, w, h);
925 RECT * rect = (RECT *)lParam;
929 window.GetDecorationsSize(&ew, &eh);
931 w = rect->right - rect->left;
932 h = rect->bottom - rect->top;
940 w = Max(w, window.minSize.w);
941 h = Max(h, window.minSize.h);
942 w = Min(w, window.maxSize.w);
943 h = Min(h, window.maxSize.h);
945 if(!window.OnResizing(&w, &h))
947 w = window.clientSize.w;
948 h = window.clientSize.h;
951 w = Max(w, window.skinMinSize.w);
952 h = Max(h, window.skinMinSize.h);
957 if(wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT)
958 rect->left = rect->right - w;
960 rect->right = rect->left + w;
962 if(wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOP || wParam == WMSZ_TOPRIGHT)
963 rect->top = rect->bottom - h;
965 rect->bottom = rect->top + h;
971 if(window.nativeDecorations)
975 GetWindowRect(windowHandle, &rcWindow);
977 if(wParam == SIZE_MAXIMIZED && window.state != maximized)
978 window.state = maximized;
979 else if(wParam == SIZE_MINIMIZED && window.state != minimized)
980 window.state = minimized;
981 else if(wParam == SIZE_RESTORED && window.state != normal && window.visible)
982 window.state = normal;
984 x = rcWindow.left - desktopX;
985 y = rcWindow.top - desktopY;
986 w = rcWindow.right - rcWindow.left;
987 h = rcWindow.bottom - rcWindow.top;
989 AeroSnapPosition(window, x, y, w, h);
990 if(!guiApp.modeSwitching)
991 window.UpdateVisual(null);
994 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
998 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
1002 return (uint)DefMDIChildProc(windowHandle, msg, wParam, lParam);
1003 // return DefWindowProc(windowHandle, msg, wParam, lParam);
1007 // --- DirectInput ---
1009 #ifndef ECERE_NODINPUT
1011 #ifndef ECERE_NOJOYSTICK
1012 bool CALLBACK ::JoystickCallback( const DIDEVICEINSTANCE* pdidInstance, void * context )
1014 if(!dInput->lpVtbl->CreateDevice(dInput, &GUID_Joystick,
1015 (IDirectInputDevice **)&directJoysticks[numJoysticks], null ))
1017 return DIENUM_CONTINUE;
1020 bool CALLBACK ::JoystickAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, void * context )
1023 IDirectInputDevice2 * curJoy = (IDirectInputDevice2 *)context;
1025 diprg.diph.dwSize = sizeof(DIPROPRANGE);
1026 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1027 diprg.diph.dwHow = DIPH_BYOFFSET;
1028 diprg.diph.dwObj = pdidoi->dwOfs;
1031 if(curJoy->lpVtbl->SetProperty(curJoy, DIPROP_RANGE, &diprg.diph))
1033 return DIENUM_CONTINUE;
1037 void ::TerminateDirectInput()
1042 directMouse->lpVtbl->Unacquire(directMouse);
1043 directMouse->lpVtbl->Release(directMouse);
1046 #ifndef ECERE_NOJOYSTICK
1047 for(j=0; j<numJoysticks; j++)
1049 if (directJoysticks[j])
1051 directJoysticks[j]->lpVtbl->Unacquire(directJoysticks[j]);
1052 directJoysticks[j]->lpVtbl->Release(directJoysticks[j]);
1053 directJoysticks[j] = null;
1060 dInput->lpVtbl->Release(dInput);
1064 directInputCreate = null;
1068 FreeLibrary(dInputDll);
1073 bool ::InitDirectInput()
1075 bool result = false;
1077 dInputDll = LoadLibraryA("dinput.dll");
1080 if((directInputCreate = (void *)GetProcAddress(dInputDll, "DirectInputCreateA")))
1082 if(!directInputCreate( hInstance, DIRECTINPUT_VERSION, &dInput, null ))
1087 if(!dInput->lpVtbl->CreateDevice(dInput, &GUID_SysMouse, &directMouse, null ))
1088 directMouse->lpVtbl->SetDataFormat(directMouse, &c_dfDIMouse );
1090 #ifndef ECERE_NOJOYSTICK
1092 dInput->lpVtbl->EnumDevices(dInput, DIDEVTYPE_JOYSTICK, JoystickCallback, null, DIEDFL_ATTACHEDONLY );
1093 for(j=0; j<NUMJOY; j++)
1094 if(directJoysticks[j])
1095 if(!directJoysticks[j]->lpVtbl->SetDataFormat(directJoysticks[j], &c_dfDIJoystick ))
1096 directJoysticks[j]->lpVtbl->EnumObjects(directJoysticks[j], JoystickAxesCallback, directJoysticks[j], DIDFT_AXIS );
1105 void ::AcquireDirectInput(HWND windowHandle, bool state)
1107 if((state && !acquiredWindow) || (!state && acquiredWindow == windowHandle))
1114 directMouse->lpVtbl->SetCooperativeLevel(directMouse, /*fullScreenMode ? */windowHandle /*: HWND_DESKTOP*/, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
1115 directMouse->lpVtbl->Acquire(directMouse);
1118 directMouse->lpVtbl->Unacquire(directMouse);
1120 #ifndef ECERE_NOJOYSTICK
1121 for(j = 0; j<NUMJOY; j++)
1122 if(directJoysticks[j])
1126 directJoysticks[j]->lpVtbl->SetCooperativeLevel(directJoysticks[j], /*fullScreenMode ? */windowHandle /*: HWND_DESKTOP*/, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
1127 directJoysticks[j]->lpVtbl->Acquire(directJoysticks[j]);
1130 directJoysticks[j]->lpVtbl->Unacquire(directJoysticks[j]);
1133 acquiredWindow = state ? windowHandle : null;
1138 /****************************************************************************
1139 /// INTEGRATION FUNCTIONALITY /////////////
1140 ****************************************************************************/
1141 bool eisWIN32ProcessKey(Window window, DWORD msg, DWORD wParam, DWORD lParam, byte ch)
1143 return ProcessKeyMessage(window, msg, wParam, lParam, ch);
1146 HWND eisWIN32GetWindowHandle(Window window)
1148 return window.windowHandle ? window.windowHandle : window.rootWindow.windowHandle;
1151 /****************************************************************************
1152 /// DRIVER IMPLEMENTATION /////////////
1153 ****************************************************************************/
1156 void CALLBACK ::TimerProc(UINT uTimerID, UINT uMsg, uint64 dwUser, uint64 dw1, uint64 dw2)
1158 void CALLBACK ::TimerProc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
1161 guiApp.SignalEvent();
1164 // --- User Interface System ---
1169 CS_DBLCLKS, ApplicationWindow, 0L, 0L, 0,
1170 LoadIcon(null, IDI_APPLICATION),
1177 wcl.hInstance = hInstance = GetModuleHandle(null);
1178 RegisterClass(&wcl);
1180 // Move that in reposition desktop
1181 startBar = FindWindowA("Shell_TrayWnd", null);
1183 systemCursors[arrow] = LoadCursor(null, IDC_ARROW);
1184 systemCursors[iBeam] = LoadCursor(null, IDC_IBEAM);
1185 systemCursors[cross] = LoadCursor(null, IDC_CROSS);
1186 systemCursors[moving] = LoadCursor(null, IDC_SIZEALL);
1187 systemCursors[sizeNESW] = LoadCursor(null, IDC_SIZENESW);
1188 systemCursors[sizeNS ] = LoadCursor(null, IDC_SIZENS);
1189 systemCursors[sizeNWSE] = LoadCursor(null, IDC_SIZENWSE);
1190 systemCursors[sizeWE ] = LoadCursor(null, IDC_SIZEWE);
1191 systemCursors[hand ] = LoadCursor(null, IDC_HAND);
1193 SetTimer(null, 0, (DWORD)(1000.0 / 18.2), null);
1194 //SetTimer(null, 0, 1, null);
1198 hiResTimer = timeSetEvent(
1201 TimerProc,0,TIME_PERIODIC);
1204 hiResTimer = timeSetEvent(
1207 TimerProc,0,TIME_PERIODIC);
1211 topWindow = CreateWindowEx(0, className, "",WS_POPUP,0,0,1,1,HWND_DESKTOP,
1212 null, hInstance, null);
1219 if(hiResTimer) timeKillEvent(hiResTimer);
1220 #ifndef ECERE_NODINPUT
1221 TerminateDirectInput();
1225 void SetTimerResolution(uint hertz)
1227 if(hiResTimer) timeKillEvent(hiResTimer);
1229 hiResTimer = timeSetEvent(1000 / hertz, 1000 / hertz, TimerProc, 0, TIME_PERIODIC);
1232 bool ProcessInput(bool processAll)
1236 RepositionDesktop(true);
1237 if(PeekMessage(&msg,0,0,0,PM_NOREMOVE))
1239 while(PeekMessage(&msg,0,0,0,PM_REMOVE))
1241 TranslateMessage(&msg);
1242 DispatchMessage(&msg);
1243 // printf("%d\n", msg.message);
1244 if(!processAll || msg.message == WM_TIMER) break;
1253 MsgWaitForMultipleObjects(1, (void **)guiApp.semaphore, FALSE, (uint)(1000 / 18.2) /*INFINITE*/, QS_ALLINPUT);
1256 void Lock(Window window)
1261 void Unlock(Window window)
1266 const char ** GraphicsDrivers(int * numDrivers)
1268 static const char *graphicsDrivers[] = { "GDI", "DirectDraw", "OpenGL", "Direct3D", "Direct3D8", "Direct3D9" };
1269 *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
1270 return (const char **)graphicsDrivers;
1273 void GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate)
1275 *fullScreen = fullScreenMode;
1279 for(c = 0; c<Resolution::enumSize; c++)
1280 if(GetResolutionWidth(c) == devMode.dmPelsWidth && GetResolutionHeight(c) == devMode.dmPelsHeight)
1285 switch(devMode.dmBitsPerPel)
1287 case 8: *colorDepth = pixelFormat8; break;
1288 case 16: *colorDepth = pixelFormat555; break;
1289 default: *colorDepth = pixelFormat888; break;
1291 * refreshRate = devMode.dmDisplayFrequency;
1295 void EnsureFullScreen(bool *fullScreen)
1300 bool ScreenMode(bool fullScreen, Resolution resolution, PixelFormat colorDepth, int refreshRate, bool * textMode)
1305 fullScreenMode = fullScreen;
1309 FillBytes(&devMode, 0, sizeof(DEVMODE));
1310 devMode.dmSize = (uint16)sizeof(devMode);
1311 devMode.dmFields |=DM_BITSPERPEL;
1312 devMode.dmFields |=DM_PELSWIDTH|DM_PELSHEIGHT;
1313 devMode.dmFields |= DM_DISPLAYFREQUENCY;
1314 devMode.dmBitsPerPel = colorDepth ? GetDepthBits(colorDepth) : GetDeviceCaps(hdc, BITSPIXEL);
1315 devMode.dmPelsWidth = resolution ? GetResolutionWidth(resolution) : GetSystemMetrics(SM_CXSCREEN);
1316 devMode.dmPelsHeight = resolution ? GetResolutionHeight(resolution) : GetSystemMetrics(SM_CYSCREEN);
1317 devMode.dmDisplayFrequency = refreshRate ? refreshRate : GetDeviceCaps(hdc, VREFRESH);
1318 if(ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
1322 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
1323 guiApp.SetDesktopPosition(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), false);
1328 static bool firstTime = true;
1330 ChangeDisplaySettings(null, 0);
1332 SetSystemPaletteUse(hdc, SYSPAL_STATIC);
1333 desktopX = desktopY = desktopW = desktopH = 0;
1335 RepositionDesktop(false);
1342 // --- Window Creation ---
1343 void * CreateRootWindow(Window window)
1346 uint16 * text = UTF8toUTF16(window.text, null);
1349 windowHandle = CreateWindowEx(0, className, text,
1351 0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),
1353 null, hInstance, null);
1354 ShowWindow(windowHandle, SW_SHOWNORMAL);
1356 else if(window.systemParent)
1357 windowHandle = CreateWindowEx(0, className, text,
1358 WS_CHILD,0,0,1,1, window.systemParent, null, hInstance, null);
1363 HWND parentWindow = null; //HWND_DESKTOP; // we get different behaviors with desktop...
1364 Window master = window.master, rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
1365 if(window.style.stayOnTop)
1366 exStyle |= WS_EX_TOPMOST;
1368 if(rootWindow && (window._isModal || window.style.interim))
1369 parentWindow = rootWindow.is3D ? rootWindow.parent.windowHandle : rootWindow.windowHandle;
1371 if(window.alphaBlend)
1372 // if(window.background.a < 255) //&& window.style & ES_REDRAW) Not needed anymore?
1373 exStyle |= WS_EX_LAYERED; // | WS_EX_TRANSPARENT;
1375 // Toolwindow will disappear if they don't have AppWindow set
1376 if(window.style.showInTaskBar || (!parentWindow && window.style.thin))
1378 exStyle |= WS_EX_APPWINDOW;
1379 parentWindow = null;
1382 if(window.style.thin)
1383 exStyle |= WS_EX_TOOLWINDOW;
1385 if(window.windowHandle)
1386 windowHandle = window.windowHandle;
1389 if(window.nativeDecorations)
1391 BorderBits borderStyle = window.borderStyle; // FIXME!
1392 style = WS_OVERLAPPED;
1393 if(borderStyle.fixed)
1394 style |= WS_CAPTION;
1396 style |= WS_SYSMENU;
1397 if(borderStyle.sizable)
1398 style |= WS_THICKFRAME;
1399 if(window.hasMinimize)
1400 style |= WS_MINIMIZEBOX;
1401 if(window.hasMaximize)
1402 style |= WS_MAXIMIZEBOX;
1404 windowHandle = CreateWindowEx(
1407 style | (window.systemParent ? WS_CHILD :
1408 (WS_POPUP | (window.style.hasMinimize ? WS_MINIMIZEBOX : 0))),
1409 0,0,1,1, parentWindow, null, hInstance, null);
1411 if(exStyle & WS_EX_LAYERED)
1412 SetLayeredWindowAttributes(windowHandle, 0, 255 /*A(window.background)*/, LWA_ALPHA);
1418 SetWindowLongPtr(windowHandle, GWLP_USERDATA, (int64)window);
1420 SetWindowLong(windowHandle, GWL_USERDATA, (DWORD)window);
1423 return windowHandle;
1426 void DestroyRootWindow(Window window)
1429 int c, lockCount = guiApp.lockMutex.lockCount;
1430 for(c = 0; c < lockCount; c++)
1431 guiApp.lockMutex.Release();
1433 oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
1435 if(oldIcon && oldIcon != (HICON)GetClassLongPtr(window.windowHandle, GCLP_HICON))
1437 if(oldIcon && oldIcon != (HICON)GetClassLong(window.windowHandle, GCL_HICON))
1439 DestroyIcon(oldIcon);
1441 ShowWindow(window.windowHandle, SW_HIDE);
1444 SetWindowLongPtr(window.windowHandle, GWLP_USERDATA, (int64)null);
1446 SetWindowLong(window.windowHandle, GWL_USERDATA, 0);
1448 DestroyWindow(window.windowHandle);
1450 for(c = 0; c < lockCount; c++)
1451 guiApp.lockMutex.Wait();
1453 window.windowHandle = null;
1456 // -- Window manipulation ---
1458 void SetRootWindowCaption(Window window, const char * name)
1460 uint16 * text = UTF8toUTF16(name, null);
1462 SetWindowText(window.windowHandle, text);
1467 void PositionRootWindow(Window window, int x, int y, int w, int h, bool move, bool resize)
1469 int flags = SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS;
1471 if(!window.systemParent && !fullScreenMode)
1477 if(!move) flags |= SWP_NOMOVE;
1478 if(!resize) flags |= SWP_NOSIZE;
1480 /*if(move && resize)
1482 flags |= SWP_NOMOVE;
1483 SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
1484 flags &=~SWP_NOMOVE;
1485 flags |= SWP_NOSIZE;
1487 if(!window.nativeDecorations || window.state != maximized || !window.visible || guiApp.modeSwitching)
1488 SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
1491 void OrderRootWindow(Window window, bool topMost)
1493 SetWindowPos(window.windowHandle, topMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0,0,0,0,
1494 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);
1497 void SetRootWindowColor(Window window)
1499 if(window.alphaBlend && window.display.pixelFormat == pixelFormat888)
1501 /*if(A(window.background) == 255)
1503 if((style & WS_EX_LAYERED) == WS_EX_LAYERED)
1504 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style &~WS_EX_LAYERED);
1508 #ifndef ECERE_NOBLENDING
1509 DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
1510 if((style & WS_EX_LAYERED) != WS_EX_LAYERED)
1511 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style | WS_EX_LAYERED);
1513 // SetLayeredWindowAttributes(window.windowHandle, 0, 255 /*Max(A(window.background),1)*/, LWA_ALPHA);
1518 void OffsetWindow(Window window, int * x, int * y)
1520 if(window.systemParent)
1522 POINT point = {*x,*y};
1523 ClientToScreen(GetParent(window.windowHandle), &point);
1529 void UpdateRootWindow(Window window)
1531 UpdateWindow(window.windowHandle);
1534 void SetRootWindowState(Window window, WindowState state, bool visible)
1543 if((window.active || window.creationActivation == activate) && !externalDisplayChange)
1544 ShowWindow(window.windowHandle, (window.nativeDecorations && state == maximized) ? SW_MAXIMIZE : SW_SHOWNORMAL);
1547 WINDOWPLACEMENT plc = { 0 };
1548 GetWindowPlacement(window.windowHandle, &plc);
1549 plc.showCmd = (window.nativeDecorations && state == maximized) ? SW_MAXIMIZE : SW_SHOWNORMAL;
1550 ShowWindow(window.windowHandle, SW_SHOWNOACTIVATE);
1551 SetWindowPlacement(window.windowHandle, &plc);
1556 ShowWindow(window.windowHandle, SW_MINIMIZE);
1562 ShowWindow(window.windowHandle, SW_HIDE);
1566 void ActivateRootWindow(Window window)
1568 if(!externalDisplayChange)
1569 SetForegroundWindow(window.windowHandle);
1572 void FlashRootWindow(Window window)
1574 FLASHWINFO flashInfo = { 0 };
1575 flashInfo.cbSize = sizeof(FLASHWINFO);
1576 flashInfo.hwnd = window.windowHandle;
1577 flashInfo.uCount = 1;
1578 flashInfo.dwFlags = FLASHW_TRAY; // FLASHW_ALL;
1580 FlashWindowEx((void *)&flashInfo);
1584 // --- Mouse-based window movement ---
1585 void StartMoving(Window window, int x, int y, bool fromKeyBoard)
1587 if(!fullScreenMode && !window.systemParent)
1588 // Commented out for Chess game because AI thread takes over the moving of main window... Still required?
1589 //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
1590 ; //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
1593 SetWindowPos(window.windowHandle, HWND_TOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
1594 mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
1595 if(!window.stayOnTop)
1596 SetWindowPos(window.windowHandle, HWND_NOTOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
1600 void StopMoving(Window window)
1602 if(!fullScreenMode && !window.systemParent)
1603 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1606 // -- Mouse manipulation ---
1608 void GetMousePosition(int *x, int *y)
1611 GetCursorPos(&point);
1616 void SetMousePosition(int x, int y)
1621 void SetMouseRange(Window window, Box box)
1623 ClipCursor((RECT *) box);
1626 void SetMouseCapture(Window window)
1629 SetCapture(window.windowHandle);
1634 // -- Mouse cursor ---
1636 void SetMouseCursor(Window window, SystemCursor cursor)
1638 if(lastCursor != cursor)
1640 lastCursor = cursor;
1641 SetCursor((cursor == (SystemCursor)-1) ? null : systemCursors[cursor]);
1647 void SetCaret(int x, int y, int size)
1652 // --- Clipboard manipulation ---
1654 void ClearClipboard()
1656 if(OpenClipboard(null))
1663 bool AllocateClipboard(ClipBoard clipBoard, uint size)
1665 bool result = false;
1666 clipBoard.text = new byte[size];
1671 bool SaveClipboard(ClipBoard clipBoard)
1673 bool result = false;
1677 uint16 * u16text = UTF8toUTF16(clipBoard.text, &wordCount);
1679 clipBoard.handle = GlobalAlloc(GHND | GMEM_DDESHARE, wordCount * 2);
1680 if(clipBoard.handle)
1682 uint16 * text = GlobalLock(clipBoard.handle);
1685 memcpy(text, u16text, wordCount * 2);
1686 GlobalUnlock(clipBoard.handle);
1687 if(OpenClipboard(null))
1690 if(SetClipboardData(CF_UNICODETEXT, clipBoard.handle))
1698 GlobalFree(clipBoard.handle);
1705 bool LoadClipboard(ClipBoard clipBoard)
1707 bool result = false;
1708 if(OpenClipboard(null))
1710 if((clipBoard.handle = GetClipboardData(CF_UNICODETEXT)))
1712 uint16 * u16text = GlobalLock(clipBoard.handle);
1715 clipBoard.text = UTF16toUTF8(u16text);
1717 GlobalUnlock(clipBoard.handle);
1725 void UnloadClipboard(ClipBoard clipBoard)
1727 delete clipBoard.text;
1730 // --- State based input ---
1732 bool AcquireInput(Window window, bool state)
1734 #ifndef ECERE_NODINPUT
1735 if(dInput || InitDirectInput())
1737 AcquireDirectInput(window.windowHandle, state);
1744 bool GetMouseState(MouseButtons * buttons, int * x, int * y)
1746 bool result = false;
1747 #ifndef ECERE_NODINPUT
1748 DIMOUSESTATE dims = {0};
1750 if(acquiredWindow && directMouse)
1752 if(directMouse->lpVtbl->GetDeviceState(directMouse, sizeof(DIMOUSESTATE), &dims ))
1754 FillBytes(&dims, 0, sizeof(dims));
1755 directMouse->lpVtbl->Acquire(directMouse);
1759 /* We don't really want this...
1762 if(GetAsyncKeyState(VK_LBUTTON))
1763 dims.rgbButtons[0] |= 0x80;
1764 if(GetAsyncKeyState(VK_RBUTTON))
1765 dims.rgbButtons[1] |= 0x80;
1766 if(GetAsyncKeyState(VK_MBUTTON))
1767 dims.rgbButtons[2] |= 0x80;
1776 Window window = (Window)GetWindowLongPtr(acquiredWindow, GWLP_USERDATA);
1778 Window window = (Window)GetWindowLong(acquiredWindow, GWL_USERDATA);
1780 ProcessKeyMessage(window, WM_MOUSEWHEEL, ((uint16)(short)dims.lZ) << 16, 0, 0);
1784 *buttons = MouseButtons {
1785 left = (dims.rgbButtons[0] & 0x80) ? true : false,
1786 right = (dims.rgbButtons[1] & 0x80) ? true : false,
1787 middle = (dims.rgbButtons[2] & 0x80) ? true : false };
1794 bool GetJoystickState(int device, Joystick joystick)
1796 bool result = false;
1797 #ifndef ECERE_NODINPUT
1798 if(joystick != null)
1800 DIJOYSTATE dijs = {0};
1801 #ifndef ECERE_NOJOYSTICK
1802 if(acquiredWindow && device < numJoysticks)
1804 if(directJoysticks[device])
1806 directJoysticks[device]->lpVtbl->Poll(directJoysticks[device]);
1807 if(directJoysticks[device]->lpVtbl->GetDeviceState(directJoysticks[device], sizeof(DIJOYSTATE), &dijs ))
1808 directJoysticks[device]->lpVtbl->Acquire(directJoysticks[device]);
1813 joystick.x = dijs.lX;
1814 joystick.y = dijs.lY;
1815 joystick.z = dijs.lZ;
1816 joystick.rx = dijs.lRx;
1817 joystick.ry = dijs.lRy;
1818 joystick.rz = dijs.lRz;
1820 ((dijs.rgbButtons[0] & 0x80) ? JOY_BUTTON1 : 0)
1821 | ((dijs.rgbButtons[1] & 0x80) ? JOY_BUTTON2 : 0)
1822 | ((dijs.rgbButtons[2] & 0x80) ? JOY_BUTTON3 : 0)
1823 | ((dijs.rgbButtons[3] & 0x80) ? JOY_BUTTON4 : 0);
1829 bool GetKeyState(Key key)
1831 bool keyState = false;
1832 if(key < 256 || key == alt || key == shift || key == control)
1836 ks = GetAsyncKeyState(VK_MENU);
1837 else if(key == control)
1838 ks = GetAsyncKeyState(VK_CONTROL);
1839 else if(key == shift)
1840 ks = GetAsyncKeyState(VK_SHIFT);
1841 else if(key2VK[key])
1842 ks = GetAsyncKeyState(key2VK[key]);
1843 keyState = (ks & 0x80000) ? true : false;
1845 else if(key == capsState)
1846 keyState = (::GetKeyState(VK_CAPITAL) & 0x00000001) != 0;
1847 else if(key == numState)
1848 keyState = (::GetKeyState(VK_NUMLOCK) & 0x00000001) != 0;
1849 else if(key == scrollState)
1850 keyState = (::GetKeyState(VK_SCROLL) & 0x00000001) != 0;
1854 bool SetIcon(Window window, BitmapResource resource)
1857 HICON oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
1859 // Dialogs Inherit master's icon if none set
1860 if(!window.style.showInTaskBar && window.hasClose)
1862 Window master = window.master;
1863 while(master && !resource)
1865 Window rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
1866 if(rootWindow && rootWindow.icon)
1867 resource = rootWindow.icon;
1869 master = master.master;
1873 // WARNING -- putting this here as it is right after CreateRootWindow
1874 // Take out Layered flag if we're not in 24 bit
1876 if(window.alphaBlend && window.display.pixelFormat != pixelFormat888)
1878 #ifndef ECERE_NOBLENDING
1879 DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
1880 style &= ~WS_EX_LAYERED;
1881 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style);
1887 if(oldIcon && oldIcon != (HICON)GetClassLongPtr(window.windowHandle, GCLP_HICON))
1889 if(oldIcon && oldIcon != (HICON)GetClassLong(window.windowHandle, GCL_HICON))
1892 DestroyIcon(oldIcon);
1898 if(bitmap.Load(resource.fileName, null, null))
1901 PixelFormat format = window.display.pixelFormat;
1902 int bits = GetDepthBits(format);
1905 bitmap.Convert(null, pixelFormat888, null);
1906 and.Allocate(null, (bitmap.width+7/8), bitmap.height, 0, pixelFormat8, false);
1908 blend = bits == 32 || bitmap.pixelFormat != pixelFormat888;
1911 byte * picture = and.picture;
1914 uint size = bitmap.height * bitmap.width;
1919 while(m < 8 && c < size)
1922 mask |= blend ? (!((ColorAlpha *)bitmap.picture)[c].a) : (((ColorAlpha *)bitmap.picture)[c].a <= 192);
1926 picture[b++] = mask;
1931 ColorAlpha color = ((ColorAlpha *)bitmap.picture)[c];
1932 if(blend ? (!color.a) : (color.a <= 192))
1934 color.color = { 0, 0, 0 };
1935 ((ColorAlpha *)bitmap.picture)[c] = color;
1940 if(bits == 15) { bits = 16; format = pixelFormat565; };
1941 bitmap.Convert(null, format, null);
1943 icon = CreateIcon(hInstance, bitmap.width, bitmap.height, 1, (byte)bits, and.picture, bitmap.picture);
1948 SendMessage(window.windowHandle, WM_SETICON, ICON_BIG, (LPARAM)icon);
1949 SendMessage(window.windowHandle, WM_SETICON, ICON_SMALL, (LPARAM)icon);
1953 void ::GetScreenArea(Window window, Box box)
1955 HMONITOR monitor = MonitorFromWindow(window.windowHandle, MONITOR_DEFAULTTONEAREST);
1956 HMONITOR taskBarMonitor = MonitorFromWindow(startBar, MONITOR_DEFAULTTONEAREST);
1959 MONITORINFO info = { 0 };
1960 info.cbSize = sizeof(MONITORINFO);
1961 GetMonitorInfo(monitor, &info);
1962 // box = { info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom };
1963 box = { info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right-1, info.rcMonitor.bottom-1 };
1965 if(taskBarMonitor == monitor)
1967 if(taskBarPlacement.rcNormalPosition.top <= box.top && taskBarPlacement.rcNormalPosition.bottom >= box.bottom)
1969 if(taskBarPlacement.rcNormalPosition.left <= box.left)
1971 if(taskBarState & ABS_AUTOHIDE)
1974 box.left = taskBarPlacement.rcNormalPosition.right;
1976 else if(taskBarState & ABS_AUTOHIDE)
1979 box.right = taskBarPlacement.rcNormalPosition.left;
1981 else if(taskBarPlacement.rcNormalPosition.left <= box.left && taskBarPlacement.rcNormalPosition.right >= box.right)
1983 if(taskBarPlacement.rcNormalPosition.top <= box.top)
1985 if(taskBarState & ABS_AUTOHIDE)
1988 box.top = taskBarPlacement.rcNormalPosition.bottom;
1990 else if(taskBarState & ABS_AUTOHIDE)
1993 box.bottom = taskBarPlacement.rcNormalPosition.top;
1997 box.left -= desktopX;
1998 box.top -= desktopY;
1999 box.right -= desktopX;
2000 box.bottom -= desktopY;