1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
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(int 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_NCACTIVATE
879
        case WM_NCACTIVATE:
880
            {
881
            parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
882
            }
883
            break;
884
#endif
885
#ifdef WM_MOUSEACTIVATE
886
        case WM_MOUSEACTIVATE:
887
            {
888
                QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
889
                parameters.sprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)", (void *)wParam, LOWORD(lParam), mouseMsg.toLatin1().data());
890
            }
891
            break;
892
#endif
893
#ifdef WM_MOUSELEAVE
894
        case WM_MOUSELEAVE:
895
            break; // wParam & lParam not used
896
#endif
897
#ifdef WM_MOUSEHOVER
898
        case WM_MOUSEHOVER:
899
#endif
900
#ifdef WM_MOUSEWHEEL
901
        case WM_MOUSEWHEEL:
902
#endif
903
#ifdef WM_MOUSEHWHEEL
904
        case WM_MOUSEHWHEEL:
905
#endif
906
#ifdef WM_LBUTTONDBLCLK
907
        case WM_LBUTTONDBLCLK:
908
#endif
909
#ifdef WM_LBUTTONDOWN
910
        case WM_LBUTTONDOWN:
911
#endif
912
#ifdef WM_LBUTTONUP
913
        case WM_LBUTTONUP:
914
#endif
915
#ifdef WM_MBUTTONDBLCLK
916
        case WM_MBUTTONDBLCLK:
917
#endif
918
#ifdef WM_MBUTTONDOWN
919
        case WM_MBUTTONDOWN:
920
#endif
921
#ifdef WM_MBUTTONUP
922
        case WM_MBUTTONUP:
923
#endif
924
#ifdef WM_RBUTTONDBLCLK
925
        case WM_RBUTTONDBLCLK:
926
#endif
927
#ifdef WM_RBUTTONDOWN
928
        case WM_RBUTTONDOWN:
929
#endif
930
#ifdef WM_RBUTTONUP
931
        case WM_RBUTTONUP:
932
#endif
933
#ifdef WM_MOUSEMOVE
934
        case WM_MOUSEMOVE:
935
            {
936
                QString vrtKeys = flagCheck(wParam,
937
                                            FLGSTR(MK_CONTROL),
938
                                            FLGSTR(MK_LBUTTON),
939
                                            FLGSTR(MK_MBUTTON),
940
                                            FLGSTR(MK_RBUTTON),
941
                                            FLGSTR(MK_SHIFT),
942
#ifdef MK_XBUTTON1
943
                                            FLGSTR(MK_XBUTTON1),
944
#endif
945
#ifdef MK_XBUTTON2
946
                                            FLGSTR(MK_XBUTTON2),
947
#endif
948
                                            FLAG_STRING());
949
                parameters.sprintf("x,y(%4d,%4d) Virtual Keys(%s)", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), vrtKeys.toLatin1().data());
950
            }
951
            break;
952
#endif
953
#ifdef WM_MOVE
954
        case WM_MOVE:
955
            parameters.sprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
956
            break;
957
#endif
958
#if defined(WM_PAINT) && defined(WM_ERASEBKGND)
959
        case WM_ERASEBKGND:
960
        case WM_PAINT:
961
            parameters.sprintf("hdc(0x%p)", (void *)wParam);
962
            break;
963
#endif
964
#ifdef WM_QUERYNEWPALETTE
965
        case WM_QUERYNEWPALETTE:
966
            break; // lParam & wParam are unused
967
#endif
968
#ifdef WM_SETCURSOR
969
        case WM_SETCURSOR:
970
            {
971
                QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
972
                parameters.sprintf("HitTestCode(0x%x) MouseMsg(%s)", LOWORD(lParam), mouseMsg.toLatin1().data());
973
            }
974
            break;
975
#endif
976
#ifdef WM_SETFOCUS
977
        case WM_SETFOCUS:
978
            parameters.sprintf("Lost Focus (0x%p)", (void *)wParam);
979
            break;
980
#endif
981
#ifdef WM_SETTEXT
982
        case WM_SETTEXT:
983
            parameters.sprintf("Set Text (%s)", QString((QChar*)lParam, (int)wcslen(reinterpret_cast<const wchar_t *>(lParam))).toLatin1().data()); //Unicode string
984
            break;
985
#endif
986
#ifdef WM_SIZE
987
        case WM_SIZE:
988
            {
989
                QString showMode = valueCheck(wParam,
990
                                              FLGSTR(SIZE_MAXHIDE),
991
                                              FLGSTR(SIZE_MAXIMIZED),
992
                                              FLGSTR(SIZE_MAXSHOW),
993
                                              FLGSTR(SIZE_MINIMIZED),
994
                                              FLGSTR(SIZE_RESTORED),
995
                                              FLAG_STRING());
996
997
                parameters.sprintf("w,h(%4d,%4d) showmode(%s)", LOWORD(lParam), HIWORD(lParam), showMode.toLatin1().data());
998
            }
999
            break;
1000
#endif
1001
#ifdef WM_WINDOWPOSCHANGED
1002
        case WM_WINDOWPOSCHANGED:
1003
            {
1004
                LPWINDOWPOS winPos = (LPWINDOWPOS)lParam;
1005
                if (!winPos)
1006
                    break;
1007
                QString hwndAfter = valueCheck(quint64(winPos->hwndInsertAfter),
1008
                                          FLAG_STRING((qptrdiff)HWND_BOTTOM,    "HWND_BOTTOM"),
1009
                                          FLAG_STRING((qptrdiff)HWND_NOTOPMOST, "HWND_NOTOPMOST"),
1010
                                          FLAG_STRING((qptrdiff)HWND_TOP,       "HWND_TOP"),
1011
                                          FLAG_STRING((qptrdiff)HWND_TOPMOST,   "HWND_TOPMOST"),
1012
                                          FLAG_STRING());
1013
                if (hwndAfter.isEmpty())
1014
                    hwndAfter = QString::number((quintptr)winPos->hwndInsertAfter, 16);
1015
                QString flags = flagCheck(winPos->flags,
1016
                                          FLGSTR(SWP_DRAWFRAME),
1017
                                          FLGSTR(SWP_FRAMECHANGED),
1018
                                          FLGSTR(SWP_HIDEWINDOW),
1019
                                          FLGSTR(SWP_NOACTIVATE),
1020
#ifdef SWP_NOCOPYBITS
1021
                                          FLGSTR(SWP_NOCOPYBITS),
1022
#endif
1023
                                          FLGSTR(SWP_NOMOVE),
1024
                                          FLGSTR(SWP_NOOWNERZORDER),
1025
                                          FLGSTR(SWP_NOREDRAW),
1026
                                          FLGSTR(SWP_NOREPOSITION),
1027
#ifdef SWP_NOSENDCHANGING
1028
                                          FLGSTR(SWP_NOSENDCHANGING),
1029
#endif
1030
                                          FLGSTR(SWP_NOSIZE),
1031
                                          FLGSTR(SWP_NOZORDER),
1032
                                          FLGSTR(SWP_SHOWWINDOW),
1033
                                          FLAG_STRING());
1034
                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());
1035
            }
1036
            break;
1037
#endif
1038
        default:
1039
            parameters.sprintf("wParam(0x%p) lParam(0x%p)", (void *)wParam, (void *)lParam);
1040
            break;
1041
    }
1042
    // Yes, we want to give the WM_ names 20 chars of space before showing the
1043
    // decoded message, since some of the common messages are quite long, and
1044
    // we don't want the decoded information to vary in output position
1045
    QString message = QString::fromLatin1("%1: ").arg(wmmsg, 20);
1046
    message += rawParameters;
1047
    message += parameters;
1048
    return message;
1049
}
1050
1051
#endif
1052
1053
QDebug operator<<(QDebug dbg, const MSG &msg)
1054
{
1055
    dbg << decodeMSG(msg);
1056
    return dbg.nospace();
1057
}
1058
#endif
1059
1060
QT_END_NAMESPACE