Fix virtual key mapping on MS Windows
[qt:qt.git] / src / corelib / kernel / qcoreapplication_win.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qcoreapplication.h"
43 #include "qcoreapplication_p.h"
44 #include "qstringlist.h"
45 #include "qt_windows.h"
46 #include "qvector.h"
47 #include "qmutex.h"
48 #include "qfileinfo.h"
49 #include "qcorecmdlineargs_p.h"
50 #include <private/qthread_p.h>
51 #include <ctype.h>
52
53 QT_BEGIN_NAMESPACE
54
55 bool usingWinMain = false;  // whether the qWinMain() is used or not
56 int appCmdShow = 0;
57
58 Q_CORE_EXPORT HINSTANCE qWinAppInst()                // get Windows app handle
59 {
60     return GetModuleHandle(0);
61 }
62
63 Q_CORE_EXPORT HINSTANCE qWinAppPrevInst()                // get Windows prev app handle
64 {
65     return 0;
66 }
67
68 Q_CORE_EXPORT int qWinAppCmdShow()                        // get main window show command
69 {
70 #if defined(Q_OS_WINCE)
71     return appCmdShow;
72 #else
73     STARTUPINFO startupInfo;
74     GetStartupInfo(&startupInfo);
75
76     return (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
77         ? startupInfo.wShowWindow
78         : SW_SHOWDEFAULT;
79 #endif
80 }
81
82 Q_CORE_EXPORT QString qAppFileName()                // get application file name
83 {
84     // We do MAX_PATH + 2 here, and request with MAX_PATH + 1, so we can handle all paths
85     // up to, and including MAX_PATH size perfectly fine with string termination, as well
86     // as easily detect if the file path is indeed larger than MAX_PATH, in which case we
87     // need to use the heap instead. This is a work-around, since contrary to what the
88     // MSDN documentation states, GetModuleFileName sometimes doesn't set the
89     // ERROR_INSUFFICIENT_BUFFER error number, and we thus cannot rely on this value if
90     // GetModuleFileName(0, buffer, MAX_PATH) == MAX_PATH.
91     // GetModuleFileName(0, buffer, MAX_PATH + 1) == MAX_PATH just means we hit the normal
92     // file path limit, and we handle it normally, if the result is MAX_PATH + 1, we use
93     // heap (even if the result _might_ be exactly MAX_PATH + 1, but that's ok).
94     wchar_t buffer[MAX_PATH + 2];
95     DWORD v = GetModuleFileName(0, buffer, MAX_PATH + 1);
96     buffer[MAX_PATH + 1] = 0;
97
98     if (v == 0)
99         return QString();
100     else if (v <= MAX_PATH)
101         return QString::fromWCharArray(buffer);
102
103     // MAX_PATH sized buffer wasn't large enough to contain the full path, use heap
104     wchar_t *b = 0;
105     int i = 1;
106     size_t size;
107     do {
108         ++i;
109         size = MAX_PATH * i;
110         b = reinterpret_cast<wchar_t *>(realloc(b, (size + 1) * sizeof(wchar_t)));
111         if (b)
112             v = GetModuleFileName(NULL, b, size);
113     } while (b && v == size);
114
115     if (b)
116         *(b + size) = 0;
117     QString res = QString::fromWCharArray(b);
118     free(b);
119
120     return res;
121 }
122
123 QString QCoreApplicationPrivate::appName() const
124 {
125     return QFileInfo(qAppFileName()).baseName();
126 }
127
128 class QWinMsgHandlerCriticalSection
129 {
130     CRITICAL_SECTION cs;
131 public:
132     QWinMsgHandlerCriticalSection()
133     { InitializeCriticalSection(&cs); }
134     ~QWinMsgHandlerCriticalSection()
135     { DeleteCriticalSection(&cs); }
136
137     void lock()
138     { EnterCriticalSection(&cs); }
139     void unlock()
140     { LeaveCriticalSection(&cs); }
141 };
142
143 Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str)
144 {
145     Q_UNUSED(t);
146     // OutputDebugString is not threadsafe.
147
148     // cannot use QMutex here, because qWarning()s in the QMutex
149     // implementation may cause this function to recurse
150     static QWinMsgHandlerCriticalSection staticCriticalSection;
151
152     if (!str)
153         str = "(null)";
154
155     staticCriticalSection.lock();
156
157     QString s(QString::fromLocal8Bit(str));
158     s += QLatin1Char('\n');
159     OutputDebugString((wchar_t*)s.utf16());
160
161     staticCriticalSection.unlock();
162 }
163
164
165 /*****************************************************************************
166   qWinMain() - Initializes Windows. Called from WinMain() in qtmain_win.cpp
167  *****************************************************************************/
168
169 #if defined(Q_OS_WINCE)
170 Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
171                int cmdShow, int &argc, QVector<char *> &argv)
172 #else
173 Q_CORE_EXPORT
174 void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
175                int cmdShow, int &argc, QVector<char *> &argv)
176 #endif
177 {
178     static bool already_called = false;
179
180     if (already_called) {
181         qWarning("Qt: Internal error: qWinMain should be called only once");
182         return;
183     }
184     already_called = true;
185     usingWinMain = true;
186
187     // Install default debug handler
188     qInstallMsgHandler(qWinMsgHandler);
189
190     // Create command line
191     argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);
192
193     appCmdShow = cmdShow;
194
195     // Ignore Windows parameters
196     Q_UNUSED(instance);
197     Q_UNUSED(prevInstance);
198 }
199
200 /*!
201     The message procedure calls this function for every message
202     received. Reimplement this function if you want to process window
203     messages \a msg that are not processed by Qt. If you don't want
204     the event to be processed by Qt, then return true and set \a result
205     to the value that the window procedure should return. Otherwise
206     return false.
207
208     It is only directly addressed messages that are filtered. To
209     handle system wide messages, such as messages from a registered
210     hot key, you need to install an event filter on the event
211     dispatcher, which is returned from
212     QAbstractEventDispatcher::instance().
213 */
214 bool QCoreApplication::winEventFilter(MSG *msg, long *result)        // Windows event filter
215 {
216     Q_UNUSED(msg);
217     Q_UNUSED(result);
218     return false;
219 }
220
221 void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
222 {
223     QThreadData *data = object->d_func()->threadData;
224
225     QMutexLocker locker(&data->postEventList.mutex);
226     if (data->postEventList.size() == 0)
227         return;
228     for (int i = 0; i < data->postEventList.size(); ++i) {
229         const QPostEvent & pe = data->postEventList.at(i);
230         if (pe.receiver == object
231             && pe.event
232             && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
233             && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
234                 --pe.receiver->d_func()->postedEvents;
235                 pe.event->posted = false;
236                 delete pe.event;
237                 const_cast<QPostEvent &>(pe).event = 0;
238                 return;
239             }
240     }
241 }
242
243 #if defined(Q_WS_WIN) && !defined(QT_NO_DEBUG_STREAM)
244 /*****************************************************************************
245   Convenience functions for convert WM_* messages into human readable strings,
246   including a nifty QDebug operator<< for simpel QDebug() << msg output.
247  *****************************************************************************/
248 QT_BEGIN_INCLUDE_NAMESPACE
249 #include <windowsx.h>
250 #include "qdebug.h"
251 QT_END_INCLUDE_NAMESPACE
252
253 #if !defined(GET_X_LPARAM)
254 #  define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
255 #  define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
256 #endif
257 #ifdef _WIN32_WCE
258 #  ifndef WM_NCACTIVATE
259 #    define WM_NCACTIVATE 0x86
260 #  endif
261 #endif
262
263 // The values below should never change. Note that none of the usual
264 // WM_...FIRST & WM_...LAST values are in the list, as they normally have other
265 // WM_... representations
266 struct KnownWM {
267     uint WM;
268     const char* str;
269 } knownWM[] =
270 {{ 0x0000, "WM_NULL" },
271  { 0x0001, "WM_CREATE" },
272  { 0x0002, "WM_DESTROY" },
273  { 0x0003, "WM_MOVE" },
274  { 0x0005, "WM_SIZE" },
275  { 0x0006, "WM_ACTIVATE" },
276  { 0x0007, "WM_SETFOCUS" },
277  { 0x0008, "WM_KILLFOCUS" },
278  { 0x000A, "WM_ENABLE" },
279  { 0x000B, "WM_SETREDRAW" },
280  { 0x000C, "WM_SETTEXT" },
281  { 0x000D, "WM_GETTEXT" },
282  { 0x000E, "WM_GETTEXTLENGTH" },
283  { 0x000F, "WM_PAINT" },
284  { 0x0010, "WM_CLOSE" },
285  { 0x0011, "WM_QUERYENDSESSION" },
286  { 0x0013, "WM_QUERYOPEN" },
287  { 0x0016, "WM_ENDSESSION" },
288  { 0x0012, "WM_QUIT" },
289  { 0x0014, "WM_ERASEBKGND" },
290  { 0x0015, "WM_SYSCOLORCHANGE" },
291  { 0x0018, "WM_SHOWWINDOW" },
292  { 0x001A, "WM_WININICHANGE" },
293  { 0x001B, "WM_DEVMODECHANGE" },
294  { 0x001C, "WM_ACTIVATEAPP" },
295  { 0x001D, "WM_FONTCHANGE" },
296  { 0x001E, "WM_TIMECHANGE" },
297  { 0x001F, "WM_CANCELMODE" },
298  { 0x0020, "WM_SETCURSOR" },
299  { 0x0021, "WM_MOUSEACTIVATE" },
300  { 0x0022, "WM_CHILDACTIVATE" },
301  { 0x0023, "WM_QUEUESYNC" },
302  { 0x0024, "WM_GETMINMAXINFO" },
303  { 0x0026, "WM_PAINTICON" },
304  { 0x0027, "WM_ICONERASEBKGND" },
305  { 0x0028, "WM_NEXTDLGCTL" },
306  { 0x002A, "WM_SPOOLERSTATUS" },
307  { 0x002B, "WM_DRAWITEM" },
308  { 0x002C, "WM_MEASUREITEM" },
309  { 0x002D, "WM_DELETEITEM" },
310  { 0x002E, "WM_VKEYTOITEM" },
311  { 0x002F, "WM_CHARTOITEM" },
312  { 0x0030, "WM_SETFONT" },
313  { 0x0031, "WM_GETFONT" },
314  { 0x0032, "WM_SETHOTKEY" },
315  { 0x0033, "WM_GETHOTKEY" },
316  { 0x0037, "WM_QUERYDRAGICON" },
317  { 0x0039, "WM_COMPAREITEM" },
318  { 0x003D, "WM_GETOBJECT" },
319  { 0x0041, "WM_COMPACTING" },
320  { 0x0044, "WM_COMMNOTIFY" },
321  { 0x0046, "WM_WINDOWPOSCHANGING" },
322  { 0x0047, "WM_WINDOWPOSCHANGED" },
323  { 0x0048, "WM_POWER" },
324  { 0x004A, "WM_COPYDATA" },
325  { 0x004B, "WM_CANCELJOURNAL" },
326  { 0x004E, "WM_NOTIFY" },
327  { 0x0050, "WM_INPUTLANGCHANGEREQUEST" },
328  { 0x0051, "WM_INPUTLANGCHANGE" },
329  { 0x0052, "WM_TCARD" },
330  { 0x0053, "WM_HELP" },
331  { 0x0054, "WM_USERCHANGED" },
332  { 0x0055, "WM_NOTIFYFORMAT" },
333  { 0x007B, "WM_CONTEXTMENU" },
334  { 0x007C, "WM_STYLECHANGING" },
335  { 0x007D, "WM_STYLECHANGED" },
336  { 0x007E, "WM_DISPLAYCHANGE" },
337  { 0x007F, "WM_GETICON" },
338  { 0x0080, "WM_SETICON" },
339  { 0x0081, "WM_NCCREATE" },
340  { 0x0082, "WM_NCDESTROY" },
341  { 0x0083, "WM_NCCALCSIZE" },
342  { 0x0084, "WM_NCHITTEST" },
343  { 0x0085, "WM_NCPAINT" },
344  { 0x0086, "WM_NCACTIVATE" },
345  { 0x0087, "WM_GETDLGCODE" },
346  { 0x0088, "WM_SYNCPAINT" },
347  { 0x00A0, "WM_NCMOUSEMOVE" },
348  { 0x00A1, "WM_NCLBUTTONDOWN" },
349  { 0x00A2, "WM_NCLBUTTONUP" },
350  { 0x00A3, "WM_NCLBUTTONDBLCLK" },
351  { 0x00A4, "WM_NCRBUTTONDOWN" },
352  { 0x00A5, "WM_NCRBUTTONUP" },
353  { 0x00A6, "WM_NCRBUTTONDBLCLK" },
354  { 0x00A7, "WM_NCMBUTTONDOWN" },
355  { 0x00A8, "WM_NCMBUTTONUP" },
356  { 0x00A9, "WM_NCMBUTTONDBLCLK" },
357  { 0x00AB, "WM_NCXBUTTONDOWN" },
358  { 0x00AC, "WM_NCXBUTTONUP" },
359  { 0x00AD, "WM_NCXBUTTONDBLCLK" },
360  { 0x00FF, "WM_INPUT" },
361  { 0x0100, "WM_KEYDOWN" },
362  { 0x0101, "WM_KEYUP" },
363  { 0x0102, "WM_CHAR" },
364  { 0x0103, "WM_DEADCHAR" },
365  { 0x0104, "WM_SYSKEYDOWN" },
366  { 0x0105, "WM_SYSKEYUP" },
367  { 0x0106, "WM_SYSCHAR" },
368  { 0x0107, "WM_SYSDEADCHAR" },
369  { 0x0109, "WM_UNICHAR" },
370  { 0x010D, "WM_IME_STARTCOMPOSITION" },
371  { 0x010E, "WM_IME_ENDCOMPOSITION" },
372  { 0x010F, "WM_IME_COMPOSITION" },
373  { 0x0110, "WM_INITDIALOG" },
374  { 0x0111, "WM_COMMAND" },
375  { 0x0112, "WM_SYSCOMMAND" },
376  { 0x0113, "WM_TIMER" },
377  { 0x0114, "WM_HSCROLL" },
378  { 0x0115, "WM_VSCROLL" },
379  { 0x0116, "WM_INITMENU" },
380  { 0x0117, "WM_INITMENUPOPUP" },
381  { 0x011F, "WM_MENUSELECT" },
382  { 0x0120, "WM_MENUCHAR" },
383  { 0x0121, "WM_ENTERIDLE" },
384  { 0x0122, "WM_MENURBUTTONUP" },
385  { 0x0123, "WM_MENUDRAG" },
386  { 0x0124, "WM_MENUGETOBJECT" },
387  { 0x0125, "WM_UNINITMENUPOPUP" },
388  { 0x0126, "WM_MENUCOMMAND" },
389  { 0x0127, "WM_CHANGEUISTATE" },
390  { 0x0128, "WM_UPDATEUISTATE" },
391  { 0x0129, "WM_QUERYUISTATE" },
392  { 0x0132, "WM_CTLCOLORMSGBOX" },
393  { 0x0133, "WM_CTLCOLOREDIT" },
394  { 0x0134, "WM_CTLCOLORLISTBOX" },
395  { 0x0135, "WM_CTLCOLORBTN" },
396  { 0x0136, "WM_CTLCOLORDLG" },
397  { 0x0137, "WM_CTLCOLORSCROLLBAR" },
398  { 0x0138, "WM_CTLCOLORSTATIC" },
399  { 0x0200, "WM_MOUSEMOVE" },
400  { 0x0201, "WM_LBUTTONDOWN" },
401  { 0x0202, "WM_LBUTTONUP" },
402  { 0x0203, "WM_LBUTTONDBLCLK" },
403  { 0x0204, "WM_RBUTTONDOWN" },
404  { 0x0205, "WM_RBUTTONUP" },
405  { 0x0206, "WM_RBUTTONDBLCLK" },
406  { 0x0207, "WM_MBUTTONDOWN" },
407  { 0x0208, "WM_MBUTTONUP" },
408  { 0x0209, "WM_MBUTTONDBLCLK" },
409  { 0x020A, "WM_MOUSEWHEEL" },
410  { 0x020B, "WM_XBUTTONDOWN" },
411  { 0x020C, "WM_XBUTTONUP" },
412  { 0x020D, "WM_XBUTTONDBLCLK" },
413  { 0x020E, "WM_MOUSEHWHEEL" },
414  { 0x0210, "WM_PARENTNOTIFY" },
415  { 0x0211, "WM_ENTERMENULOOP" },
416  { 0x0212, "WM_EXITMENULOOP" },
417  { 0x0213, "WM_NEXTMENU" },
418  { 0x0214, "WM_SIZING" },
419  { 0x0215, "WM_CAPTURECHANGED" },
420  { 0x0216, "WM_MOVING" },
421  { 0x0218, "WM_POWERBROADCAST" },
422  { 0x0219, "WM_DEVICECHANGE" },
423  { 0x0220, "WM_MDICREATE" },
424  { 0x0221, "WM_MDIDESTROY" },
425  { 0x0222, "WM_MDIACTIVATE" },
426  { 0x0223, "WM_MDIRESTORE" },
427  { 0x0224, "WM_MDINEXT" },
428  { 0x0225, "WM_MDIMAXIMIZE" },
429  { 0x0226, "WM_MDITILE" },
430  { 0x0227, "WM_MDICASCADE" },
431  { 0x0228, "WM_MDIICONARRANGE" },
432  { 0x0229, "WM_MDIGETACTIVE" },
433  { 0x0230, "WM_MDISETMENU" },
434  { 0x0231, "WM_ENTERSIZEMOVE" },
435  { 0x0232, "WM_EXITSIZEMOVE" },
436  { 0x0233, "WM_DROPFILES" },
437  { 0x0234, "WM_MDIREFRESHMENU" },
438  { 0x0281, "WM_IME_SETCONTEXT" },
439  { 0x0282, "WM_IME_NOTIFY" },
440  { 0x0283, "WM_IME_CONTROL" },
441  { 0x0284, "WM_IME_COMPOSITIONFULL" },
442  { 0x0285, "WM_IME_SELECT" },
443  { 0x0286, "WM_IME_CHAR" },
444  { 0x0288, "WM_IME_REQUEST" },
445  { 0x0290, "WM_IME_KEYDOWN" },
446  { 0x0291, "WM_IME_KEYUP" },
447  { 0x02A0, "WM_NCMOUSEHOVER" },
448  { 0x02A1, "WM_MOUSEHOVER" },
449  { 0x02A2, "WM_NCMOUSELEAVE" },
450  { 0x02A3, "WM_MOUSELEAVE" },
451  { 0x02B1, "WM_WTSSESSION_CHANGE" },
452  { 0x02C0, "WM_TABLET_FIRST" },
453  { 0x02C1, "WM_TABLET_FIRST + 1" },
454  { 0x02C2, "WM_TABLET_FIRST + 2" },
455  { 0x02C3, "WM_TABLET_FIRST + 3" },
456  { 0x02C4, "WM_TABLET_FIRST + 4" },
457  { 0x02C5, "WM_TABLET_FIRST + 5" },
458  { 0x02C6, "WM_TABLET_FIRST + 6" },
459  { 0x02C7, "WM_TABLET_FIRST + 7" },
460  { 0x02C8, "WM_TABLET_FIRST + 8" },
461  { 0x02C9, "WM_TABLET_FIRST + 9" },
462  { 0x02CA, "WM_TABLET_FIRST + 10" },
463  { 0x02CB, "WM_TABLET_FIRST + 11" },
464  { 0x02CC, "WM_TABLET_FIRST + 12" },
465  { 0x02CD, "WM_TABLET_FIRST + 13" },
466  { 0x02CE, "WM_TABLET_FIRST + 14" },
467  { 0x02CF, "WM_TABLET_FIRST + 15" },
468  { 0x02D0, "WM_TABLET_FIRST + 16" },
469  { 0x02D1, "WM_TABLET_FIRST + 17" },
470  { 0x02D2, "WM_TABLET_FIRST + 18" },
471  { 0x02D3, "WM_TABLET_FIRST + 19" },
472  { 0x02D4, "WM_TABLET_FIRST + 20" },
473  { 0x02D5, "WM_TABLET_FIRST + 21" },
474  { 0x02D6, "WM_TABLET_FIRST + 22" },
475  { 0x02D7, "WM_TABLET_FIRST + 23" },
476  { 0x02D8, "WM_TABLET_FIRST + 24" },
477  { 0x02D9, "WM_TABLET_FIRST + 25" },
478  { 0x02DA, "WM_TABLET_FIRST + 26" },
479  { 0x02DB, "WM_TABLET_FIRST + 27" },
480  { 0x02DC, "WM_TABLET_FIRST + 28" },
481  { 0x02DD, "WM_TABLET_FIRST + 29" },
482  { 0x02DE, "WM_TABLET_FIRST + 30" },
483  { 0x02DF, "WM_TABLET_LAST" },
484  { 0x0300, "WM_CUT" },
485  { 0x0301, "WM_COPY" },
486  { 0x0302, "WM_PASTE" },
487  { 0x0303, "WM_CLEAR" },
488  { 0x0304, "WM_UNDO" },
489  { 0x0305, "WM_RENDERFORMAT" },
490  { 0x0306, "WM_RENDERALLFORMATS" },
491  { 0x0307, "WM_DESTROYCLIPBOARD" },
492  { 0x0308, "WM_DRAWCLIPBOARD" },
493  { 0x0309, "WM_PAINTCLIPBOARD" },
494  { 0x030A, "WM_VSCROLLCLIPBOARD" },
495  { 0x030B, "WM_SIZECLIPBOARD" },
496  { 0x030C, "WM_ASKCBFORMATNAME" },
497  { 0x030D, "WM_CHANGECBCHAIN" },
498  { 0x030E, "WM_HSCROLLCLIPBOARD" },
499  { 0x030F, "WM_QUERYNEWPALETTE" },
500  { 0x0310, "WM_PALETTEISCHANGING" },
501  { 0x0311, "WM_PALETTECHANGED" },
502  { 0x0312, "WM_HOTKEY" },
503  { 0x0317, "WM_PRINT" },
504  { 0x0318, "WM_PRINTCLIENT" },
505  { 0x0319, "WM_APPCOMMAND" },
506  { 0x031A, "WM_THEMECHANGED" },
507  { 0x0358, "WM_HANDHELDFIRST" },
508  { 0x0359, "WM_HANDHELDFIRST + 1" },
509  { 0x035A, "WM_HANDHELDFIRST + 2" },
510  { 0x035B, "WM_HANDHELDFIRST + 3" },
511  { 0x035C, "WM_HANDHELDFIRST + 4" },
512  { 0x035D, "WM_HANDHELDFIRST + 5" },
513  { 0x035E, "WM_HANDHELDFIRST + 6" },
514  { 0x035F, "WM_HANDHELDLAST" },
515  { 0x0360, "WM_AFXFIRST" },
516  { 0x0361, "WM_AFXFIRST + 1" },
517  { 0x0362, "WM_AFXFIRST + 2" },
518  { 0x0363, "WM_AFXFIRST + 3" },
519  { 0x0364, "WM_AFXFIRST + 4" },
520  { 0x0365, "WM_AFXFIRST + 5" },
521  { 0x0366, "WM_AFXFIRST + 6" },
522  { 0x0367, "WM_AFXFIRST + 7" },
523  { 0x0368, "WM_AFXFIRST + 8" },
524  { 0x0369, "WM_AFXFIRST + 9" },
525  { 0x036A, "WM_AFXFIRST + 10" },
526  { 0x036B, "WM_AFXFIRST + 11" },
527  { 0x036C, "WM_AFXFIRST + 12" },
528  { 0x036D, "WM_AFXFIRST + 13" },
529  { 0x036E, "WM_AFXFIRST + 14" },
530  { 0x036F, "WM_AFXFIRST + 15" },
531  { 0x0370, "WM_AFXFIRST + 16" },
532  { 0x0371, "WM_AFXFIRST + 17" },
533  { 0x0372, "WM_AFXFIRST + 18" },
534  { 0x0373, "WM_AFXFIRST + 19" },
535  { 0x0374, "WM_AFXFIRST + 20" },
536  { 0x0375, "WM_AFXFIRST + 21" },
537  { 0x0376, "WM_AFXFIRST + 22" },
538  { 0x0377, "WM_AFXFIRST + 23" },
539  { 0x0378, "WM_AFXFIRST + 24" },
540  { 0x0379, "WM_AFXFIRST + 25" },
541  { 0x037A, "WM_AFXFIRST + 26" },
542  { 0x037B, "WM_AFXFIRST + 27" },
543  { 0x037C, "WM_AFXFIRST + 28" },
544  { 0x037D, "WM_AFXFIRST + 29" },
545  { 0x037E, "WM_AFXFIRST + 30" },
546  { 0x037F, "WM_AFXLAST" },
547  { 0x0380, "WM_PENWINFIRST" },
548  { 0x0381, "WM_PENWINFIRST + 1" },
549  { 0x0382, "WM_PENWINFIRST + 2" },
550  { 0x0383, "WM_PENWINFIRST + 3" },
551  { 0x0384, "WM_PENWINFIRST + 4" },
552  { 0x0385, "WM_PENWINFIRST + 5" },
553  { 0x0386, "WM_PENWINFIRST + 6" },
554  { 0x0387, "WM_PENWINFIRST + 7" },
555  { 0x0388, "WM_PENWINFIRST + 8" },
556  { 0x0389, "WM_PENWINFIRST + 9" },
557  { 0x038A, "WM_PENWINFIRST + 10" },
558  { 0x038B, "WM_PENWINFIRST + 11" },
559  { 0x038C, "WM_PENWINFIRST + 12" },
560  { 0x038D, "WM_PENWINFIRST + 13" },
561  { 0x038E, "WM_PENWINFIRST + 14" },
562  { 0x038F, "WM_PENWINLAST" },
563  { 0x0400, "WM_USER" },
564  { 0x8000, "WM_APP" },
565  { 0,0 }}; // End of known messages
566
567 // Looks up the WM_ message in the table above
568 static const char* findWMstr(uint msg)
569 {
570     uint i = 0;
571     const char* result = 0;
572     // Known WM_'s
573     while (knownWM[i].str && (knownWM[i].WM != msg))
574         ++i;
575     result = knownWM[i].str;
576     return result;
577 };
578
579 // Convenience function for converting flags and values into readable strings
580 struct FLAG_STRING_STRUCT
581 {
582     uint value;
583     const char* str;
584 };
585
586 FLAG_STRING_STRUCT FLAG_STRING(uint value = 0, const char *c = 0)
587 {
588     FLAG_STRING_STRUCT s = {value, c};
589     return s;
590 }
591
592 #define FLGSTR(x) FLAG_STRING(x, #x)
593
594 // Returns an ORed (" | ") together string for the flags active in the actual
595 // value. (...) must consist of FLAG_STRING, with a FLAG_STRING() as the last
596 // value in the list passed to the function
597 QString flagCheck(uint actual, ...)
598 {
599     va_list ap;
600     va_start(ap, actual);
601
602     QString result;
603     int count = 0;
604     FLAG_STRING_STRUCT v;
605     while((v=va_arg(ap,FLAG_STRING_STRUCT)).str) {
606         if ((actual & v.value) == v.value) {
607             if (count++)
608                 result += QLatin1String(" | ");
609             result += QString::fromLatin1(v.str);
610         }
611     }
612     va_end(ap);
613     return result;
614 };
615
616 // Returns the string representation of the value in 'actual'. (...) must
617 // consist of FLAG_STRING, with a FLAG_STRING() as the last value in the list
618 // passed to the function
619 QString valueCheck(uint actual, ...)
620 {
621     va_list ap;
622     va_start(ap, actual);
623
624     QString result;
625     FLAG_STRING_STRUCT v;
626     while((v=va_arg(ap,FLAG_STRING_STRUCT)).str && (actual != v.value))
627         ;
628     result = QString::fromLatin1(v.str);
629
630     va_end(ap);
631     return result;
632 };
633
634 #ifdef Q_CC_BOR
635
636 QString decodeMSG(const MSG& msg)
637 {
638     return QString::fromLatin1("THis is not supported on Borland");
639 }
640
641 #else
642
643 // Returns a "human readable" string representation of the MSG and the
644 // information it points to
645 QString decodeMSG(const MSG& msg)
646 {
647     const WPARAM wParam = msg.wParam;
648     const LPARAM lParam = msg.lParam;
649     QString wmmsg = QString::fromLatin1(findWMstr(msg.message));
650     // Unknown WM_, so use number
651     if (wmmsg.isEmpty())
652         wmmsg = QString::fromLatin1("WM_(%1)").arg(msg.message);
653
654     QString rawParameters;
655     rawParameters.sprintf("hwnd(0x%p) ", (void *)msg.hwnd);
656
657     // Custom WM_'s
658     if (msg.message > WM_APP)
659         wmmsg = QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
660     else if (msg.message > WM_USER)
661         wmmsg = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
662
663     QString parameters;
664     switch (msg.message) {
665 #ifdef WM_ACTIVATE
666         case WM_ACTIVATE:
667             {
668                 QString activation = valueCheck(wParam,
669                                                 FLAG_STRING(WA_ACTIVE,      "Activate"),
670                                                 FLAG_STRING(WA_INACTIVE,    "Deactivate"),
671                                                 FLAG_STRING(WA_CLICKACTIVE, "Activate by mouseclick"),
672                                                 FLAG_STRING());
673                 parameters.sprintf("%s Hwnd (0x%p)", activation.toLatin1().data(), (void *)msg.hwnd);
674             }
675             break;
676 #endif
677 #ifdef WM_CAPTURECHANGED
678         case WM_CAPTURECHANGED:
679             parameters.sprintf("Hwnd gaining capture (0x%p)", (void *)lParam);
680             break;
681 #endif
682 #ifdef WM_CREATE
683         case WM_CREATE:
684             {
685                 LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
686                 QString styles = flagCheck(lpcs->style,
687                                            FLGSTR(WS_BORDER),
688                                            FLGSTR(WS_CAPTION),
689                                            FLGSTR(WS_CHILD),
690                                            FLGSTR(WS_CLIPCHILDREN),
691                                            FLGSTR(WS_CLIPSIBLINGS),
692                                            FLGSTR(WS_DISABLED),
693                                            FLGSTR(WS_DLGFRAME),
694                                            FLGSTR(WS_GROUP),
695                                            FLGSTR(WS_HSCROLL),
696                                            FLGSTR(WS_OVERLAPPED),
697 #if defined(WS_OVERLAPPEDWINDOW) && (WS_OVERLAPPEDWINDOW != 0)
698                                            FLGSTR(WS_OVERLAPPEDWINDOW),
699 #endif
700 #ifdef WS_ICONIC
701                                            FLGSTR(WS_ICONIC),
702 #endif
703                                            FLGSTR(WS_MAXIMIZE),
704                                            FLGSTR(WS_MAXIMIZEBOX),
705                                            FLGSTR(WS_MINIMIZE),
706                                            FLGSTR(WS_MINIMIZEBOX),
707                                            FLGSTR(WS_OVERLAPPEDWINDOW),
708                                            FLGSTR(WS_POPUP),
709 #ifdef WS_POPUPWINDOW
710                                            FLGSTR(WS_POPUPWINDOW),
711 #endif
712                                            FLGSTR(WS_SIZEBOX),
713                                            FLGSTR(WS_SYSMENU),
714                                            FLGSTR(WS_TABSTOP),
715                                            FLGSTR(WS_THICKFRAME),
716 #ifdef WS_TILED
717                                            FLGSTR(WS_TILED),
718 #endif
719 #ifdef WS_TILEDWINDOW
720                                            FLGSTR(WS_TILEDWINDOW),
721 #endif
722                                            FLGSTR(WS_VISIBLE),
723                                            FLGSTR(WS_VSCROLL),
724                                            FLAG_STRING());
725
726                 QString exStyles = flagCheck(lpcs->dwExStyle,
727 #ifdef WS_EX_ACCEPTFILES
728                                            FLGSTR(WS_EX_ACCEPTFILES),
729 #endif
730 #ifdef WS_EX_APPWINDOW
731                                            FLGSTR(WS_EX_APPWINDOW),
732 #endif
733                                            FLGSTR(WS_EX_CLIENTEDGE),
734                                            FLGSTR(WS_EX_DLGMODALFRAME),
735 #ifdef WS_EX_LEFT
736                                            FLGSTR(WS_EX_LEFT),
737 #endif
738                                            FLGSTR(WS_EX_LEFTSCROLLBAR),
739 #ifdef WS_EX_LTRREADING
740                                            FLGSTR(WS_EX_LTRREADING),
741 #endif
742 #ifdef WS_EX_MDICHILD
743                                            FLGSTR(WS_EX_MDICHILD),
744 #endif
745 #ifdef WS_EX_NOACTIVATE
746                                            FLGSTR(WS_EX_NOACTIVATE),
747 #endif
748 #ifdef WS_EX_NOANIMATION
749                                            FLGSTR(WS_EX_NOANIMATION),
750 #endif
751                                            FLGSTR(WS_EX_NOPARENTNOTIFY),
752                                            FLGSTR(WS_EX_OVERLAPPEDWINDOW),
753 #ifdef WS_EX_PALETTEWINDOW
754                                            FLGSTR(WS_EX_PALETTEWINDOW),
755 #endif
756 #ifdef WS_EX_RIGHT
757                                            FLGSTR(WS_EX_RIGHT),
758 #endif
759 #ifdef WS_EX_RIGHTSCROLLBAR
760                                            FLGSTR(WS_EX_RIGHTSCROLLBAR),
761 #endif
762 #ifdef WS_EX_RTLREADING
763                                            FLGSTR(WS_EX_RTLREADING),
764 #endif
765                                            FLGSTR(WS_EX_STATICEDGE),
766                                            FLGSTR(WS_EX_TOOLWINDOW),
767                                            FLGSTR(WS_EX_TOPMOST),
768 #ifdef WS_EX_TRANSPARENT
769                                            FLGSTR(WS_EX_TRANSPARENT),
770 #endif
771                                            FLGSTR(WS_EX_WINDOWEDGE),
772 #ifdef WS_EX_CAPTIONOKBTN
773                                            FLGSTR(WS_EX_CAPTIONOKBTN),
774 #endif
775                                            FLAG_STRING());
776
777                 QString className;
778                 if (lpcs->lpszClass != 0) {
779                     if (HIWORD(lpcs->lpszClass) == 0) // Atom
780                         className = QString::number(LOWORD(lpcs->lpszClass), 16);
781                     else                              // String
782                         className = QString((QChar*)lpcs->lpszClass,
783                                             (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszClass)));
784                 }
785
786                 QString windowName;
787                 if (lpcs->lpszName != 0)
788                     windowName = QString((QChar*)lpcs->lpszName,
789                                          (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszName)));
790
791                 parameters.sprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
792                                    lpcs->x, lpcs->y, lpcs->cx, lpcs->cy, className.toLatin1().data(),
793                                    windowName.toLatin1().data(), (void *)lpcs->hwndParent,
794                                    styles.toLatin1().data(), exStyles.toLatin1().data());
795             }
796             break;
797 #endif
798 #ifdef WM_DESTROY
799         case WM_DESTROY:
800             parameters.sprintf("Destroy hwnd (0x%p)", (void *)msg.hwnd);
801             break;
802 #endif
803 #ifdef WM_IME_NOTIFY
804         case WM_IME_NOTIFY:
805             {
806                 QString imnCommand = valueCheck(wParam,
807                                             FLGSTR(IMN_CHANGECANDIDATE),
808                                             FLGSTR(IMN_CLOSECANDIDATE),
809                                             FLGSTR(IMN_CLOSESTATUSWINDOW),
810                                             FLGSTR(IMN_GUIDELINE),
811                                             FLGSTR(IMN_OPENCANDIDATE),
812                                             FLGSTR(IMN_OPENSTATUSWINDOW),
813                                             FLGSTR(IMN_SETCANDIDATEPOS),
814                                             FLGSTR(IMN_SETCOMPOSITIONFONT),
815                                             FLGSTR(IMN_SETCOMPOSITIONWINDOW),
816                                             FLGSTR(IMN_SETCONVERSIONMODE),
817                                             FLGSTR(IMN_SETOPENSTATUS),
818                                             FLGSTR(IMN_SETSENTENCEMODE),
819                                             FLGSTR(IMN_SETSTATUSWINDOWPOS),
820                                             FLAG_STRING());
821                 parameters.sprintf("Command(%s : 0x%p)", imnCommand.toLatin1().data(), (void *)lParam);
822             }
823             break;
824 #endif
825 #ifdef WM_IME_SETCONTEXT
826         case WM_IME_SETCONTEXT:
827             {
828                 bool fSet = (BOOL)wParam;
829                 DWORD fShow = (DWORD)lParam;
830                 QString showFlgs = flagCheck(fShow,
831 #ifdef ISC_SHOWUICOMPOSITIONWINDOW
832                                              FLGSTR(ISC_SHOWUICOMPOSITIONWINDOW),
833 #endif
834 #ifdef ISC_SHOWUIGUIDWINDOW
835                                              FLGSTR(ISC_SHOWUIGUIDWINDOW),
836 #endif
837 #ifdef ISC_SHOWUISOFTKBD
838                                              FLGSTR(ISC_SHOWUISOFTKBD),
839 #endif
840                                              FLGSTR(ISC_SHOWUICANDIDATEWINDOW),
841                                              FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 1),
842                                              FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 2),
843                                              FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 3),
844                                              FLAG_STRING());
845                 parameters.sprintf("Input context(%s) Show flags(%s)", (fSet? "Active" : "Inactive"), showFlgs.toLatin1().data());
846             }
847             break;
848 #endif
849 #ifdef WM_KILLFOCUS
850         case WM_KILLFOCUS:
851             parameters.sprintf("Hwnd gaining keyboard focus (0x%p)", (void *)wParam);
852             break;
853 #endif
854 #ifdef WM_CHAR
855         case WM_CHAR:
856 #endif
857 #ifdef WM_IME_CHAR
858         case WM_IME_CHAR:
859 #endif
860 #ifdef WM_KEYDOWN
861         case WM_KEYDOWN:
862 #endif
863 #ifdef WM_KEYUP
864         case WM_KEYUP:
865             {
866                 int nVirtKey     = (int)wParam;
867                 long lKeyData    = (long)lParam;
868                 int repCount     = (lKeyData & 0xffff);        // Bit 0-15
869                 int scanCode     = (lKeyData & 0xf0000) >> 16; // Bit 16-23
870                 bool contextCode = (lKeyData && 0x20000000);   // Bit 29
871                 bool prevState   = (lKeyData && 0x40000000);   // Bit 30
872                 bool transState  = (lKeyData && 0x80000000);   // Bit 31
873                 parameters.sprintf("Virual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
874                                    nVirtKey, scanCode, repCount, contextCode, prevState, transState);
875             }
876             break;
877 #endif
878 #ifdef WM_INPUTLANGCHANGE
879         case WM_INPUTLANGCHANGE:
880             parameters = QLatin1String("Keyboard layout changed");
881             break;
882 #endif // WM_INPUTLANGCHANGE
883 #ifdef WM_NCACTIVATE
884         case WM_NCACTIVATE:
885             {
886             parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
887             }
888             break;
889 #endif
890 #ifdef WM_MOUSEACTIVATE
891         case WM_MOUSEACTIVATE:
892             {
893                 QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
894                 parameters.sprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)", (void *)wParam, LOWORD(lParam), mouseMsg.toLatin1().data());
895             }
896             break;
897 #endif
898 #ifdef WM_MOUSELEAVE
899         case WM_MOUSELEAVE:
900             break; // wParam & lParam not used
901 #endif
902 #ifdef WM_MOUSEHOVER
903         case WM_MOUSEHOVER:
904 #endif
905 #ifdef WM_MOUSEWHEEL
906         case WM_MOUSEWHEEL:
907 #endif
908 #ifdef WM_MOUSEHWHEEL
909         case WM_MOUSEHWHEEL:
910 #endif
911 #ifdef WM_LBUTTONDBLCLK
912         case WM_LBUTTONDBLCLK:
913 #endif
914 #ifdef WM_LBUTTONDOWN
915         case WM_LBUTTONDOWN:
916 #endif
917 #ifdef WM_LBUTTONUP
918         case WM_LBUTTONUP:
919 #endif
920 #ifdef WM_MBUTTONDBLCLK
921         case WM_MBUTTONDBLCLK:
922 #endif
923 #ifdef WM_MBUTTONDOWN
924         case WM_MBUTTONDOWN:
925 #endif
926 #ifdef WM_MBUTTONUP
927         case WM_MBUTTONUP:
928 #endif
929 #ifdef WM_RBUTTONDBLCLK
930         case WM_RBUTTONDBLCLK:
931 #endif
932 #ifdef WM_RBUTTONDOWN
933         case WM_RBUTTONDOWN:
934 #endif
935 #ifdef WM_RBUTTONUP
936         case WM_RBUTTONUP:
937 #endif
938 #ifdef WM_MOUSEMOVE
939         case WM_MOUSEMOVE:
940             {
941                 QString vrtKeys = flagCheck(wParam,
942                                             FLGSTR(MK_CONTROL),
943                                             FLGSTR(MK_LBUTTON),
944                                             FLGSTR(MK_MBUTTON),
945                                             FLGSTR(MK_RBUTTON),
946                                             FLGSTR(MK_SHIFT),
947 #ifdef MK_XBUTTON1
948                                             FLGSTR(MK_XBUTTON1),
949 #endif
950 #ifdef MK_XBUTTON2
951                                             FLGSTR(MK_XBUTTON2),
952 #endif
953                                             FLAG_STRING());
954                 parameters.sprintf("x,y(%4d,%4d) Virtual Keys(%s)", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), vrtKeys.toLatin1().data());
955             }
956             break;
957 #endif
958 #ifdef WM_MOVE
959         case WM_MOVE:
960             parameters.sprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
961             break;
962 #endif
963 #if defined(WM_PAINT) && defined(WM_ERASEBKGND)
964         case WM_ERASEBKGND:
965         case WM_PAINT:
966             parameters.sprintf("hdc(0x%p)", (void *)wParam);
967             break;
968 #endif
969 #ifdef WM_QUERYNEWPALETTE
970         case WM_QUERYNEWPALETTE:
971             break; // lParam & wParam are unused
972 #endif
973 #ifdef WM_SETCURSOR
974         case WM_SETCURSOR:
975             {
976                 QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
977                 parameters.sprintf("HitTestCode(0x%x) MouseMsg(%s)", LOWORD(lParam), mouseMsg.toLatin1().data());
978             }
979             break;
980 #endif
981 #ifdef WM_SETFOCUS
982         case WM_SETFOCUS:
983             parameters.sprintf("Lost Focus (0x%p)", (void *)wParam);
984             break;
985 #endif
986 #ifdef WM_SETTEXT
987         case WM_SETTEXT:
988             parameters.sprintf("Set Text (%s)", QString((QChar*)lParam, (int)wcslen(reinterpret_cast<const wchar_t *>(lParam))).toLatin1().data()); //Unicode string
989             break;
990 #endif
991 #ifdef WM_SIZE
992         case WM_SIZE:
993             {
994                 QString showMode = valueCheck(wParam,
995                                               FLGSTR(SIZE_MAXHIDE),
996                                               FLGSTR(SIZE_MAXIMIZED),
997                                               FLGSTR(SIZE_MAXSHOW),
998                                               FLGSTR(SIZE_MINIMIZED),
999                                               FLGSTR(SIZE_RESTORED),
1000                                               FLAG_STRING());
1001
1002                 parameters.sprintf("w,h(%4d,%4d) showmode(%s)", LOWORD(lParam), HIWORD(lParam), showMode.toLatin1().data());
1003             }
1004             break;
1005 #endif
1006 #ifdef WM_WINDOWPOSCHANGED
1007         case WM_WINDOWPOSCHANGED:
1008             {
1009                 LPWINDOWPOS winPos = (LPWINDOWPOS)lParam;
1010                 if (!winPos)
1011                     break;
1012                 QString hwndAfter = valueCheck(quint64(winPos->hwndInsertAfter),
1013                                           FLAG_STRING((qptrdiff)HWND_BOTTOM,    "HWND_BOTTOM"),
1014                                           FLAG_STRING((qptrdiff)HWND_NOTOPMOST, "HWND_NOTOPMOST"),
1015                                           FLAG_STRING((qptrdiff)HWND_TOP,       "HWND_TOP"),
1016                                           FLAG_STRING((qptrdiff)HWND_TOPMOST,   "HWND_TOPMOST"),
1017                                           FLAG_STRING());
1018                 if (hwndAfter.isEmpty())
1019                     hwndAfter = QString::number((quintptr)winPos->hwndInsertAfter, 16);
1020                 QString flags = flagCheck(winPos->flags,
1021                                           FLGSTR(SWP_DRAWFRAME),
1022                                           FLGSTR(SWP_FRAMECHANGED),
1023                                           FLGSTR(SWP_HIDEWINDOW),
1024                                           FLGSTR(SWP_NOACTIVATE),
1025 #ifdef SWP_NOCOPYBITS
1026                                           FLGSTR(SWP_NOCOPYBITS),
1027 #endif
1028                                           FLGSTR(SWP_NOMOVE),
1029                                           FLGSTR(SWP_NOOWNERZORDER),
1030                                           FLGSTR(SWP_NOREDRAW),
1031                                           FLGSTR(SWP_NOREPOSITION),
1032 #ifdef SWP_NOSENDCHANGING
1033                                           FLGSTR(SWP_NOSENDCHANGING),
1034 #endif
1035                                           FLGSTR(SWP_NOSIZE),
1036                                           FLGSTR(SWP_NOZORDER),
1037                                           FLGSTR(SWP_SHOWWINDOW),
1038                                           FLAG_STRING());
1039                 parameters.sprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(%s)", winPos->x, winPos->y, winPos->cx, winPos->cy, flags.toLatin1().data(), hwndAfter.toLatin1().data());
1040             }
1041             break;
1042 #endif
1043         default:
1044             parameters.sprintf("wParam(0x%p) lParam(0x%p)", (void *)wParam, (void *)lParam);
1045             break;
1046     }
1047     // Yes, we want to give the WM_ names 20 chars of space before showing the
1048     // decoded message, since some of the common messages are quite long, and
1049     // we don't want the decoded information to vary in output position
1050     QString message = QString::fromLatin1("%1: ").arg(wmmsg, 20);
1051     message += rawParameters;
1052     message += parameters;
1053     return message;
1054 }
1055
1056 #endif
1057
1058 QDebug operator<<(QDebug dbg, const MSG &msg)
1059 {
1060     dbg << decodeMSG(msg);
1061     return dbg.nospace();
1062 }
1063 #endif
1064
1065 QT_END_NAMESPACE