1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 // include windows.h first to have all definitions available
20 #include <WNT_Window.hxx>
22 #if defined(_WIN32) && !defined(OCCT_UWP)
24 #include <Aspect_Convert.hxx>
25 #include <Aspect_WindowDefinitionError.hxx>
26 #include <Aspect_WindowError.hxx>
27 #include <Message.hxx>
28 #include <Standard_Type.hxx>
29 #include <TCollection_ExtendedString.hxx>
30 #include <WNT_WClass.hxx>
32 IMPLEMENT_STANDARD_RTTIEXT(WNT_Window, Aspect_Window)
34 // =======================================================================
35 // function : WNT_Window
37 // =======================================================================
38 WNT_Window::WNT_Window (const Standard_CString theTitle,
39 const Handle(WNT_WClass)& theClass,
40 const WNT_Dword& theStyle,
41 const Standard_Integer thePxLeft,
42 const Standard_Integer thePxTop,
43 const Standard_Integer thePxWidth,
44 const Standard_Integer thePxHeight,
45 const Quantity_NameOfColor theBackColor,
46 const Aspect_Handle theParent,
47 const Aspect_Handle theMenu,
48 const Standard_Address theClientStruct)
52 aXRight (thePxLeft + thePxWidth),
53 aYBottom (thePxTop + thePxHeight),
55 myIsForeign (Standard_False)
57 if (thePxWidth <= 0 || thePxHeight <= 0)
59 throw Aspect_WindowDefinitionError("Coordinate(s) out of range");
62 DWORD aStyle = theStyle;
63 if (theParent && !(theStyle & WS_CHILD))
65 aStyle |= WS_CHILD | WS_CLIPSIBLINGS;
67 else if (!theParent && !(theStyle & WS_CLIPCHILDREN))
69 aStyle |= WS_CLIPCHILDREN;
72 // include decorations in the window dimensions to reproduce same behavior of Xw_Window
75 aRect.bottom = aYBottom;
77 aRect.right = aXRight;
78 AdjustWindowRect (&aRect, aStyle, theMenu != NULL ? TRUE : FALSE);
81 aXRight = aRect.right;
82 aYBottom = aRect.bottom;
84 const TCollection_ExtendedString aTitleW (theTitle);
85 const TCollection_ExtendedString aClassNameW (myWClass->Name());
86 myHWindow = CreateWindowW (aClassNameW.ToWideString(), aTitleW.ToWideString(),
89 (aXRight - aXLeft), (aYBottom - aYTop),
92 (HINSTANCE )myWClass->Instance(),
96 throw Aspect_WindowDefinitionError("Unable to create window");
99 myHParentWindow = theParent;
100 SetBackground (theBackColor);
103 // =======================================================================
104 // function : WNT_Window
106 // =======================================================================
107 WNT_Window::WNT_Window (const Aspect_Handle theHandle,
108 const Quantity_NameOfColor theBackColor)
109 : myIsForeign (Standard_True)
111 myHWindow = theHandle;
112 myHParentWindow = GetParent ((HWND )theHandle);
114 SetBackground (theBackColor);
116 WINDOWPLACEMENT aPlace;
117 aPlace.length = sizeof (WINDOWPLACEMENT);
118 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
120 aXLeft = aPlace.rcNormalPosition.left;
121 aYTop = aPlace.rcNormalPosition.top;
122 aXRight = aPlace.rcNormalPosition.right;
123 aYBottom = aPlace.rcNormalPosition.bottom;
126 // =======================================================================
127 // function : ~WNT_Window
129 // =======================================================================
130 WNT_Window::~WNT_Window()
132 if (myHWindow == NULL
138 DestroyWindow ((HWND )myHWindow);
139 myIsForeign = Standard_False;
142 // =======================================================================
143 // function : SetCursor
145 // =======================================================================
146 void WNT_Window::SetCursor (const Aspect_Handle theCursor) const
148 ::SetClassLongPtrW ((HWND )myHWindow, GCLP_HCURSOR, (LONG_PTR )theCursor);
151 // =======================================================================
152 // function : IsMapped
154 // =======================================================================
155 Standard_Boolean WNT_Window::IsMapped() const
159 return Standard_True;
162 WINDOWPLACEMENT aPlace;
163 aPlace.length = sizeof (WINDOWPLACEMENT);
164 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
165 return !(aPlace.showCmd == SW_HIDE
166 || aPlace.showCmd == SW_MINIMIZE);
169 // =======================================================================
172 // =======================================================================
173 void WNT_Window::Map() const
181 // =======================================================================
184 // =======================================================================
185 void WNT_Window::Map (const Standard_Integer theMapMode) const
192 ::ShowWindow ((HWND )myHWindow, theMapMode);
193 ::UpdateWindow ((HWND )myHWindow);
196 // =======================================================================
199 // =======================================================================
200 void WNT_Window::Unmap() const
205 // =======================================================================
206 // function : DoResize
208 // =======================================================================
209 Aspect_TypeOfResize WNT_Window::DoResize()
213 return Aspect_TOR_UNKNOWN;
217 Aspect_TypeOfResize mode = Aspect_TOR_UNKNOWN;
220 wp.length = sizeof ( WINDOWPLACEMENT );
221 GetWindowPlacement ( ( HWND )myHWindow, &wp );
223 if (wp.showCmd != SW_SHOWMINIMIZED)
225 if (Abs ((int )wp.rcNormalPosition.left - aXLeft ) > 2) mask |= 1;
226 if (Abs ((int )wp.rcNormalPosition.right - aXRight ) > 2) mask |= 2;
227 if (Abs ((int )wp.rcNormalPosition.top - aYTop ) > 2) mask |= 4;
228 if (Abs ((int )wp.rcNormalPosition.bottom - aYBottom) > 2) mask |= 8;
233 mode = Aspect_TOR_NO_BORDER;
236 mode = Aspect_TOR_LEFT_BORDER;
239 mode = Aspect_TOR_RIGHT_BORDER;
242 mode = Aspect_TOR_TOP_BORDER;
245 mode = Aspect_TOR_LEFT_AND_TOP_BORDER;
248 mode = Aspect_TOR_TOP_AND_RIGHT_BORDER;
251 mode = Aspect_TOR_BOTTOM_BORDER;
254 mode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER;
257 mode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER;
263 aXLeft = wp.rcNormalPosition.left;
264 aXRight = wp.rcNormalPosition.right;
265 aYTop = wp.rcNormalPosition.top;
266 aYBottom = wp.rcNormalPosition.bottom;
272 // =======================================================================
275 // =======================================================================
276 Standard_Real WNT_Window::Ratio() const
280 return Standard_Real(aXRight - aXLeft)/ Standard_Real(aYBottom - aYTop);
284 GetClientRect ((HWND )myHWindow, &aRect);
285 return Standard_Real(aRect.right - aRect.left) / Standard_Real(aRect.bottom - aRect.top);
288 // =======================================================================
289 // function : Position
291 // =======================================================================
292 void WNT_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1,
293 Standard_Integer& theX2, Standard_Integer& theY2) const
305 ::GetClientRect ((HWND )myHWindow, &aRect);
307 POINT aPntLeft, aPntRight;
308 aPntLeft.x = aPntLeft.y = 0;
309 ::ClientToScreen ((HWND )myHWindow, &aPntLeft);
310 aPntRight.x = aRect.right;
311 aPntRight.y = aRect.bottom;
312 ::ClientToScreen ((HWND )myHWindow, &aPntRight);
314 if (myHParentWindow != NULL)
316 ::ScreenToClient ((HWND )myHParentWindow, &aPntLeft);
317 ::ScreenToClient ((HWND )myHParentWindow, &aPntRight);
326 // =======================================================================
329 // =======================================================================
330 void WNT_Window::Size (Standard_Integer& theWidth,
331 Standard_Integer& theHeight) const
335 theWidth = aXRight - aXLeft;
336 theHeight = aYBottom - aYTop;
341 ::GetClientRect ((HWND )myHWindow, &aRect);
342 theWidth = aRect.right;
343 theHeight = aRect.bottom;
346 // =======================================================================
349 // =======================================================================
350 void WNT_Window::SetPos (const Standard_Integer theX, const Standard_Integer theY,
351 const Standard_Integer theX1, const Standard_Integer theY1)
359 // =======================================================================
360 // function : SetTitle
362 // =======================================================================
363 void WNT_Window::SetTitle (const TCollection_AsciiString& theTitle)
365 const TCollection_ExtendedString aTitleW (theTitle);
366 SetWindowTextW ((HWND )myHWindow, aTitleW.ToWideString());
369 // =======================================================================
370 // function : InvalidateContent
372 // =======================================================================
373 void WNT_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& )
375 if (myHWindow != NULL)
377 ::InvalidateRect ((HWND )myHWindow, NULL, TRUE);
381 // =======================================================================
382 // function : VirtualKeyFromNative
384 // =======================================================================
385 Aspect_VKey WNT_Window::VirtualKeyFromNative (Standard_Integer theKey)
387 if (theKey >= Standard_Integer('0')
388 && theKey <= Standard_Integer('9'))
390 return Aspect_VKey((theKey - Standard_Integer('0')) + Aspect_VKey_0);
392 if (theKey >= Standard_Integer('A')
393 && theKey <= Standard_Integer('Z'))
395 // main latin alphabet keys
396 return Aspect_VKey((theKey - Standard_Integer('A')) + Aspect_VKey_A);
402 if (theKey <= VK_F12)
404 return Aspect_VKey((theKey - VK_F1) + Aspect_VKey_F1);
406 return Aspect_VKey_UNKNOWN;
408 if (theKey >= VK_NUMPAD0
409 && theKey <= VK_NUMPAD9)
412 return Aspect_VKey((theKey - VK_NUMPAD0) + Aspect_VKey_Numpad0);
423 return Aspect_VKey_UNKNOWN;
425 return Aspect_VKey_Backspace;
427 return Aspect_VKey_Tab;
429 return Aspect_VKey_UNKNOWN;
431 return Aspect_VKey_Enter;
433 return Aspect_VKey_Shift;
435 return Aspect_VKey_Control;
437 return Aspect_VKey_Alt; //Aspect_VKey_Menu;
440 return Aspect_VKey_UNKNOWN;
442 return Aspect_VKey_Escape;
447 return Aspect_VKey_UNKNOWN;
449 return Aspect_VKey_Space;
451 return Aspect_VKey_PageUp;
453 return Aspect_VKey_PageDown;
455 return Aspect_VKey_End;
457 return Aspect_VKey_Home;
459 return Aspect_VKey_Left;
461 return Aspect_VKey_Up;
463 return Aspect_VKey_Down;
465 return Aspect_VKey_Right;
470 return Aspect_VKey_UNKNOWN;
472 return Aspect_VKey_UNKNOWN; // Aspect_VKey_Insert
474 return Aspect_VKey_Delete;
480 return Aspect_VKey_UNKNOWN;
482 return Aspect_VKey_NumpadMultiply;
484 return Aspect_VKey_NumpadAdd;
487 return Aspect_VKey_UNKNOWN;
489 return Aspect_VKey_NumpadSubtract;
491 return Aspect_VKey_NumpadDivide;
493 return Aspect_VKey_Numlock;
495 return Aspect_VKey_Scroll;
502 return Aspect_VKey_UNKNOWN;
503 case VK_BROWSER_BACK:
504 return Aspect_VKey_BrowserBack;
505 case VK_BROWSER_FORWARD:
506 return Aspect_VKey_BrowserForward;
507 case VK_BROWSER_REFRESH:
508 return Aspect_VKey_BrowserRefresh;
509 case VK_BROWSER_STOP:
510 return Aspect_VKey_BrowserStop;
511 case VK_BROWSER_SEARCH:
512 return Aspect_VKey_BrowserSearch;
513 case VK_BROWSER_FAVORITES:
514 return Aspect_VKey_BrowserFavorites;
515 case VK_BROWSER_HOME:
516 return Aspect_VKey_BrowserHome;
518 return Aspect_VKey_VolumeMute;
520 return Aspect_VKey_VolumeDown;
522 return Aspect_VKey_VolumeUp;
523 case VK_MEDIA_NEXT_TRACK:
524 return Aspect_VKey_MediaNextTrack;
525 case VK_MEDIA_PREV_TRACK:
526 return Aspect_VKey_MediaPreviousTrack;
528 return Aspect_VKey_MediaStop;
529 case VK_MEDIA_PLAY_PAUSE:
530 return Aspect_VKey_MediaPlayPause;
532 return Aspect_VKey_Semicolon;
534 return Aspect_VKey_Plus;
536 return Aspect_VKey_Comma;
538 return Aspect_VKey_Minus;
540 return Aspect_VKey_Period;
542 return Aspect_VKey_Slash;
544 return Aspect_VKey_Tilde;
546 return Aspect_VKey_BracketLeft;
548 return Aspect_VKey_Backslash;
550 return Aspect_VKey_BracketRight;
552 return Aspect_VKey_Apostrophe;
554 return Aspect_VKey_UNKNOWN;
557 // =======================================================================
558 // function : MouseKeyFlagsFromEvent
560 // =======================================================================
561 Aspect_VKeyFlags WNT_Window::MouseKeyFlagsFromEvent (WPARAM theKeys)
563 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
564 if ((theKeys & MK_CONTROL) != 0)
566 aFlags |= Aspect_VKeyFlags_CTRL;
568 if ((theKeys & MK_SHIFT) != 0)
570 aFlags |= Aspect_VKeyFlags_SHIFT;
572 if (GetKeyState (VK_MENU) < 0)
574 aFlags |= Aspect_VKeyFlags_ALT;
579 // =======================================================================
580 // function : MouseKeyFlagsAsync
582 // =======================================================================
583 Aspect_VKeyFlags WNT_Window::MouseKeyFlagsAsync()
585 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
586 if ((GetAsyncKeyState (VK_CONTROL) & 0x8000) != 0)
588 aFlags |= Aspect_VKeyFlags_CTRL;
590 if ((GetAsyncKeyState (VK_SHIFT) & 0x8000) != 0)
592 aFlags |= Aspect_VKeyFlags_SHIFT;
594 if ((GetAsyncKeyState (VK_MENU) & 0x8000) != 0)
596 aFlags |= Aspect_VKeyFlags_ALT;
601 // =======================================================================
602 // function : MouseButtonsFromEvent
604 // =======================================================================
605 Aspect_VKeyMouse WNT_Window::MouseButtonsFromEvent (WPARAM theKeys)
607 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
608 if ((theKeys & MK_LBUTTON) != 0)
610 aButtons |= Aspect_VKeyMouse_LeftButton;
612 if ((theKeys & MK_MBUTTON) != 0)
614 aButtons |= Aspect_VKeyMouse_MiddleButton;
616 if ((theKeys & MK_RBUTTON) != 0)
618 aButtons |= Aspect_VKeyMouse_RightButton;
623 // =======================================================================
624 // function : MouseButtonsAsync
626 // =======================================================================
627 Aspect_VKeyMouse WNT_Window::MouseButtonsAsync()
629 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
630 const bool isSwapped = GetSystemMetrics (SM_SWAPBUTTON) != 0;
632 if ((GetAsyncKeyState (!isSwapped ? VK_LBUTTON : VK_RBUTTON) & 0x8000) != 0)
634 aButtons |= Aspect_VKeyMouse_LeftButton;
636 if ((GetAsyncKeyState (VK_MBUTTON) & 0x8000) != 0)
638 aButtons |= Aspect_VKeyMouse_MiddleButton;
640 if ((GetAsyncKeyState (!isSwapped ? VK_RBUTTON : VK_LBUTTON) & 0x8000) != 0)
642 aButtons |= Aspect_VKeyMouse_RightButton;
647 // =======================================================================
648 // function : RegisterRawInputDevices
650 // =======================================================================
651 int WNT_Window::RegisterRawInputDevices (unsigned int theRawDeviceMask)
654 || myHWindow == NULL)
660 enum HidUsagePage { THE_HID_USAGE_PAGE_GENERIC = 0x01 }; // HID_USAGE_PAGE_GENERIC
663 THE_HID_USAGE_GENERIC_MOUSE = 0x02, // HID_USAGE_GENERIC_MOUSE
664 THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER = 0x08, // HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
668 RAWINPUTDEVICE aRawInDevList[2];
669 if ((theRawDeviceMask & RawInputMask_Mouse) != 0)
672 RAWINPUTDEVICE& aRawMouse = aRawInDevList[aNbDevices++];
673 aRawMouse.usUsagePage = THE_HID_USAGE_PAGE_GENERIC;
674 aRawMouse.usUsage = THE_HID_USAGE_GENERIC_MOUSE;
675 aRawMouse.dwFlags = RIDEV_INPUTSINK;
676 aRawMouse.hwndTarget = (HWND )myHWindow;
678 if ((theRawDeviceMask & RawInputMask_SpaceMouse) != 0)
681 RAWINPUTDEVICE& aRawSpace = aRawInDevList[aNbDevices++];
682 aRawSpace.usUsagePage = THE_HID_USAGE_PAGE_GENERIC;
683 aRawSpace.usUsage = THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER;
684 aRawSpace.dwFlags = 0; // RIDEV_DEVNOTIFY
685 aRawSpace.hwndTarget = (HWND )myHWindow;
688 for (int aTryIter = aNbDevices; aTryIter > 0; --aTryIter)
690 if (::RegisterRawInputDevices (aRawInDevList, aTryIter, sizeof(aRawInDevList[0])))
695 Message::SendTrace (aRawInDevList[aTryIter - 1].usUsage == THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
696 ? "Warning: RegisterRawInputDevices() failed to register RAW multi-axis controller input"
697 : "Warning: RegisterRawInputDevices() failed to register RAW mouse input");