How to get window handle (HWND) of core application window on Win32 for QSpaceNavigator
-
Hi,
in my application I would like to use a device that supports the Windows Raw Input API (3D Connexion Space Navigator). In order to use the device I need a windows handle (HWND) that receives the WM_INPUT messages of the raw input device. My initial idea was, to use the QApplication window handle and then to overwrite the winEventFilter() method of QApplication to process the WM_INPUT events. But unlike QWidget the QApplication class does not provide a winId() function to get the native windows handle.
So my next idea (workaround) was, to derive my QSpaceNavigatorWidget class from QWidget, use the window handle of this widget optained via winId() funtion and overwrite the virtual funtion @bool winEvent(MSG * message, long * result)@
to process WM_INPUT events and to post QSpaceNavigatorEvent to the active window. But this is working only partly. It works only if a window that should receive the QSpaceNavigatorEvent contains a widget that can get the input focus (i.e. QSpinBox). If I activate that window and no widget has the input focus than the @bool winEvent(MSG * message, long * result)@
function of my QSpaceNavigatorWidget never gets called - strange?!?
The next thing I would try is to create my own private Win32 window in my QSpaceNavigator class and use this handle and my own private Win32 event handler to process the WM_INPUT events like it is done in qeventdispatcher_win.cpp
@HWND wnd = CreateWindow(wc.lpszClassName, // classname
wc.lpszClassName, // window name
0, // style
0, 0, 0, 0, // geometry
0, // parent
0, // menu handle
qWinAppInst(), // application
0); // windows creation data.@Is this an appropriate solution or is ther any best practice for using Win32 raw input devices in Qt?
-
Is this what you are looking for:
@WId QWidget::effectiveWinId () const@
Using this method you can get the native window handle used by QWidgets. WId is a typedef to HWND on windows.
-
It does not matter if I use
@WId QWidget::effectiveWinId () const@
or
@
WId QWidget::winId () const@Both functions return the same value for my widget. I can use the returned handle to register it with my raw input device but Qt calls the function
@bool QWidget::winEvent(MSG * message, long * result)@
of the widget that returned the native windows handle only, if the active and focused window contains a widget that can get the input focus. So the native windows handle of a QWidget is not suitable for use with Win32 raw input API. Therefore I need a valid handle of the applications core window (not the main window).
A possible solution would be to use the qWinAppInst() function to get a native Win32 hInstance value and to find the core application window via Win32 function calls:
@DWORD ProcIDFromWnd(HWND hWnd)
{
DWORD ProcId;
GetWindowThreadProcessId(hWnd, &ProcId);
return ProcId;
}HWND qGetNativeAppWindow()
{
HWND tempHwnd = 0;
// Grab the first window handle that Windows finds:
tempHwnd = FindWindow(0, 0);
HINSTANCE hInstance = qWinAppInst();
do
{
// Check if no parent for this window
if (GetParent(tempHwnd) == 0)
{
DWORD ProcId = ProcIDFromWnd(tempHwnd);
HINSTANCE AppInstance = (HINSTANCE)GetWindowLong(tempHwnd, GWL_HINSTANCE);
if (AppInstance == hInstance)
{
#ifdef GWLP_USERDATA
QAbstractEventDispatcher *q = (QAbstractEventDispatcher *) GetWindowLongPtr(tempHwnd, GWLP_USERDATA);
#else
QAbstractEventDispatcher *q = (QAbstractEventDispatcher *) GetWindowLong(tempHwnd, GWL_USERDATA);
#endif
if (q == QAbstractEventDispatcher::instance())
{
return tempHwnd;
}
}
}
tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT);
}
while (tempHwnd != 0);
return tempHwnd;
}
@Or is there any better solution to implement raw input device support for Win32?