1 namespace gui::drivers;
10 #define _WIN32_WINNT 0x0500
17 #define WIN32_LEAN_AND_MEAN
18 #define Method _Method
25 #if defined(ECERE_VANILLA)
26 #define ECERE_NOJOYSTICK
29 #ifndef ECERE_NODINPUT
30 #ifndef ECERE_NOJOYSTICK
31 #define DIRECTINPUT_VERSION 0x700
34 #define DIRECTINPUT_VERSION 0x300
44 #define VK_EQUALS 0xBB
47 #define VK_PERIOD 0xBE
50 #define VK_LBRACKET 0xDB
51 #define VK_BACK_SLASH 0xDC
52 #define VK_RBRACKET 0xDD
56 #define WM_MOUSEWHEEL 0x20A
60 #define IDC_HAND (char *)0x7F89
65 #define LWA_COLORKEY 0x00000001
66 #define LWA_ALPHA 0x00000002
68 #define WS_EX_LAYERED 0x00080000
73 SetLayeredWindowAttributes(
88 #define ECERE_NODINPUT
89 #define ECERE_NOJOYSTICK
90 #define ECERE_NOBLENDING
93 static byte key2VK[256] =
95 0,VK_ESCAPE,'1','2','3','4','5','6','7','8','9','0',VK_MINUS,VK_EQUALS,VK_BACK,VK_TAB,
96 'Q','W','E','R','T','Y','U','I','O','P',VK_LBRACKET,VK_RBRACKET,VK_RETURN,VK_CONTROL,'A','S',
97 'D','F','G','H','J','K','L',VK_SEMI,VK_QUOTE,VK_TILDE,VK_SHIFT,VK_BACK_SLASH,'Z','X','C','V',
98 'B','N','M',VK_COMMA,VK_PERIOD,VK_DIVIDE,VK_SHIFT,VK_MULTIPLY,VK_LMENU,VK_SPACE,VK_CAPITAL,VK_F1,VK_F2,VK_F3,VK_F4,VK_F5,
99 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,
100 VK_NUMPAD2,VK_NUMPAD3,VK_NUMPAD0,VK_DELETE,0,0,0,0,0,0,0,0,0,0,0,0,
101 0,0,0,0,0,0,VK_HOME,VK_UP,VK_PRIOR,VK_LEFT,VK_RIGHT,VK_END,VK_DOWN,VK_NEXT,VK_INSERT,VK_DELETE,
102 0,0,0,VK_SHIFT,VK_MENU,VK_CONTROL
104 static char className[] = "ECERE Application";
105 static HINSTANCE hInstance;
107 static DEVMODE devMode;
108 static HWND acquiredWindow = null;
109 static HCURSOR systemCursors[SystemCursor];
110 static bool fullScreenMode;
111 static int desktopX = 0, desktopY = 0, desktopW = 0, desktopH = 0;
112 static DWORD hiResTimer;
113 // static HWND topWindow;
115 static HWND startBar;
117 #ifndef ECERE_NODINPUT
119 static HMODULE dInputDll = null;
120 static BOOL * (WINAPI * directInputCreate)(HINSTANCE, DWORD, IDirectInput **, void *);
121 static IDirectInput * dInput = null;
122 static IDirectInputDevice * directMouse = null;
123 #ifndef ECERE_NOJOYSTICK
124 static int numJoysticks = 0;
125 static IDirectInputDevice2 * directJoysticks[NUMJOY] = {null,null,null,null};
130 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
131 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp;
132 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
133 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
134 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;
135 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
136 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
137 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;
138 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
139 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
140 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
141 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick;
142 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown;
143 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
147 static Box lastMonitorAreas[32];
148 static Box monitorAreas[32];
151 static bool EnumerateMonitors(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
153 MONITORINFO info = { 0 };
154 info.cbSize = sizeof(MONITORINFO);
155 GetMonitorInfo(hMonitor, &info);
156 monitorAreas[monitor] = { info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom };
161 static bool externalDisplayChange;
163 static int taskBarState;
164 static WINDOWPLACEMENT taskBarPlacement;
165 static bool activateApp;
167 static SystemCursor lastCursor = (SystemCursor)-1;
169 void AeroSnapPosition(Window window, int x, int y, int w, int h)
171 int oldX = window.absPosition.x;
173 // To prevent having a window < minClientSize with Aero Snap, because we don't receive a WM_SIZING!
174 // The sensible implementation of this is in WM_SIZING
178 window.GetDecorationsSize(&ew, &eh);
186 gw = Max(gw, window.minSize.w);
187 gh = Max(gh, window.minSize.h);
188 gw = Min(gw, window.maxSize.w);
189 gh = Min(gh, window.maxSize.h);
191 if(!window.OnResizing(&gw, &gh))
193 gw = window.clientSize.w;
194 gh = window.clientSize.h;
197 gw = Max(gw, window.skinMinSize.w);
198 gh = Max(gh, window.skinMinSize.h);
203 if(w != gw || h != gh)
206 // Adjust x position if we resized from top or bottom left corner
214 guiApp.interfaceDriver.PositionRootWindow(window, x, y, w, h, move, true);
217 window.ExternalPosition(x, y, w, h);
220 class Win32Interface : Interface
222 class_property(name) = "Win32";
224 void ::RepositionDesktop(bool updateChildren)
227 static double lastTime = 0, time;
230 static Size lastScreen;
231 static Point lastScreenPos;
232 static WINDOWPLACEMENT lastPlacement;
234 static double lastAutoHideCheck = 0;
235 int newTaskBarState = taskBarState;
236 HMONITOR primaryMonitor;
239 if(time - lastTime < 0.1) return;
242 // Every sec, check for the auto hide property
243 if(time - lastAutoHideCheck > 1)
245 APPBARDATA appBarData = { 0 };
246 newTaskBarState = SHAppBarMessage(ABM_GETSTATE, &appBarData);
247 lastAutoHideCheck = time;
251 EnumDisplayMonitors(null, null, EnumerateMonitors, 0);
252 for(c = 0; c<monitor; c++)
254 if(monitorAreas[c].left != lastMonitorAreas[c].left ||
255 monitorAreas[c].top != lastMonitorAreas[c].top ||
256 monitorAreas[c].right != lastMonitorAreas[c].right ||
257 monitorAreas[c].bottom != lastMonitorAreas[c].bottom)
263 memcpy(lastMonitorAreas, monitorAreas, sizeof(monitorAreas));
265 guiApp.virtualScreen =
267 GetSystemMetrics(SM_CXVIRTUALSCREEN),
268 GetSystemMetrics(SM_CYVIRTUALSCREEN)
270 guiApp.virtualScreenPos =
272 x = GetSystemMetrics(SM_XVIRTUALSCREEN),
273 y = GetSystemMetrics(SM_YVIRTUALSCREEN)
277 HMONITOR monitor = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY);
280 MONITORINFO info = { 0 };
281 info.cbSize = sizeof(MONITORINFO);
282 primaryMonitor = monitor;
283 GetMonitorInfo(monitor, &info);
284 x = info.rcMonitor.left;
285 y = info.rcMonitor.top;
286 w = info.rcMonitor.right - info.rcWork.left;
287 h = info.rcMonitor.bottom - info.rcWork.top;
292 WINDOWPLACEMENT placement = { 0 };
293 placement.length = sizeof(WINDOWPLACEMENT);
295 if(!GetWindowPlacement(startBar, &placement))
297 startBar = FindWindowA("Shell_TrayWnd", null);
298 GetWindowPlacement(startBar, &placement);
301 HMONITOR taskBarMonitor = MonitorFromWindow(startBar, MONITOR_DEFAULTTONEAREST);
302 if(primaryMonitor == taskBarMonitor)
304 if(placement.rcNormalPosition.top <= 0 && placement.rcNormalPosition.bottom >= h - 1)
306 if(placement.rcNormalPosition.left <= 0)
308 x = (taskBarState & ABS_AUTOHIDE) ? 1 : placement.rcNormalPosition.right;
312 w = (taskBarState & ABS_AUTOHIDE) ? (w - 1) : Min(placement.rcNormalPosition.left, w);
314 else if(placement.rcNormalPosition.left <= 0 && placement.rcNormalPosition.right >= w - 1)
316 if(placement.rcNormalPosition.top <= 0)
318 y = (taskBarState & ABS_AUTOHIDE) ? 1 : placement.rcNormalPosition.bottom;
322 h = (taskBarState & ABS_AUTOHIDE) ? (h - 1) : Min(placement.rcNormalPosition.top, h);
328 placement.rcNormalPosition.left != taskBarPlacement.rcNormalPosition.left ||
329 placement.rcNormalPosition.top != taskBarPlacement.rcNormalPosition.top ||
330 placement.rcNormalPosition.right != taskBarPlacement.rcNormalPosition.right ||
331 placement.rcNormalPosition.bottom != taskBarPlacement.rcNormalPosition.bottom ||
332 newTaskBarState != taskBarState)
334 taskBarState = newTaskBarState;
335 guiApp.desktop.size.w = 0;
340 taskBarPlacement = placement;
341 guiApp.SetDesktopPosition(x, y, w, h, updateChildren);
344 lastScreen = guiApp.virtualScreen;
345 lastScreenPos = guiApp.virtualScreenPos;
349 /****************************************************************************
350 /// PRIVATE UTILITY FUNCTIONS /////////////
351 ****************************************************************************/
352 // --- Keyboard Input ---
353 bool ::ProcessKeyMessage(Window window, DWORD msg, WPARAM wParam, LPARAM lParam, unichar ch)
359 bool frenchShift = (ch < 0x10000) ? (((VkKeyScan((uint16)ch) >> 8) & 6) == 6) : false;
361 if(msg == WM_CHAR || msg == WM_DEADCHAR)
366 if(msg == WM_MOUSEWHEEL)
367 code = (((short) HIWORD(wParam)) < 0) ? wheelDown : wheelUp;
370 key = (byte)((lParam & 0xFF0000)>>16);
371 if(lParam & 0x1000000)
373 key = Interface::GetExtendedKey(key);
383 if(key != leftShift && key != rightShift && ::GetKeyState(VK_SHIFT) & 0x80000)
385 if(key != leftControl && key != rightControl && ::GetKeyState(VK_CONTROL) & 0x80000 && !frenchShift)
387 if(key != leftAlt && key != rightAlt && ::GetKeyState(VK_MENU) & 0x80000 && !frenchShift)
390 if(msg == WM_MOUSEWHEEL)
392 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code, 0);
397 byte ch = Interface::TranslateKeykey, code.shift);
398 if(::GetKeyState(VK_CAPITAL))
402 if(msg == WM_KEYUP || msg == WM_SYSKEYUP)
404 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, code, ch);
408 if(!(lParam & 0x40000000))
413 Class * keyClass = eSystem_FindClass(__ecereModule, "Key");
414 code.OnGetString(string, null, null);
415 eSystem_Logf("%s\n", string);
419 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, code, ch);
422 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code,ch);
429 // --- Window procedure ---
430 DWORD CALLBACK ::ApplicationWindow(HWND windowHandle, UINT msg, WPARAM wParam, LPARAM lParam)
432 Window window = (Window)GetWindowLong(windowHandle, GWL_USERDATA);
433 static Point lastPos;
440 case WM_QUERYNEWPALETTE:
441 case WM_PALETTECHANGED:
443 window.display.RestorePalette();
444 UpdateWindow(windowHandle);
448 if(!fullScreenMode && !guiApp.IsModeSwitching())
452 Window modalRoot = window.FindModal();
454 HWND modalWindow = modalRoot ? modalRoot.windowHandle : null;
456 FLASHWINFO flashInfo = { 0 };
457 flashInfo.cbSize = sizeof(FLASHWINFO);
458 flashInfo.hwnd = window.windowHandle;
459 flashInfo.uCount = 0;
460 flashInfo.dwFlags = FLASHW_STOP;
461 FlashWindowEx((void *)&flashInfo);
463 if(modalWindow && modalWindow != windowHandle)
464 modalRoot.ExternalActivate(true, true, window, null);
466 window.ExternalActivate(true, true, window, null);
473 foreground = GetForegroundWindow();
474 if(foreground == windowHandle && lParam)
475 foreground = (HWND)lParam;
477 GetWindowThreadProcessId(foreground, &id);
479 windowLong = GetWindowLong(foreground, GWL_WNDPROC);
480 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
481 // The != ApplicationWindow check is for not recognizing the Console window as an Ecere Window
482 // That check causes a problem with the OpenGL driver which seems to popup a window of a different class
483 if(window.displaySystem && window.displaySystem.driver == class(OpenGLDisplayDriver))
484 windowLong = (uint)ApplicationWindow;
486 if(id != GetCurrentProcessId() || windowLong != (LPARAM)ApplicationWindow)
487 window.ExternalActivate(false, true, window, null);
488 // DefWindowProc for WM_NCACTIVATE draws the decorations, make sure it's drawn in the right state
489 return (uint)DefWindowProc(windowHandle, msg, window.active, lParam);
494 for(window = guiApp.desktop.firstChild; window; window = window.next)
495 SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 0,0,0,0,
496 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW);
500 return (uint)DefWindowProc(windowHandle, msg, window ? window.active : wParam, lParam);
503 if(!guiApp.IsModeSwitching())
507 HDC hdc = GetDC(windowHandle);
510 guiApp.SetAppFocus(false);
511 ShowWindow(windowHandle, SW_MINIMIZE);
512 ChangeDisplaySettings(null,0);
513 SetSystemPaletteUse(hdc, SYSPAL_STATIC);
517 ChangeDisplaySettings(&devMode, CDS_FULLSCREEN);
518 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
520 window.display.RestorePalette();
521 ShowWindow(windowHandle, SW_SHOWNORMAL);
522 guiApp.SetAppFocus(true);
524 window.display.Resize(window.clientSize.w, window.clientSize.h);
527 ReleaseDC(windowHandle, hdc);
533 if(wParam && !guiApp.desktop.active /*&& lParam != GetCurrentThreadID()*/)
537 for(window = guiApp.desktop.firstChild; window; window = window.next)
538 SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 0,0,0,0,
539 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW);
542 guiApp.SetAppFocus(wParam);
546 guiApp.SetAppFocus(wParam);
550 if(!window.alphaBlend || window.display.pixelFormat != pixelFormat888)
555 #define ACCESS_ITEM(l, id) \
556 ((FastItem)(((id) == -1) ? null : (((byte *)((l).items)) + (id) * (l).itemSize)))
559 #define ACCESS_ITEM(l, id) \
562 BoxItem item = window.dirtyArea.count ? (BoxItem)ACCESS_ITEM(window.dirtyArea, window.dirtyArea.first) : null;
564 BeginPaint(windowHandle, &ps);
566 // Prevent flickering if we're going to update anyways
568 printf(" Paint message (%d, %d)-(%d, %d)\n",
569 item ? item.box.left : 0,
570 item ? item.box.top : 0,
571 item ? item.box.right : 0,
572 item ? item.box.bottom : 0);
574 // Causes redraw bug...
575 if(!window.manageDisplay || !item ||
578 item.box.right < window.size.w - 1 ||
579 item.box.bottom < window.size.h - 1)
581 Box box { ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-1, ps.rcPaint.bottom-1 };
582 window.UpdateDirty(box);
584 // TODO: Fix precompiler with
585 // window.UpdateDirty((Box *)&ps.rcPaint);
586 EndPaint(windowHandle, &ps);
590 case WM_DISPLAYCHANGE:
592 static int lastBits = 0;
593 static int lastRes = 0;
594 if(lastBits != wParam || lastRes != lParam)
599 externalDisplayChange = true;
600 if(guiApp.desktop.DisplayModeChanged())
603 if(!window.style.hidden)
604 ShowWindow(windowHandle, SW_SHOWNOACTIVATE /*SW_SHOWNORMAL*/);
605 window.FigureCaption(caption);
606 SetRootWindowCaption(window, caption);
608 externalDisplayChange = false;
623 if(msg != WM_CHAR && window.composing)
628 case WM_SYSKEYDOWN: min = max = WM_SYSCHAR; break;
629 case WM_KEYDOWN: min = max = WM_CHAR; break;
630 case WM_SYSKEYUP: min = WM_SYSCHAR; max = WM_SYSDEADCHAR; break;
631 case WM_KEYUP: min = WM_CHAR; max = WM_DEADCHAR; break;
634 // This is very annoying.
635 // PeekMessage somehow invokes this function directly... don't know why.
636 // Only crashes when running through debug mode in visual studio
638 if(msg == WM_CHAR || msg == WM_DEADCHAR || PeekMessage(&charMsg, windowHandle, min, max, PM_REMOVE))
640 ch = (msg == WM_CHAR || msg == WM_DEADCHAR) ? wParam : (unichar)charMsg.wParam;
641 if(msg == WM_SYSKEYDOWN && ch == 13)
643 ShowWindow(window.windowHandle, SW_SHOWNORMAL);
644 // window.ExternalActivate(true, true, window, null);
646 if(msg == WM_SYSKEYUP || msg == WM_KEYUP)
648 if(!ProcessKeyMessage(window, WM_KEYDOWN, 0x40000000, 0, ch))
654 ProcessKeyMessage(window, msg, wParam, lParam, ch);
655 if(window.composing && msg == WM_CHAR)
657 COMPOSITIONFORM form;
658 Window caretOwner = guiApp.caretOwner;
661 HIMC ctx = ImmGetContext(windowHandle);
662 form.dwStyle = CFS_POINT;
663 form.ptCurrentPos.x = caretOwner.caretPos.x - caretOwner.scroll.x + caretOwner.absPosition.x - window.absPosition.x + 4;
664 form.ptCurrentPos.y = caretOwner.caretPos.y - caretOwner.scroll.x + caretOwner.absPosition.y - window.absPosition.y + 2;
665 window.composing = true;
666 ImmSetCompositionWindow(ctx, &form);
667 ImmReleaseContext(windowHandle, ctx);
670 if(msg != WM_MOUSEWHEEL)
674 case WM_IME_STARTCOMPOSITION:
676 COMPOSITIONFORM form;
677 Window caretOwner = guiApp.caretOwner;
680 HIMC ctx = ImmGetContext(windowHandle);
681 form.dwStyle = CFS_POINT;
682 form.ptCurrentPos.x = caretOwner.caretPos.x - caretOwner.scroll.x + caretOwner.absPosition.x - window.absPosition.x + 4;
683 form.ptCurrentPos.y = caretOwner.caretPos.y - caretOwner.scroll.y + caretOwner.absPosition.y - window.absPosition.y + 2;
685 form.rcArea.left = window.caretPos.x;
686 form.rcArea.top = 250;
687 form.rcArea.right = 500;
688 form.rcArea.bottom = 300;
690 window.composing = true;
691 DefWindowProc(windowHandle, msg, wParam, lParam);
692 ImmSetCompositionWindow(ctx, &form);
693 ImmSetStatusWindowPos(ctx, &form.ptCurrentPos);
695 FontResource res = caretOwner.font;
696 LOGFONT font = { 0 };
698 int pixels = GetDeviceCaps(hdc, LOGPIXELSY);
700 font.lfHeight = -(int)((float)res.size * pixels / 72 + 0.5);
701 font.lfWeight = res.flags.bold ? FW_BOLD : FW_NORMAL;
702 font.lfItalic = res.flags.italic ? TRUE : FALSE,
703 font.lfUnderline = res.flags.underline ? TRUE : FALSE;
704 font.lfCharSet = DEFAULT_CHARSET;
705 font.lfOutPrecision = OUT_DEFAULT_PRECIS;
706 font.lfClipPrecision = CLIP_DEFAULT_PRECIS;
707 font.lfQuality = DEFAULT_QUALITY;
708 font.lfPitchAndFamily = (byte)DEFAULT_PITCH|FF_DONTCARE; // TODO: Fix compiler 0 | 0 to produce byte, not int
709 UTF8toUTF16Buffer(res.faceName, font.lfFaceName, LF_FACESIZE);
711 ImmSetCompositionFont(ctx, &font);
712 ImmReleaseContext(windowHandle, ctx);
718 case WM_IME_ENDCOMPOSITION:
719 window.composing = false;
720 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
721 /*case WM_IME_COMPOSITION:
722 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
724 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
726 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
728 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
730 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
732 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
733 case WM_IME_SETCONTEXT:
734 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
736 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
738 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
739 case WM_IME_COMPOSITIONFULL:
740 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
743 if(window.nativeDecorations)
745 uint result = (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
746 // Reset the cursor on native decorations
747 if(result != HTCLIENT && lastCursor != arrow)
749 SetCursor(systemCursors[arrow]);
763 case WM_LBUTTONDBLCLK:
765 case WM_RBUTTONDBLCLK:
767 case WM_MBUTTONDBLCLK:
769 x = window.absPosition.x;
770 y = window.absPosition.y;
771 /*case WM_NCLBUTTONUP:
774 case WM_NCLBUTTONDOWN:
775 case WM_NCLBUTTONDBLCLK:
776 case WM_NCRBUTTONDOWN:
777 case WM_NCRBUTTONDBLCLK:
778 case WM_NCMBUTTONDOWN:
779 case WM_NCMBUTTONDBLCLK:
780 case WM_NCMOUSEMOVE:*/
783 bool consequential = false;
785 x += (short)LOWORD(lParam);
786 y += (short)HIWORD(lParam);
788 if(window.nativeDecorations)
790 x += window.clientStart.x;
791 y += window.clientStart.y - (window.hasMenuBar ? skinMenuHeight : 0);
794 if(::GetKeyState(VK_SHIFT) & 0x80000) code.shift = true;
795 if(::GetKeyState(VK_CONTROL) & 0x80000) code.ctrl = true;
796 if(::GetKeyState(VK_MENU) & 0x80000) code.alt = true;
797 if(wParam & MK_LBUTTON) code.left = true;
798 if(wParam & MK_MBUTTON) code.middle = true;
799 if(wParam & MK_RBUTTON) code.right = true;
801 if(msg == WM_MOUSEMOVE)
803 if(lastPos.x == x && lastPos.y == y)
804 consequential = true;
812 //case WM_NCMOUSEMOVE:
814 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x,y,&code, consequential, false);
816 //case WM_NCLBUTTONDBLCLK:
817 case WM_LBUTTONDBLCLK:
818 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick, x,y,&code, false, true))
820 //case WM_NCLBUTTONDOWN:
822 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown,x,y,&code, false,
823 (msg == WM_LBUTTONDBLCLK) ? false: true);
825 //case WM_NCLBUTTONUP:
826 case WM_LBUTTONUP: window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x,y,&code, false, false);break;
827 //case WM_NCMBUTTONDBLCLK:
828 case WM_MBUTTONDBLCLK:
829 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick, x,y,&code, false, false))
831 //case WM_NCMBUTTONDOWN:
833 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown, x,y,&code, false,
834 (msg == WM_LBUTTONDBLCLK) ? false: true);
836 //case WM_NCMBUTTONUP:
838 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp, x,y,&code, false, false);
840 //case WM_NCRBUTTONDBLCLK:
841 case WM_RBUTTONDBLCLK:
842 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick, x,y,&code, false, true))
844 //case WM_NCRBUTTONDOWN:
846 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown, x,y,&code, false,
847 (msg == WM_LBUTTONDBLCLK) ? false: true);
849 //case WM_NCRBUTTONUP:
851 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp, x,y,&code, false, false);
859 if(window.nativeDecorations)
861 if(DefWindowProc(windowHandle, msg, wParam, lParam))
864 // SetCursor(systemCursors[0]);
865 SetCursor((lastCursor == (SystemCursor)-1) ? null : systemCursors[lastCursor]);
868 case WM_EXITMENULOOP:
869 case WM_EXITSIZEMOVE:
870 // We had some DirectInput stuff in here
872 case WM_ENTERMENULOOP:
873 case WM_ENTERSIZEMOVE:
874 // We had some DirectInput stuff in here
884 WINDOWPLACEMENT placement = { 0 };
886 placement.length = sizeof(WINDOWPLACEMENT);
887 GetWindowRect(windowHandle, &rcWindow);
888 GetWindowPlacement(windowHandle, &placement);
890 x = rcWindow.left - desktopX;
891 y = rcWindow.top - desktopY;
892 w = rcWindow.right - rcWindow.left;
893 h = rcWindow.bottom - rcWindow.top;
895 AeroSnapPosition(window, x, y, w, h);
902 RECT * rect = (RECT *)lParam;
906 window.GetDecorationsSize(&ew, &eh);
908 w = rect->right - rect->left;
909 h = rect->bottom - rect->top;
917 w = Max(w, window.minSize.w);
918 h = Max(h, window.minSize.h);
919 w = Min(w, window.maxSize.w);
920 h = Min(h, window.maxSize.h);
922 if(!window.OnResizing(&w, &h))
924 w = window.clientSize.w;
925 h = window.clientSize.h;
928 w = Max(w, window.skinMinSize.w);
929 h = Max(h, window.skinMinSize.h);
934 if(wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT)
935 rect->left = rect->right - w;
937 rect->right = rect->left + w;
939 if(wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOP || wParam == WMSZ_TOPRIGHT)
940 rect->top = rect->bottom - h;
942 rect->bottom = rect->top + h;
948 if(window.nativeDecorations)
952 GetWindowRect(windowHandle, &rcWindow);
954 if(wParam == SIZE_MAXIMIZED && window.state != maximized)
955 window.state = maximized;
956 else if(wParam == SIZE_MINIMIZED && window.state != minimized)
957 window.state = minimized;
958 else if(wParam == SIZE_RESTORED && window.state != normal && window.visible)
959 window.state = normal;
961 x = rcWindow.left - desktopX;
962 y = rcWindow.top - desktopY;
963 w = rcWindow.right - rcWindow.left;
964 h = rcWindow.bottom - rcWindow.top;
966 AeroSnapPosition(window, x, y, w, h);
967 if(!guiApp.modeSwitching)
968 window.UpdateVisual(null);
971 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
975 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
979 return (uint)DefMDIChildProc(windowHandle, msg, wParam, lParam);
980 // return DefWindowProc(windowHandle, msg, wParam, lParam);
984 // --- DirectInput ---
986 #ifndef ECERE_NODINPUT
988 #ifndef ECERE_NOJOYSTICK
989 bool CALLBACK ::JoystickCallback( const DIDEVICEINSTANCE* pdidInstance, void * context )
991 if(!dInput->lpVtbl->CreateDevice(dInput, &GUID_Joystick,
992 (IDirectInputDevice **)&directJoysticks[numJoysticks], null ))
994 return DIENUM_CONTINUE;
997 bool CALLBACK ::JoystickAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, void * context )
1000 IDirectInputDevice2 * curJoy = (IDirectInputDevice2 *)context;
1002 diprg.diph.dwSize = sizeof(DIPROPRANGE);
1003 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1004 diprg.diph.dwHow = DIPH_BYOFFSET;
1005 diprg.diph.dwObj = pdidoi->dwOfs;
1008 if(curJoy->lpVtbl->SetProperty(curJoy, DIPROP_RANGE, &diprg.diph))
1010 return DIENUM_CONTINUE;
1014 void ::TerminateDirectInput()
1019 directMouse->lpVtbl->Unacquire(directMouse);
1020 directMouse->lpVtbl->Release(directMouse);
1023 #ifndef ECERE_NOJOYSTICK
1024 for(j=0; j<numJoysticks; j++)
1026 if (directJoysticks[j])
1028 directJoysticks[j]->lpVtbl->Unacquire(directJoysticks[j]);
1029 directJoysticks[j]->lpVtbl->Release(directJoysticks[j]);
1030 directJoysticks[j] = null;
1037 dInput->lpVtbl->Release(dInput);
1041 directInputCreate = null;
1045 FreeLibrary(dInputDll);
1050 bool ::InitDirectInput()
1052 bool result = false;
1054 dInputDll = LoadLibraryA("dinput.dll");
1057 if((directInputCreate = (void *)GetProcAddress(dInputDll, "DirectInputCreateA")))
1059 if(!directInputCreate( hInstance, DIRECTINPUT_VERSION, &dInput, null ))
1064 if(!dInput->lpVtbl->CreateDevice(dInput, &GUID_SysMouse, &directMouse, null ))
1065 directMouse->lpVtbl->SetDataFormat(directMouse, &c_dfDIMouse );
1067 #ifndef ECERE_NOJOYSTICK
1069 dInput->lpVtbl->EnumDevices(dInput, DIDEVTYPE_JOYSTICK, JoystickCallback, null, DIEDFL_ATTACHEDONLY );
1070 for(j=0; j<NUMJOY; j++)
1071 if(directJoysticks[j])
1072 if(!directJoysticks[j]->lpVtbl->SetDataFormat(directJoysticks[j], &c_dfDIJoystick ))
1073 directJoysticks[j]->lpVtbl->EnumObjects(directJoysticks[j], JoystickAxesCallback, directJoysticks[j], DIDFT_AXIS );
1082 void ::AcquireDirectInput(HWND windowHandle, bool state)
1086 if((state && !acquiredWindow) || (!state && acquiredWindow == windowHandle))
1093 directMouse->lpVtbl->SetCooperativeLevel(directMouse, /*fullScreenMode ? */windowHandle /*: HWND_DESKTOP*/, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
1094 directMouse->lpVtbl->Acquire(directMouse);
1097 directMouse->lpVtbl->Unacquire(directMouse);
1099 #ifndef ECERE_NOJOYSTICK
1100 for(j = 0; j<NUMJOY; j++)
1101 if(directJoysticks[j])
1105 directJoysticks[j]->lpVtbl->SetCooperativeLevel(directJoysticks[j], /*fullScreenMode ? */windowHandle /*: HWND_DESKTOP*/, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
1106 directJoysticks[j]->lpVtbl->Acquire(directJoysticks[j]);
1109 directJoysticks[j]->lpVtbl->Unacquire(directJoysticks[j]);
1112 acquiredWindow = state ? windowHandle : null;
1117 /****************************************************************************
1118 /// INTEGRATION FUNCTIONALITY /////////////
1119 ****************************************************************************/
1120 bool eisWIN32ProcessKey(Window window, DWORD msg, DWORD wParam, DWORD lParam, byte ch)
1122 return ProcessKeyMessage(window, msg, wParam, lParam, ch);
1125 HWND eisWIN32GetWindowHandle(Window window)
1127 return window.windowHandle ? window.windowHandle : window.rootWindow.windowHandle;
1130 /****************************************************************************
1131 /// DRIVER IMPLEMENTATION /////////////
1132 ****************************************************************************/
1134 void CALLBACK ::TimerProc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
1136 guiApp.SignalEvent();
1139 // --- User Interface System ---
1144 CS_DBLCLKS, ApplicationWindow, 0L, 0L, 0,
1145 LoadIcon(null, IDI_APPLICATION),
1151 wcl.hInstance = hInstance = GetModuleHandle(null);
1152 RegisterClass(&wcl);
1154 // Move that in reposition desktop
1155 startBar = FindWindowA("Shell_TrayWnd", null);
1157 systemCursors[arrow] = LoadCursor(null, IDC_ARROW);
1158 systemCursors[iBeam] = LoadCursor(null, IDC_IBEAM);
1159 systemCursors[cross] = LoadCursor(null, IDC_CROSS);
1160 systemCursors[moving] = LoadCursor(null, IDC_SIZEALL);
1161 systemCursors[sizeNESW] = LoadCursor(null, IDC_SIZENESW);
1162 systemCursors[sizeNS ] = LoadCursor(null, IDC_SIZENS);
1163 systemCursors[sizeNWSE] = LoadCursor(null, IDC_SIZENWSE);
1164 systemCursors[sizeWE ] = LoadCursor(null, IDC_SIZEWE);
1165 systemCursors[hand ] = LoadCursor(null, IDC_HAND);
1167 SetTimer(null, 0, (DWORD)(1000.0 / 18.2), null);
1168 //SetTimer(null, 0, 1, null);
1172 hiResTimer = timeSetEvent(
1175 TimerProc,0,TIME_PERIODIC);
1178 hiResTimer = timeSetEvent(
1181 TimerProc,0,TIME_PERIODIC);
1185 topWindow = CreateWindowEx(0, className, "",WS_POPUP,0,0,1,1,HWND_DESKTOP,
1186 null, hInstance, null);
1193 if(hiResTimer) timeKillEvent(hiResTimer);
1194 #ifndef ECERE_NODINPUT
1195 TerminateDirectInput();
1199 void SetTimerResolution(uint hertz)
1201 if(hiResTimer) timeKillEvent(hiResTimer);
1203 hiResTimer = timeSetEvent(1000 / hertz, 1000 / hertz, TimerProc, 0, TIME_PERIODIC);
1206 bool ProcessInput(bool processAll)
1210 RepositionDesktop(true);
1211 if(PeekMessage(&msg,0,0,0,PM_NOREMOVE))
1213 while(PeekMessage(&msg,0,0,0,PM_REMOVE))
1215 TranslateMessage(&msg);
1216 DispatchMessage(&msg);
1217 // printf("%d\n", msg.message);
1218 if(!processAll || msg.message == WM_TIMER) break;
1227 MsgWaitForMultipleObjects(1, (void **)guiApp.semaphore, FALSE, (uint)(1000 / 18.2) /*INFINITE*/, QS_ALLINPUT);
1230 void Lock(Window window)
1235 void Unlock(Window window)
1240 char ** GraphicsDrivers(int * numDrivers)
1242 static char *graphicsDrivers[] = { "GDI", "DirectDraw", "OpenGL", "Direct3D", "Direct3D8", "Direct3D9" };
1243 *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
1244 return (char **)graphicsDrivers;
1247 void GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate)
1249 *fullScreen = fullScreenMode;
1253 for(c = 0; c<Resolution::enumSize; c++)
1254 if(GetResolutionWidth(c) == devMode.dmPelsWidth && GetResolutionHeight(c) == devMode.dmPelsHeight)
1259 switch(devMode.dmBitsPerPel)
1261 case 8: *colorDepth = pixelFormat8; break;
1262 case 16: *colorDepth = pixelFormat555; break;
1263 default: *colorDepth = pixelFormat888; break;
1265 * refreshRate = devMode.dmDisplayFrequency;
1269 void EnsureFullScreen(bool *fullScreen)
1274 bool ScreenMode(bool fullScreen, Resolution resolution, PixelFormat colorDepth, int refreshRate, bool * textMode)
1279 fullScreenMode = fullScreen;
1283 FillBytes(&devMode, 0, sizeof(DEVMODE));
1284 devMode.dmSize = (uint16)sizeof(devMode);
1285 devMode.dmFields |=DM_BITSPERPEL;
1286 devMode.dmFields |=DM_PELSWIDTH|DM_PELSHEIGHT;
1287 devMode.dmFields |= DM_DISPLAYFREQUENCY;
1288 devMode.dmBitsPerPel = colorDepth ? GetDepthBits(colorDepth) : GetDeviceCaps(hdc, BITSPIXEL);
1289 devMode.dmPelsWidth = resolution ? GetResolutionWidth(resolution) : GetSystemMetrics(SM_CXSCREEN);
1290 devMode.dmPelsHeight = resolution ? GetResolutionHeight(resolution) : GetSystemMetrics(SM_CYSCREEN);
1291 devMode.dmDisplayFrequency = refreshRate ? refreshRate : GetDeviceCaps(hdc, VREFRESH);
1292 if(ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
1296 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
1297 guiApp.SetDesktopPosition(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), false);
1302 static bool firstTime = true;
1304 ChangeDisplaySettings(null, 0);
1306 SetSystemPaletteUse(hdc, SYSPAL_STATIC);
1307 desktopX = desktopY = desktopW = desktopH = 0;
1309 RepositionDesktop(false);
1316 // --- Window Creation ---
1317 void * CreateRootWindow(Window window)
1320 uint16 * text = UTF8toUTF16(window.text, null);
1323 windowHandle = CreateWindowEx(0, className, text,
1325 0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),
1327 null, hInstance, null);
1328 ShowWindow(windowHandle, SW_SHOWNORMAL);
1330 else if(window.systemParent)
1331 windowHandle = CreateWindowEx(0, className, text,
1332 WS_CHILD,0,0,1,1, window.systemParent, null, hInstance, null);
1337 HWND parentWindow = null; //HWND_DESKTOP; // we get different behaviors with desktop...
1338 if(window.style.stayOnTop)
1339 exStyle |= WS_EX_TOPMOST;
1341 // exStyle |= WS_EX_TOOLWINDOW;
1343 if(window.master.rootWindow && window.master.rootWindow != guiApp.desktop && (window.style.modal || window.style.interim))
1345 Window master = window.master;
1346 Window rootWindow = window.master.rootWindow;
1348 parentWindow = rootWindow.is3D ? rootWindow.parent.windowHandle : rootWindow.windowHandle;
1350 // parentWindow = window.master.rootWindow.is3D ? window.master.rootWindow.parent.windowHandle : window.master.rootWindow.windowHandle;
1353 if(window.alphaBlend)
1354 // if(window.background.a < 255) //&& window.style & ES_REDRAW) Not needed anymore?
1355 exStyle |= WS_EX_LAYERED; // | WS_EX_TRANSPARENT;
1357 if(window.style.showInTaskBar)
1359 exStyle |= WS_EX_APPWINDOW;
1360 parentWindow = null;
1361 //style |= WS_SYSMENU;
1363 else if(window.master.rootWindow && window.master.rootWindow != guiApp.desktop)
1365 exStyle |= WS_EX_TOOLWINDOW;
1366 //exStyle |= WS_EX_APPWINDOW;
1367 //style |= WS_SYSMENU;
1371 // exStyle |= WS_EX_APPWINDOW;
1372 //style |= WS_SYSMENU;
1374 /*else if(parentWindow)
1375 exStyle |= WS_EX_TOOLWINDOW;*/
1376 /*if(window.interim)
1377 parentWindow = window.master.rootWindow.windowHandle;*/
1379 if(window.windowHandle)
1380 windowHandle = window.windowHandle;
1383 if(window.nativeDecorations)
1385 BorderBits borderStyle = window.borderStyle; // FIXME!
1386 style = WS_OVERLAPPED;
1387 if(borderStyle.fixed)
1388 style |= WS_CAPTION;
1390 style |= WS_SYSMENU;
1391 if(borderStyle.sizable)
1392 style |= WS_THICKFRAME;
1393 if(window.hasMinimize)
1394 style |= WS_MINIMIZEBOX;
1395 if(window.hasMaximize)
1396 style |= WS_MAXIMIZEBOX;
1398 windowHandle = CreateWindowEx(
1401 style | (window.systemParent ? WS_CHILD :
1402 (WS_POPUP | (window.style.hasMinimize ? WS_MINIMIZEBOX : 0))),
1403 0,0,1,1, parentWindow, null, hInstance, null);
1406 if(exStyle & WS_EX_LAYERED)
1407 SetLayeredWindowAttributes(windowHandle, 0, 255 /*A(window.background)*/, LWA_ALPHA);
1412 SetWindowLong(windowHandle, GWL_USERDATA, (DWORD)window);
1414 return windowHandle;
1417 void DestroyRootWindow(Window window)
1419 HICON oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
1420 if(oldIcon && oldIcon != (HICON)GetClassLong(window.windowHandle, GCL_HICON))
1422 DestroyIcon(oldIcon);
1425 // TO FIX LOCK UP PROBLEMS... WOULD NEED TO UNLOCK ALL RECURSIONS ((GuiApplication)__thisModule.application).Unlock();
1426 ShowWindow(window.windowHandle, SW_HIDE);
1427 // TO FIX LOCK UP PROBLEMS... WOULD NEED TO LOCK ALL RECURSIONS((GuiApplication)__thisModule.application).Lock();
1429 SetWindowLong(window.windowHandle, GWL_USERDATA, 0);
1430 DestroyWindow(window.windowHandle);
1431 window.windowHandle = null;
1434 // -- Window manipulation ---
1436 void SetRootWindowCaption(Window window, char * name)
1438 uint16 * text = UTF8toUTF16(name, null);
1439 SetWindowText(window.windowHandle, text);
1443 void PositionRootWindow(Window window, int x, int y, int w, int h, bool move, bool resize)
1445 int flags = SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS;
1447 if(!window.systemParent && !fullScreenMode)
1453 if(!move) flags |= SWP_NOMOVE;
1454 if(!resize) flags |= SWP_NOSIZE;
1456 /*if(move && resize)
1458 flags |= SWP_NOMOVE;
1459 SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
1460 flags &=~SWP_NOMOVE;
1461 flags |= SWP_NOSIZE;
1463 if(!window.nativeDecorations || window.state != maximized || !window.visible || guiApp.modeSwitching)
1464 SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
1467 void OrderRootWindow(Window window, bool topMost)
1469 SetWindowPos(window.windowHandle, topMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0,0,0,0,
1470 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);
1473 void SetRootWindowColor(Window window)
1475 DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
1476 if(window.alphaBlend && window.display.pixelFormat == pixelFormat888)
1478 /*if(A(window.background) == 255)
1480 if((style & WS_EX_LAYERED) == WS_EX_LAYERED)
1481 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style &~WS_EX_LAYERED);
1485 #ifndef ECERE_NOBLENDING
1486 if((style & WS_EX_LAYERED) != WS_EX_LAYERED)
1487 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style | WS_EX_LAYERED);
1489 // SetLayeredWindowAttributes(window.windowHandle, 0, 255 /*Max(A(window.background),1)*/, LWA_ALPHA);
1494 void OffsetWindow(Window window, int * x, int * y)
1496 if(window.systemParent)
1498 POINT point = {*x,*y};
1499 ClientToScreen(GetParent(window.windowHandle), &point);
1505 void UpdateRootWindow(Window window)
1507 UpdateWindow(window.windowHandle);
1510 void SetRootWindowState(Window window, WindowState state, bool visible)
1518 ShowWindow(window.windowHandle, (window.creationActivation == activate && !externalDisplayChange) ?
1519 ((window.nativeDecorations && state == maximized) ? SW_MAXIMIZE : SW_SHOWNORMAL) : SW_SHOWNOACTIVATE);
1522 ShowWindow(window.windowHandle, SW_MINIMIZE);
1528 ShowWindow(window.windowHandle, SW_HIDE);
1532 void ActivateRootWindow(Window window)
1534 if(!externalDisplayChange)
1535 SetForegroundWindow(window.windowHandle);
1538 void FlashRootWindow(Window window)
1540 FLASHWINFO flashInfo = { 0 };
1541 flashInfo.cbSize = sizeof(FLASHWINFO);
1542 flashInfo.hwnd = window.windowHandle;
1543 flashInfo.uCount = 1;
1544 flashInfo.dwFlags = FLASHW_TRAY; // FLASHW_ALL;
1545 FlashWindowEx((void *)&flashInfo);
1548 // --- Mouse-based window movement ---
1549 void StartMoving(Window window, int x, int y, bool fromKeyBoard)
1551 if(!fullScreenMode && !window.systemParent)
1552 // Commented out for Chess game because AI thread takes over the moving of main window... Still required?
1553 //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
1554 ; //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
1557 SetWindowPos(window.windowHandle, HWND_TOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
1558 mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
1559 SetWindowPos(window.windowHandle, HWND_NOTOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
1563 void StopMoving(Window window)
1565 if(!fullScreenMode && !window.systemParent)
1566 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1569 // -- Mouse manipulation ---
1571 void GetMousePosition(int *x, int *y)
1574 GetCursorPos(&point);
1579 void SetMousePosition(int x, int y)
1584 void SetMouseRange(Window window, Box box)
1586 ClipCursor((RECT *) box);
1589 void SetMouseCapture(Window window)
1592 SetCapture(window.windowHandle);
1597 // -- Mouse cursor ---
1599 void SetMouseCursor(SystemCursor cursor)
1601 if(lastCursor != cursor)
1603 lastCursor = cursor;
1604 SetCursor((cursor == (SystemCursor)-1) ? null : systemCursors[cursor]);
1610 void SetCaret(int x, int y, int size)
1615 // --- Clipboard manipulation ---
1617 void ClearClipboard()
1619 if(OpenClipboard(null))
1626 bool AllocateClipboard(ClipBoard clipBoard, uint size)
1628 bool result = false;
1629 clipBoard.text = new byte[size];
1634 bool SaveClipboard(ClipBoard clipBoard)
1636 bool result = false;
1640 uint16 * u16text = UTF8toUTF16(clipBoard.text, &wordCount);
1642 clipBoard.handle = GlobalAlloc(GHND | GMEM_DDESHARE, wordCount * 2);
1643 if(clipBoard.handle)
1645 uint16 * text = GlobalLock(clipBoard.handle);
1648 memcpy(text, u16text, wordCount * 2);
1649 GlobalUnlock(clipBoard.handle);
1650 if(OpenClipboard(null))
1653 if(SetClipboardData(CF_UNICODETEXT, clipBoard.handle))
1661 GlobalFree(clipBoard.handle);
1668 bool LoadClipboard(ClipBoard clipBoard)
1670 bool result = false;
1671 if(OpenClipboard(null))
1673 if((clipBoard.handle = GetClipboardData(CF_UNICODETEXT)))
1675 uint16 * u16text = GlobalLock(clipBoard.handle);
1678 clipBoard.text = UTF16toUTF8(u16text);
1680 GlobalUnlock(clipBoard.handle);
1688 void UnloadClipboard(ClipBoard clipBoard)
1690 delete clipBoard.text;
1693 // --- State based input ---
1695 bool AcquireInput(Window window, bool state)
1697 #ifndef ECERE_NODINPUT
1698 if(dInput || InitDirectInput())
1700 AcquireDirectInput(window.windowHandle, state);
1707 bool GetMouseState(MouseButtons * buttons, int * x, int * y)
1709 bool result = false;
1710 #ifndef ECERE_NODINPUT
1711 DIMOUSESTATE dims = {0};
1713 if(acquiredWindow && directMouse)
1715 if(directMouse->lpVtbl->GetDeviceState(directMouse, sizeof(DIMOUSESTATE), &dims ))
1717 FillBytes(&dims, 0, sizeof(dims));
1718 directMouse->lpVtbl->Acquire(directMouse);
1722 /* We don't really want this...
1725 if(GetAsyncKeyState(VK_LBUTTON))
1726 dims.rgbButtons[0] |= 0x80;
1727 if(GetAsyncKeyState(VK_RBUTTON))
1728 dims.rgbButtons[1] |= 0x80;
1729 if(GetAsyncKeyState(VK_MBUTTON))
1730 dims.rgbButtons[2] |= 0x80;
1738 *buttons = MouseButtons {
1739 left = (dims.rgbButtons[0] & 0x80) ? true : false,
1740 right = (dims.rgbButtons[1] & 0x80) ? true : false,
1741 middle = (dims.rgbButtons[2] & 0x80) ? true : false };
1748 bool GetJoystickState(int device, Joystick joystick)
1750 bool result = false;
1751 #ifndef ECERE_NODINPUT
1752 if(joystick != null)
1754 DIJOYSTATE dijs = {0};
1755 #ifndef ECERE_NOJOYSTICK
1756 if(acquiredWindow && device < numJoysticks)
1758 if(directJoysticks[device])
1760 directJoysticks[device]->lpVtbl->Poll(directJoysticks[device]);
1761 if(directJoysticks[device]->lpVtbl->GetDeviceState(directJoysticks[device], sizeof(DIJOYSTATE), &dijs ))
1762 directJoysticks[device]->lpVtbl->Acquire(directJoysticks[device]);
1767 joystick.x = dijs.lX;
1768 joystick.y = dijs.lY;
1769 joystick.z = dijs.lZ;
1770 joystick.rx = dijs.lRx;
1771 joystick.ry = dijs.lRy;
1772 joystick.rz = dijs.lRz;
1774 ((dijs.rgbButtons[0] & 0x80) ? JOY_BUTTON1 : 0)
1775 | ((dijs.rgbButtons[1] & 0x80) ? JOY_BUTTON2 : 0)
1776 | ((dijs.rgbButtons[2] & 0x80) ? JOY_BUTTON3 : 0)
1777 | ((dijs.rgbButtons[3] & 0x80) ? JOY_BUTTON4 : 0);
1783 bool GetKeyState(Key key)
1785 bool keyState = false;
1789 keyState = GetAsyncKeyState(key2VK[key]);
1790 keyState = (keyState & 0x80000) ? true : false;
1792 else if(key == capsState)
1793 keyState = ::GetKeyState(VK_CAPITAL) & 0x00000001;
1794 else if(key == numState)
1795 keyState = ::GetKeyState(VK_NUMLOCK) & 0x00000001;
1796 else if(key == scrollState)
1797 keyState = ::GetKeyState(VK_SCROLL) & 0x00000001;
1801 bool SetIcon(Window window, BitmapResource resource)
1804 HICON oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
1806 // WARNING -- putting this here as it is right after CreateRootWindow
1807 // Take out Layered flag if we're not in 24 bit
1809 if(window.alphaBlend && window.display.pixelFormat != pixelFormat888)
1811 #ifndef ECERE_NOBLENDING
1812 DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
1813 style &= ~WS_EX_LAYERED;
1814 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style);
1819 if(oldIcon && oldIcon != (HICON)GetClassLong(window.windowHandle, GCL_HICON))
1821 DestroyIcon(oldIcon);
1827 if(bitmap.Load(resource.fileName, null, null))
1830 PixelFormat format = window.display.pixelFormat;
1831 int bits = GetDepthBits(format);
1834 bitmap.Convert(null, pixelFormat888, null);
1835 and.Allocate(null, (bitmap.width+7/8), bitmap.height, 0, pixelFormat8, false);
1837 blend = bits == 32 || bitmap.pixelFormat != pixelFormat888;
1840 byte * picture = and.picture;
1843 uint size = bitmap.height * bitmap.width;
1848 while(m < 8 && c < size)
1851 mask |= blend ? (!((ColorAlpha *)bitmap.picture)[c].a) : (((ColorAlpha *)bitmap.picture)[c].a <= 192);
1855 picture[b++] = mask;
1860 ColorAlpha color = ((ColorAlpha *)bitmap.picture)[c];
1861 if(blend ? (!color.a) : (color.a <= 192))
1863 color.color = { 0, 0, 0 };
1864 ((ColorAlpha *)bitmap.picture)[c] = color;
1869 if(bits == 15) { bits = 16; format = pixelFormat565; };
1870 bitmap.Convert(null, format, null);
1872 icon = CreateIcon(hInstance, bitmap.width, bitmap.height, 1, (byte)bits, and.picture, bitmap.picture);
1877 SendMessage(window.windowHandle, WM_SETICON, ICON_BIG, (LPARAM)icon);
1878 SendMessage(window.windowHandle, WM_SETICON, ICON_SMALL, (LPARAM)icon);
1882 void ::GetScreenArea(Window window, Box box)
1884 HMONITOR monitor = MonitorFromWindow(window.windowHandle, MONITOR_DEFAULTTONEAREST);
1885 HMONITOR taskBarMonitor = MonitorFromWindow(startBar, MONITOR_DEFAULTTONEAREST);
1888 MONITORINFO info = { 0 };
1889 info.cbSize = sizeof(MONITORINFO);
1890 GetMonitorInfo(monitor, &info);
1891 // box = { info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom };
1892 box = { info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right-1, info.rcMonitor.bottom-1 };
1894 if(taskBarMonitor == monitor)
1896 if(taskBarPlacement.rcNormalPosition.top <= box.top && taskBarPlacement.rcNormalPosition.bottom >= box.bottom)
1898 if(taskBarPlacement.rcNormalPosition.left <= box.left)
1900 if(taskBarState & ABS_AUTOHIDE)
1903 box.left = taskBarPlacement.rcNormalPosition.right;
1905 else if(taskBarState & ABS_AUTOHIDE)
1908 box.right = taskBarPlacement.rcNormalPosition.left;
1910 else if(taskBarPlacement.rcNormalPosition.left <= box.left && taskBarPlacement.rcNormalPosition.right >= box.right)
1912 if(taskBarPlacement.rcNormalPosition.top <= box.top)
1914 if(taskBarState & ABS_AUTOHIDE)
1917 box.top = taskBarPlacement.rcNormalPosition.bottom;
1919 else if(taskBarState & ABS_AUTOHIDE)
1922 box.bottom = taskBarPlacement.rcNormalPosition.top;
1926 box.left -= desktopX;
1927 box.top -= desktopY;
1928 box.right -= desktopX;
1929 box.bottom -= desktopY;