0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / WNT / WNT_Window.cxx
... / ...
CommitLineData
1// Copyright (c) 1998-1999 Matra Datavision
2// Copyright (c) 1999-2014 OPEN CASCADE SAS
3//
4// This file is part of Open CASCADE Technology software library.
5//
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.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
15#if defined(_WIN32)
16 // include windows.h first to have all definitions available
17 #include <windows.h>
18#endif
19
20#include <WNT_Window.hxx>
21
22#if defined(_WIN32) && !defined(OCCT_UWP)
23
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>
31
32IMPLEMENT_STANDARD_RTTIEXT(WNT_Window, Aspect_Window)
33
34// =======================================================================
35// function : WNT_Window
36// purpose :
37// =======================================================================
38WNT_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)
49: Aspect_Window(),
50 aXLeft (thePxLeft),
51 aYTop (thePxTop),
52 aXRight (thePxLeft + thePxWidth),
53 aYBottom (thePxTop + thePxHeight),
54 myWClass (theClass),
55 myIsForeign (Standard_False)
56{
57 if (thePxWidth <= 0 || thePxHeight <= 0)
58 {
59 throw Aspect_WindowDefinitionError("Coordinate(s) out of range");
60 }
61
62 DWORD aStyle = theStyle;
63 if (theParent && !(theStyle & WS_CHILD))
64 {
65 aStyle |= WS_CHILD | WS_CLIPSIBLINGS;
66 }
67 else if (!theParent && !(theStyle & WS_CLIPCHILDREN))
68 {
69 aStyle |= WS_CLIPCHILDREN;
70 }
71
72 // include decorations in the window dimensions to reproduce same behavior of Xw_Window
73 RECT aRect;
74 aRect.top = aYTop;
75 aRect.bottom = aYBottom;
76 aRect.left = aXLeft;
77 aRect.right = aXRight;
78 AdjustWindowRect (&aRect, aStyle, theMenu != NULL ? TRUE : FALSE);
79 aXLeft = aRect.left;
80 aYTop = aRect.top;
81 aXRight = aRect.right;
82 aYBottom = aRect.bottom;
83
84 const TCollection_ExtendedString aTitleW (theTitle);
85 const TCollection_ExtendedString aClassNameW (myWClass->Name());
86 myHWindow = CreateWindowW (aClassNameW.ToWideString(), aTitleW.ToWideString(),
87 aStyle,
88 aXLeft, aYTop,
89 (aXRight - aXLeft), (aYBottom - aYTop),
90 (HWND )theParent,
91 (HMENU )theMenu,
92 (HINSTANCE )myWClass->Instance(),
93 theClientStruct);
94 if (!myHWindow)
95 {
96 throw Aspect_WindowDefinitionError("Unable to create window");
97 }
98
99 myHParentWindow = theParent;
100 SetBackground (theBackColor);
101}
102
103// =======================================================================
104// function : WNT_Window
105// purpose :
106// =======================================================================
107WNT_Window::WNT_Window (const Aspect_Handle theHandle,
108 const Quantity_NameOfColor theBackColor)
109: myIsForeign (Standard_True)
110{
111 myHWindow = theHandle;
112 myHParentWindow = GetParent ((HWND )theHandle);
113
114 SetBackground (theBackColor);
115
116 WINDOWPLACEMENT aPlace;
117 aPlace.length = sizeof (WINDOWPLACEMENT);
118 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
119
120 aXLeft = aPlace.rcNormalPosition.left;
121 aYTop = aPlace.rcNormalPosition.top;
122 aXRight = aPlace.rcNormalPosition.right;
123 aYBottom = aPlace.rcNormalPosition.bottom;
124}
125
126// =======================================================================
127// function : ~WNT_Window
128// purpose :
129// =======================================================================
130WNT_Window::~WNT_Window()
131{
132 if (myHWindow == NULL
133 || myIsForeign)
134 {
135 return;
136 }
137
138 DestroyWindow ((HWND )myHWindow);
139 myIsForeign = Standard_False;
140}
141
142// =======================================================================
143// function : SetCursor
144// purpose :
145// =======================================================================
146void WNT_Window::SetCursor (const Aspect_Handle theCursor) const
147{
148 ::SetClassLongPtrW ((HWND )myHWindow, GCLP_HCURSOR, (LONG_PTR )theCursor);
149}
150
151// =======================================================================
152// function : IsMapped
153// purpose :
154// =======================================================================
155Standard_Boolean WNT_Window::IsMapped() const
156{
157 if (IsVirtual())
158 {
159 return Standard_True;
160 }
161
162 WINDOWPLACEMENT aPlace;
163 aPlace.length = sizeof (WINDOWPLACEMENT);
164 ::GetWindowPlacement ((HWND )myHWindow, &aPlace);
165 return !(aPlace.showCmd == SW_HIDE
166 || aPlace.showCmd == SW_MINIMIZE);
167}
168
169// =======================================================================
170// function : Map
171// purpose :
172// =======================================================================
173void WNT_Window::Map() const
174{
175 if (!IsVirtual())
176 {
177 Map (SW_SHOW);
178 }
179}
180
181// =======================================================================
182// function : Map
183// purpose :
184// =======================================================================
185void WNT_Window::Map (const Standard_Integer theMapMode) const
186{
187 if (IsVirtual())
188 {
189 return;
190 }
191
192 ::ShowWindow ((HWND )myHWindow, theMapMode);
193 ::UpdateWindow ((HWND )myHWindow);
194}
195
196// =======================================================================
197// function : Unmap
198// purpose :
199// =======================================================================
200void WNT_Window::Unmap() const
201{
202 Map (SW_HIDE);
203}
204
205// =======================================================================
206// function : DoResize
207// purpose :
208// =======================================================================
209Aspect_TypeOfResize WNT_Window::DoResize()
210{
211 if (IsVirtual())
212 {
213 return Aspect_TOR_UNKNOWN;
214 }
215
216 int mask = 0;
217 Aspect_TypeOfResize mode = Aspect_TOR_UNKNOWN;
218 WINDOWPLACEMENT wp;
219
220 wp.length = sizeof ( WINDOWPLACEMENT );
221 GetWindowPlacement ( ( HWND )myHWindow, &wp );
222
223 if (wp.showCmd != SW_SHOWMINIMIZED)
224 {
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;
229
230 switch (mask)
231 {
232 case 0:
233 mode = Aspect_TOR_NO_BORDER;
234 break;
235 case 1:
236 mode = Aspect_TOR_LEFT_BORDER;
237 break;
238 case 2:
239 mode = Aspect_TOR_RIGHT_BORDER;
240 break;
241 case 4:
242 mode = Aspect_TOR_TOP_BORDER;
243 break;
244 case 5:
245 mode = Aspect_TOR_LEFT_AND_TOP_BORDER;
246 break;
247 case 6:
248 mode = Aspect_TOR_TOP_AND_RIGHT_BORDER;
249 break;
250 case 8:
251 mode = Aspect_TOR_BOTTOM_BORDER;
252 break;
253 case 9:
254 mode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER;
255 break;
256 case 10:
257 mode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER;
258 break;
259 default:
260 break;
261 } // end switch
262
263 aXLeft = wp.rcNormalPosition.left;
264 aXRight = wp.rcNormalPosition.right;
265 aYTop = wp.rcNormalPosition.top;
266 aYBottom = wp.rcNormalPosition.bottom;
267 }
268
269 return mode;
270}
271
272// =======================================================================
273// function : Ratio
274// purpose :
275// =======================================================================
276Standard_Real WNT_Window::Ratio() const
277{
278 if (IsVirtual())
279 {
280 return Standard_Real(aXRight - aXLeft)/ Standard_Real(aYBottom - aYTop);
281 }
282
283 RECT aRect;
284 GetClientRect ((HWND )myHWindow, &aRect);
285 return Standard_Real(aRect.right - aRect.left) / Standard_Real(aRect.bottom - aRect.top);
286}
287
288// =======================================================================
289// function : Position
290// purpose :
291// =======================================================================
292void WNT_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1,
293 Standard_Integer& theX2, Standard_Integer& theY2) const
294{
295 if (IsVirtual())
296 {
297 theX1 = aXLeft;
298 theX2 = aXRight;
299 theY1 = aYTop;
300 theY2 = aYBottom;
301 return;
302 }
303
304 RECT aRect;
305 ::GetClientRect ((HWND )myHWindow, &aRect);
306
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);
313
314 if (myHParentWindow != NULL)
315 {
316 ::ScreenToClient ((HWND )myHParentWindow, &aPntLeft);
317 ::ScreenToClient ((HWND )myHParentWindow, &aPntRight);
318 }
319
320 theX1 = aPntLeft.x;
321 theX2 = aPntRight.x;
322 theY1 = aPntLeft.y;
323 theY2 = aPntRight.y;
324}
325
326// =======================================================================
327// function : Size
328// purpose :
329// =======================================================================
330void WNT_Window::Size (Standard_Integer& theWidth,
331 Standard_Integer& theHeight) const
332{
333 if (IsVirtual())
334 {
335 theWidth = aXRight - aXLeft;
336 theHeight = aYBottom - aYTop;
337 return;
338 }
339
340 RECT aRect;
341 ::GetClientRect ((HWND )myHWindow, &aRect);
342 theWidth = aRect.right;
343 theHeight = aRect.bottom;
344}
345
346// =======================================================================
347// function : SetPos
348// purpose :
349// =======================================================================
350void WNT_Window::SetPos (const Standard_Integer theX, const Standard_Integer theY,
351 const Standard_Integer theX1, const Standard_Integer theY1)
352{
353 aXLeft = theX;
354 aYTop = theY;
355 aXRight = theX1;
356 aYBottom = theY1;
357}
358
359// =======================================================================
360// function : SetTitle
361// purpose :
362// =======================================================================
363void WNT_Window::SetTitle (const TCollection_AsciiString& theTitle)
364{
365 const TCollection_ExtendedString aTitleW (theTitle);
366 SetWindowTextW ((HWND )myHWindow, aTitleW.ToWideString());
367}
368
369// =======================================================================
370// function : InvalidateContent
371// purpose :
372// =======================================================================
373void WNT_Window::InvalidateContent (const Handle(Aspect_DisplayConnection)& )
374{
375 if (myHWindow != NULL)
376 {
377 ::InvalidateRect ((HWND )myHWindow, NULL, TRUE);
378 }
379}
380
381// =======================================================================
382// function : VirtualKeyFromNative
383// purpose :
384// =======================================================================
385Aspect_VKey WNT_Window::VirtualKeyFromNative (Standard_Integer theKey)
386{
387 if (theKey >= Standard_Integer('0')
388 && theKey <= Standard_Integer('9'))
389 {
390 return Aspect_VKey((theKey - Standard_Integer('0')) + Aspect_VKey_0);
391 }
392 if (theKey >= Standard_Integer('A')
393 && theKey <= Standard_Integer('Z'))
394 {
395 // main latin alphabet keys
396 return Aspect_VKey((theKey - Standard_Integer('A')) + Aspect_VKey_A);
397 }
398 if (theKey >= VK_F1
399 && theKey <= VK_F24)
400 {
401 // special keys
402 if (theKey <= VK_F12)
403 {
404 return Aspect_VKey((theKey - VK_F1) + Aspect_VKey_F1);
405 }
406 return Aspect_VKey_UNKNOWN;
407 }
408 if (theKey >= VK_NUMPAD0
409 && theKey <= VK_NUMPAD9)
410 {
411 // numpad keys
412 return Aspect_VKey((theKey - VK_NUMPAD0) + Aspect_VKey_Numpad0);
413 }
414
415 switch (theKey)
416 {
417 case VK_LBUTTON:
418 case VK_RBUTTON:
419 case VK_CANCEL:
420 case VK_MBUTTON:
421 case VK_XBUTTON1:
422 case VK_XBUTTON2:
423 return Aspect_VKey_UNKNOWN;
424 case VK_BACK:
425 return Aspect_VKey_Backspace;
426 case VK_TAB:
427 return Aspect_VKey_Tab;
428 case VK_CLEAR:
429 return Aspect_VKey_UNKNOWN;
430 case VK_RETURN:
431 return Aspect_VKey_Enter;
432 case VK_SHIFT:
433 return Aspect_VKey_Shift;
434 case VK_CONTROL:
435 return Aspect_VKey_Control;
436 case VK_MENU:
437 return Aspect_VKey_Alt; //Aspect_VKey_Menu;
438 case VK_PAUSE:
439 case VK_CAPITAL:
440 return Aspect_VKey_UNKNOWN;
441 case VK_ESCAPE:
442 return Aspect_VKey_Escape;
443 case VK_CONVERT:
444 case VK_NONCONVERT:
445 case VK_ACCEPT:
446 case VK_MODECHANGE:
447 return Aspect_VKey_UNKNOWN;
448 case VK_SPACE:
449 return Aspect_VKey_Space;
450 case VK_PRIOR:
451 return Aspect_VKey_PageUp;
452 case VK_NEXT:
453 return Aspect_VKey_PageDown;
454 case VK_END:
455 return Aspect_VKey_End;
456 case VK_HOME:
457 return Aspect_VKey_Home;
458 case VK_LEFT:
459 return Aspect_VKey_Left;
460 case VK_UP:
461 return Aspect_VKey_Up;
462 case VK_DOWN:
463 return Aspect_VKey_Down;
464 case VK_RIGHT:
465 return Aspect_VKey_Right;
466 case VK_SELECT:
467 case VK_PRINT:
468 case VK_EXECUTE:
469 case VK_SNAPSHOT:
470 return Aspect_VKey_UNKNOWN;
471 case VK_INSERT:
472 return Aspect_VKey_UNKNOWN; // Aspect_VKey_Insert
473 case VK_DELETE:
474 return Aspect_VKey_Delete;
475 case VK_HELP:
476 case VK_LWIN:
477 case VK_RWIN:
478 case VK_APPS:
479 case VK_SLEEP:
480 return Aspect_VKey_UNKNOWN;
481 case VK_MULTIPLY:
482 return Aspect_VKey_NumpadMultiply;
483 case VK_ADD:
484 return Aspect_VKey_NumpadAdd;
485 case VK_SEPARATOR:
486 case VK_DECIMAL:
487 return Aspect_VKey_UNKNOWN;
488 case VK_SUBTRACT:
489 return Aspect_VKey_NumpadSubtract;
490 case VK_DIVIDE:
491 return Aspect_VKey_NumpadDivide;
492 case VK_NUMLOCK:
493 return Aspect_VKey_Numlock;
494 case VK_SCROLL:
495 return Aspect_VKey_Scroll;
496 case VK_LSHIFT:
497 case VK_RSHIFT:
498 case VK_LCONTROL:
499 case VK_RCONTROL:
500 case VK_LMENU:
501 case VK_RMENU:
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;
517 case VK_VOLUME_MUTE:
518 return Aspect_VKey_VolumeMute;
519 case VK_VOLUME_DOWN:
520 return Aspect_VKey_VolumeDown;
521 case VK_VOLUME_UP:
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;
527 case VK_MEDIA_STOP:
528 return Aspect_VKey_MediaStop;
529 case VK_MEDIA_PLAY_PAUSE:
530 return Aspect_VKey_MediaPlayPause;
531 case VK_OEM_1:
532 return Aspect_VKey_Semicolon;
533 case VK_OEM_PLUS:
534 return Aspect_VKey_Plus;
535 case VK_OEM_COMMA:
536 return Aspect_VKey_Comma;
537 case VK_OEM_MINUS:
538 return Aspect_VKey_Minus;
539 case VK_OEM_PERIOD:
540 return Aspect_VKey_Period;
541 case VK_OEM_2:
542 return Aspect_VKey_Slash;
543 case VK_OEM_3:
544 return Aspect_VKey_Tilde;
545 case VK_OEM_4:
546 return Aspect_VKey_BracketLeft;
547 case VK_OEM_5:
548 return Aspect_VKey_Backslash;
549 case VK_OEM_6:
550 return Aspect_VKey_BracketRight;
551 case VK_OEM_7:
552 return Aspect_VKey_Apostrophe;
553 }
554 return Aspect_VKey_UNKNOWN;
555}
556
557// =======================================================================
558// function : MouseKeyFlagsFromEvent
559// purpose :
560// =======================================================================
561Aspect_VKeyFlags WNT_Window::MouseKeyFlagsFromEvent (WPARAM theKeys)
562{
563 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
564 if ((theKeys & MK_CONTROL) != 0)
565 {
566 aFlags |= Aspect_VKeyFlags_CTRL;
567 }
568 if ((theKeys & MK_SHIFT) != 0)
569 {
570 aFlags |= Aspect_VKeyFlags_SHIFT;
571 }
572 if (GetKeyState (VK_MENU) < 0)
573 {
574 aFlags |= Aspect_VKeyFlags_ALT;
575 }
576 return aFlags;
577}
578
579// =======================================================================
580// function : MouseKeyFlagsAsync
581// purpose :
582// =======================================================================
583Aspect_VKeyFlags WNT_Window::MouseKeyFlagsAsync()
584{
585 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
586 if ((GetAsyncKeyState (VK_CONTROL) & 0x8000) != 0)
587 {
588 aFlags |= Aspect_VKeyFlags_CTRL;
589 }
590 if ((GetAsyncKeyState (VK_SHIFT) & 0x8000) != 0)
591 {
592 aFlags |= Aspect_VKeyFlags_SHIFT;
593 }
594 if ((GetAsyncKeyState (VK_MENU) & 0x8000) != 0)
595 {
596 aFlags |= Aspect_VKeyFlags_ALT;
597 }
598 return aFlags;
599}
600
601// =======================================================================
602// function : MouseButtonsFromEvent
603// purpose :
604// =======================================================================
605Aspect_VKeyMouse WNT_Window::MouseButtonsFromEvent (WPARAM theKeys)
606{
607 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
608 if ((theKeys & MK_LBUTTON) != 0)
609 {
610 aButtons |= Aspect_VKeyMouse_LeftButton;
611 }
612 if ((theKeys & MK_MBUTTON) != 0)
613 {
614 aButtons |= Aspect_VKeyMouse_MiddleButton;
615 }
616 if ((theKeys & MK_RBUTTON) != 0)
617 {
618 aButtons |= Aspect_VKeyMouse_RightButton;
619 }
620 return aButtons;
621}
622
623// =======================================================================
624// function : MouseButtonsAsync
625// purpose :
626// =======================================================================
627Aspect_VKeyMouse WNT_Window::MouseButtonsAsync()
628{
629 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
630 const bool isSwapped = GetSystemMetrics (SM_SWAPBUTTON) != 0;
631
632 if ((GetAsyncKeyState (!isSwapped ? VK_LBUTTON : VK_RBUTTON) & 0x8000) != 0)
633 {
634 aButtons |= Aspect_VKeyMouse_LeftButton;
635 }
636 if ((GetAsyncKeyState (VK_MBUTTON) & 0x8000) != 0)
637 {
638 aButtons |= Aspect_VKeyMouse_MiddleButton;
639 }
640 if ((GetAsyncKeyState (!isSwapped ? VK_RBUTTON : VK_LBUTTON) & 0x8000) != 0)
641 {
642 aButtons |= Aspect_VKeyMouse_RightButton;
643 }
644 return aButtons;
645}
646
647// =======================================================================
648// function : RegisterRawInputDevices
649// purpose :
650// =======================================================================
651int WNT_Window::RegisterRawInputDevices (unsigned int theRawDeviceMask)
652{
653 if (IsVirtual()
654 || myHWindow == NULL)
655 {
656 return 0;
657 }
658
659 // hidusage.h
660 enum HidUsagePage { THE_HID_USAGE_PAGE_GENERIC = 0x01 }; // HID_USAGE_PAGE_GENERIC
661 enum HidUsage
662 {
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
665 };
666
667 int aNbDevices = 0;
668 RAWINPUTDEVICE aRawInDevList[2];
669 if ((theRawDeviceMask & RawInputMask_Mouse) != 0)
670 {
671 // mouse
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;
677 }
678 if ((theRawDeviceMask & RawInputMask_SpaceMouse) != 0)
679 {
680 // space mouse
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;
686 }
687
688 for (int aTryIter = aNbDevices; aTryIter > 0; --aTryIter)
689 {
690 if (::RegisterRawInputDevices (aRawInDevList, aTryIter, sizeof(aRawInDevList[0])))
691 {
692 return aTryIter;
693 }
694
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");
698 }
699 return 0;
700}
701
702#endif // _WIN32