summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcoreapplication_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qcoreapplication_win.cpp')
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp1060
1 files changed, 1060 insertions, 0 deletions
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
new file mode 100644
index 0000000000..a6f43a8900
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -0,0 +1,1060 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qstringlist.h"
+#include "qt_windows.h"
+#include "qvector.h"
+#include "qmutex.h"
+#include "qfileinfo.h"
+#include "qcorecmdlineargs_p.h"
+#include <private/qthread_p.h>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+bool usingWinMain = false; // whether the qWinMain() is used or not
+int appCmdShow = 0;
+
+Q_CORE_EXPORT HINSTANCE qWinAppInst() // get Windows app handle
+{
+ return GetModuleHandle(0);
+}
+
+Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app handle
+{
+ return 0;
+}
+
+Q_CORE_EXPORT int qWinAppCmdShow() // get main window show command
+{
+#if defined(Q_OS_WINCE)
+ return appCmdShow;
+#else
+ STARTUPINFO startupInfo;
+ GetStartupInfo(&startupInfo);
+
+ return (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
+ ? startupInfo.wShowWindow
+ : SW_SHOWDEFAULT;
+#endif
+}
+
+Q_CORE_EXPORT QString qAppFileName() // get application file name
+{
+ // We do MAX_PATH + 2 here, and request with MAX_PATH + 1, so we can handle all paths
+ // up to, and including MAX_PATH size perfectly fine with string termination, as well
+ // as easily detect if the file path is indeed larger than MAX_PATH, in which case we
+ // need to use the heap instead. This is a work-around, since contrary to what the
+ // MSDN documentation states, GetModuleFileName sometimes doesn't set the
+ // ERROR_INSUFFICIENT_BUFFER error number, and we thus cannot rely on this value if
+ // GetModuleFileName(0, buffer, MAX_PATH) == MAX_PATH.
+ // GetModuleFileName(0, buffer, MAX_PATH + 1) == MAX_PATH just means we hit the normal
+ // file path limit, and we handle it normally, if the result is MAX_PATH + 1, we use
+ // heap (even if the result _might_ be exactly MAX_PATH + 1, but that's ok).
+ wchar_t buffer[MAX_PATH + 2];
+ DWORD v = GetModuleFileName(0, buffer, MAX_PATH + 1);
+ buffer[MAX_PATH + 1] = 0;
+
+ if (v == 0)
+ return QString();
+ else if (v <= MAX_PATH)
+ return QString::fromWCharArray(buffer);
+
+ // MAX_PATH sized buffer wasn't large enough to contain the full path, use heap
+ wchar_t *b = 0;
+ int i = 1;
+ size_t size;
+ do {
+ ++i;
+ size = MAX_PATH * i;
+ b = reinterpret_cast<wchar_t *>(realloc(b, (size + 1) * sizeof(wchar_t)));
+ if (b)
+ v = GetModuleFileName(NULL, b, size);
+ } while (b && v == size);
+
+ if (b)
+ *(b + size) = 0;
+ QString res = QString::fromWCharArray(b);
+ free(b);
+
+ return res;
+}
+
+QString QCoreApplicationPrivate::appName() const
+{
+ return QFileInfo(qAppFileName()).baseName();
+}
+
+class QWinMsgHandlerCriticalSection
+{
+ CRITICAL_SECTION cs;
+public:
+ QWinMsgHandlerCriticalSection()
+ { InitializeCriticalSection(&cs); }
+ ~QWinMsgHandlerCriticalSection()
+ { DeleteCriticalSection(&cs); }
+
+ void lock()
+ { EnterCriticalSection(&cs); }
+ void unlock()
+ { LeaveCriticalSection(&cs); }
+};
+
+Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str)
+{
+ Q_UNUSED(t);
+ // OutputDebugString is not threadsafe.
+
+ // cannot use QMutex here, because qWarning()s in the QMutex
+ // implementation may cause this function to recurse
+ static QWinMsgHandlerCriticalSection staticCriticalSection;
+
+ if (!str)
+ str = "(null)";
+
+ staticCriticalSection.lock();
+
+ QString s(QString::fromLocal8Bit(str));
+ s += QLatin1Char('\n');
+ OutputDebugString((wchar_t*)s.utf16());
+
+ staticCriticalSection.unlock();
+}
+
+
+/*****************************************************************************
+ qWinMain() - Initializes Windows. Called from WinMain() in qtmain_win.cpp
+ *****************************************************************************/
+
+#if defined(Q_OS_WINCE)
+Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
+ int cmdShow, int &argc, QVector<char *> &argv)
+#else
+Q_CORE_EXPORT
+void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
+ int cmdShow, int &argc, QVector<char *> &argv)
+#endif
+{
+ static bool already_called = false;
+
+ if (already_called) {
+ qWarning("Qt: Internal error: qWinMain should be called only once");
+ return;
+ }
+ already_called = true;
+ usingWinMain = true;
+
+ // Install default debug handler
+ qInstallMsgHandler(qWinMsgHandler);
+
+ // Create command line
+ argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);
+
+ appCmdShow = cmdShow;
+
+ // Ignore Windows parameters
+ Q_UNUSED(instance);
+ Q_UNUSED(prevInstance);
+}
+
+/*!
+ The message procedure calls this function for every message
+ received. Reimplement this function if you want to process window
+ messages \a msg that are not processed by Qt. If you don't want
+ the event to be processed by Qt, then return true and set \a result
+ to the value that the window procedure should return. Otherwise
+ return false.
+
+ It is only directly addressed messages that are filtered. To
+ handle system wide messages, such as messages from a registered
+ hot key, you need to install an event filter on the event
+ dispatcher, which is returned from
+ QAbstractEventDispatcher::instance().
+*/
+bool QCoreApplication::winEventFilter(MSG *msg, long *result) // Windows event filter
+{
+ Q_UNUSED(msg);
+ Q_UNUSED(result);
+ return false;
+}
+
+void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
+{
+ QThreadData *data = object->d_func()->threadData;
+
+ QMutexLocker locker(&data->postEventList.mutex);
+ if (data->postEventList.size() == 0)
+ return;
+ for (int i = 0; i < data->postEventList.size(); ++i) {
+ const QPostEvent & pe = data->postEventList.at(i);
+ if (pe.receiver == object
+ && pe.event
+ && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
+ && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ const_cast<QPostEvent &>(pe).event = 0;
+ return;
+ }
+ }
+}
+
+#if defined(Q_WS_WIN) && !defined(QT_NO_DEBUG_STREAM)
+/*****************************************************************************
+ Convenience functions for convert WM_* messages into human readable strings,
+ including a nifty QDebug operator<< for simpel QDebug() << msg output.
+ *****************************************************************************/
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <windowsx.h>
+#include "qdebug.h"
+QT_END_INCLUDE_NAMESPACE
+
+#if !defined(GET_X_LPARAM)
+# define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+# define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
+#endif
+#ifdef _WIN32_WCE
+# ifndef WM_NCACTIVATE
+# define WM_NCACTIVATE 0x86
+# endif
+#endif
+
+// The values below should never change. Note that none of the usual
+// WM_...FIRST & WM_...LAST values are in the list, as they normally have other
+// WM_... representations
+struct KnownWM {
+ uint WM;
+ const char* str;
+} knownWM[] =
+{{ 0x0000, "WM_NULL" },
+ { 0x0001, "WM_CREATE" },
+ { 0x0002, "WM_DESTROY" },
+ { 0x0003, "WM_MOVE" },
+ { 0x0005, "WM_SIZE" },
+ { 0x0006, "WM_ACTIVATE" },
+ { 0x0007, "WM_SETFOCUS" },
+ { 0x0008, "WM_KILLFOCUS" },
+ { 0x000A, "WM_ENABLE" },
+ { 0x000B, "WM_SETREDRAW" },
+ { 0x000C, "WM_SETTEXT" },
+ { 0x000D, "WM_GETTEXT" },
+ { 0x000E, "WM_GETTEXTLENGTH" },
+ { 0x000F, "WM_PAINT" },
+ { 0x0010, "WM_CLOSE" },
+ { 0x0011, "WM_QUERYENDSESSION" },
+ { 0x0013, "WM_QUERYOPEN" },
+ { 0x0016, "WM_ENDSESSION" },
+ { 0x0012, "WM_QUIT" },
+ { 0x0014, "WM_ERASEBKGND" },
+ { 0x0015, "WM_SYSCOLORCHANGE" },
+ { 0x0018, "WM_SHOWWINDOW" },
+ { 0x001A, "WM_WININICHANGE" },
+ { 0x001B, "WM_DEVMODECHANGE" },
+ { 0x001C, "WM_ACTIVATEAPP" },
+ { 0x001D, "WM_FONTCHANGE" },
+ { 0x001E, "WM_TIMECHANGE" },
+ { 0x001F, "WM_CANCELMODE" },
+ { 0x0020, "WM_SETCURSOR" },
+ { 0x0021, "WM_MOUSEACTIVATE" },
+ { 0x0022, "WM_CHILDACTIVATE" },
+ { 0x0023, "WM_QUEUESYNC" },
+ { 0x0024, "WM_GETMINMAXINFO" },
+ { 0x0026, "WM_PAINTICON" },
+ { 0x0027, "WM_ICONERASEBKGND" },
+ { 0x0028, "WM_NEXTDLGCTL" },
+ { 0x002A, "WM_SPOOLERSTATUS" },
+ { 0x002B, "WM_DRAWITEM" },
+ { 0x002C, "WM_MEASUREITEM" },
+ { 0x002D, "WM_DELETEITEM" },
+ { 0x002E, "WM_VKEYTOITEM" },
+ { 0x002F, "WM_CHARTOITEM" },
+ { 0x0030, "WM_SETFONT" },
+ { 0x0031, "WM_GETFONT" },
+ { 0x0032, "WM_SETHOTKEY" },
+ { 0x0033, "WM_GETHOTKEY" },
+ { 0x0037, "WM_QUERYDRAGICON" },
+ { 0x0039, "WM_COMPAREITEM" },
+ { 0x003D, "WM_GETOBJECT" },
+ { 0x0041, "WM_COMPACTING" },
+ { 0x0044, "WM_COMMNOTIFY" },
+ { 0x0046, "WM_WINDOWPOSCHANGING" },
+ { 0x0047, "WM_WINDOWPOSCHANGED" },
+ { 0x0048, "WM_POWER" },
+ { 0x004A, "WM_COPYDATA" },
+ { 0x004B, "WM_CANCELJOURNAL" },
+ { 0x004E, "WM_NOTIFY" },
+ { 0x0050, "WM_INPUTLANGCHANGEREQUEST" },
+ { 0x0051, "WM_INPUTLANGCHANGE" },
+ { 0x0052, "WM_TCARD" },
+ { 0x0053, "WM_HELP" },
+ { 0x0054, "WM_USERCHANGED" },
+ { 0x0055, "WM_NOTIFYFORMAT" },
+ { 0x007B, "WM_CONTEXTMENU" },
+ { 0x007C, "WM_STYLECHANGING" },
+ { 0x007D, "WM_STYLECHANGED" },
+ { 0x007E, "WM_DISPLAYCHANGE" },
+ { 0x007F, "WM_GETICON" },
+ { 0x0080, "WM_SETICON" },
+ { 0x0081, "WM_NCCREATE" },
+ { 0x0082, "WM_NCDESTROY" },
+ { 0x0083, "WM_NCCALCSIZE" },
+ { 0x0084, "WM_NCHITTEST" },
+ { 0x0085, "WM_NCPAINT" },
+ { 0x0086, "WM_NCACTIVATE" },
+ { 0x0087, "WM_GETDLGCODE" },
+ { 0x0088, "WM_SYNCPAINT" },
+ { 0x00A0, "WM_NCMOUSEMOVE" },
+ { 0x00A1, "WM_NCLBUTTONDOWN" },
+ { 0x00A2, "WM_NCLBUTTONUP" },
+ { 0x00A3, "WM_NCLBUTTONDBLCLK" },
+ { 0x00A4, "WM_NCRBUTTONDOWN" },
+ { 0x00A5, "WM_NCRBUTTONUP" },
+ { 0x00A6, "WM_NCRBUTTONDBLCLK" },
+ { 0x00A7, "WM_NCMBUTTONDOWN" },
+ { 0x00A8, "WM_NCMBUTTONUP" },
+ { 0x00A9, "WM_NCMBUTTONDBLCLK" },
+ { 0x00AB, "WM_NCXBUTTONDOWN" },
+ { 0x00AC, "WM_NCXBUTTONUP" },
+ { 0x00AD, "WM_NCXBUTTONDBLCLK" },
+ { 0x00FF, "WM_INPUT" },
+ { 0x0100, "WM_KEYDOWN" },
+ { 0x0101, "WM_KEYUP" },
+ { 0x0102, "WM_CHAR" },
+ { 0x0103, "WM_DEADCHAR" },
+ { 0x0104, "WM_SYSKEYDOWN" },
+ { 0x0105, "WM_SYSKEYUP" },
+ { 0x0106, "WM_SYSCHAR" },
+ { 0x0107, "WM_SYSDEADCHAR" },
+ { 0x0109, "WM_UNICHAR" },
+ { 0x010D, "WM_IME_STARTCOMPOSITION" },
+ { 0x010E, "WM_IME_ENDCOMPOSITION" },
+ { 0x010F, "WM_IME_COMPOSITION" },
+ { 0x0110, "WM_INITDIALOG" },
+ { 0x0111, "WM_COMMAND" },
+ { 0x0112, "WM_SYSCOMMAND" },
+ { 0x0113, "WM_TIMER" },
+ { 0x0114, "WM_HSCROLL" },
+ { 0x0115, "WM_VSCROLL" },
+ { 0x0116, "WM_INITMENU" },
+ { 0x0117, "WM_INITMENUPOPUP" },
+ { 0x011F, "WM_MENUSELECT" },
+ { 0x0120, "WM_MENUCHAR" },
+ { 0x0121, "WM_ENTERIDLE" },
+ { 0x0122, "WM_MENURBUTTONUP" },
+ { 0x0123, "WM_MENUDRAG" },
+ { 0x0124, "WM_MENUGETOBJECT" },
+ { 0x0125, "WM_UNINITMENUPOPUP" },
+ { 0x0126, "WM_MENUCOMMAND" },
+ { 0x0127, "WM_CHANGEUISTATE" },
+ { 0x0128, "WM_UPDATEUISTATE" },
+ { 0x0129, "WM_QUERYUISTATE" },
+ { 0x0132, "WM_CTLCOLORMSGBOX" },
+ { 0x0133, "WM_CTLCOLOREDIT" },
+ { 0x0134, "WM_CTLCOLORLISTBOX" },
+ { 0x0135, "WM_CTLCOLORBTN" },
+ { 0x0136, "WM_CTLCOLORDLG" },
+ { 0x0137, "WM_CTLCOLORSCROLLBAR" },
+ { 0x0138, "WM_CTLCOLORSTATIC" },
+ { 0x0200, "WM_MOUSEMOVE" },
+ { 0x0201, "WM_LBUTTONDOWN" },
+ { 0x0202, "WM_LBUTTONUP" },
+ { 0x0203, "WM_LBUTTONDBLCLK" },
+ { 0x0204, "WM_RBUTTONDOWN" },
+ { 0x0205, "WM_RBUTTONUP" },
+ { 0x0206, "WM_RBUTTONDBLCLK" },
+ { 0x0207, "WM_MBUTTONDOWN" },
+ { 0x0208, "WM_MBUTTONUP" },
+ { 0x0209, "WM_MBUTTONDBLCLK" },
+ { 0x020A, "WM_MOUSEWHEEL" },
+ { 0x020B, "WM_XBUTTONDOWN" },
+ { 0x020C, "WM_XBUTTONUP" },
+ { 0x020D, "WM_XBUTTONDBLCLK" },
+ { 0x020E, "WM_MOUSEHWHEEL" },
+ { 0x0210, "WM_PARENTNOTIFY" },
+ { 0x0211, "WM_ENTERMENULOOP" },
+ { 0x0212, "WM_EXITMENULOOP" },
+ { 0x0213, "WM_NEXTMENU" },
+ { 0x0214, "WM_SIZING" },
+ { 0x0215, "WM_CAPTURECHANGED" },
+ { 0x0216, "WM_MOVING" },
+ { 0x0218, "WM_POWERBROADCAST" },
+ { 0x0219, "WM_DEVICECHANGE" },
+ { 0x0220, "WM_MDICREATE" },
+ { 0x0221, "WM_MDIDESTROY" },
+ { 0x0222, "WM_MDIACTIVATE" },
+ { 0x0223, "WM_MDIRESTORE" },
+ { 0x0224, "WM_MDINEXT" },
+ { 0x0225, "WM_MDIMAXIMIZE" },
+ { 0x0226, "WM_MDITILE" },
+ { 0x0227, "WM_MDICASCADE" },
+ { 0x0228, "WM_MDIICONARRANGE" },
+ { 0x0229, "WM_MDIGETACTIVE" },
+ { 0x0230, "WM_MDISETMENU" },
+ { 0x0231, "WM_ENTERSIZEMOVE" },
+ { 0x0232, "WM_EXITSIZEMOVE" },
+ { 0x0233, "WM_DROPFILES" },
+ { 0x0234, "WM_MDIREFRESHMENU" },
+ { 0x0281, "WM_IME_SETCONTEXT" },
+ { 0x0282, "WM_IME_NOTIFY" },
+ { 0x0283, "WM_IME_CONTROL" },
+ { 0x0284, "WM_IME_COMPOSITIONFULL" },
+ { 0x0285, "WM_IME_SELECT" },
+ { 0x0286, "WM_IME_CHAR" },
+ { 0x0288, "WM_IME_REQUEST" },
+ { 0x0290, "WM_IME_KEYDOWN" },
+ { 0x0291, "WM_IME_KEYUP" },
+ { 0x02A0, "WM_NCMOUSEHOVER" },
+ { 0x02A1, "WM_MOUSEHOVER" },
+ { 0x02A2, "WM_NCMOUSELEAVE" },
+ { 0x02A3, "WM_MOUSELEAVE" },
+ { 0x02B1, "WM_WTSSESSION_CHANGE" },
+ { 0x02C0, "WM_TABLET_FIRST" },
+ { 0x02C1, "WM_TABLET_FIRST + 1" },
+ { 0x02C2, "WM_TABLET_FIRST + 2" },
+ { 0x02C3, "WM_TABLET_FIRST + 3" },
+ { 0x02C4, "WM_TABLET_FIRST + 4" },
+ { 0x02C5, "WM_TABLET_FIRST + 5" },
+ { 0x02C6, "WM_TABLET_FIRST + 6" },
+ { 0x02C7, "WM_TABLET_FIRST + 7" },
+ { 0x02C8, "WM_TABLET_FIRST + 8" },
+ { 0x02C9, "WM_TABLET_FIRST + 9" },
+ { 0x02CA, "WM_TABLET_FIRST + 10" },
+ { 0x02CB, "WM_TABLET_FIRST + 11" },
+ { 0x02CC, "WM_TABLET_FIRST + 12" },
+ { 0x02CD, "WM_TABLET_FIRST + 13" },
+ { 0x02CE, "WM_TABLET_FIRST + 14" },
+ { 0x02CF, "WM_TABLET_FIRST + 15" },
+ { 0x02D0, "WM_TABLET_FIRST + 16" },
+ { 0x02D1, "WM_TABLET_FIRST + 17" },
+ { 0x02D2, "WM_TABLET_FIRST + 18" },
+ { 0x02D3, "WM_TABLET_FIRST + 19" },
+ { 0x02D4, "WM_TABLET_FIRST + 20" },
+ { 0x02D5, "WM_TABLET_FIRST + 21" },
+ { 0x02D6, "WM_TABLET_FIRST + 22" },
+ { 0x02D7, "WM_TABLET_FIRST + 23" },
+ { 0x02D8, "WM_TABLET_FIRST + 24" },
+ { 0x02D9, "WM_TABLET_FIRST + 25" },
+ { 0x02DA, "WM_TABLET_FIRST + 26" },
+ { 0x02DB, "WM_TABLET_FIRST + 27" },
+ { 0x02DC, "WM_TABLET_FIRST + 28" },
+ { 0x02DD, "WM_TABLET_FIRST + 29" },
+ { 0x02DE, "WM_TABLET_FIRST + 30" },
+ { 0x02DF, "WM_TABLET_LAST" },
+ { 0x0300, "WM_CUT" },
+ { 0x0301, "WM_COPY" },
+ { 0x0302, "WM_PASTE" },
+ { 0x0303, "WM_CLEAR" },
+ { 0x0304, "WM_UNDO" },
+ { 0x0305, "WM_RENDERFORMAT" },
+ { 0x0306, "WM_RENDERALLFORMATS" },
+ { 0x0307, "WM_DESTROYCLIPBOARD" },
+ { 0x0308, "WM_DRAWCLIPBOARD" },
+ { 0x0309, "WM_PAINTCLIPBOARD" },
+ { 0x030A, "WM_VSCROLLCLIPBOARD" },
+ { 0x030B, "WM_SIZECLIPBOARD" },
+ { 0x030C, "WM_ASKCBFORMATNAME" },
+ { 0x030D, "WM_CHANGECBCHAIN" },
+ { 0x030E, "WM_HSCROLLCLIPBOARD" },
+ { 0x030F, "WM_QUERYNEWPALETTE" },
+ { 0x0310, "WM_PALETTEISCHANGING" },
+ { 0x0311, "WM_PALETTECHANGED" },
+ { 0x0312, "WM_HOTKEY" },
+ { 0x0317, "WM_PRINT" },
+ { 0x0318, "WM_PRINTCLIENT" },
+ { 0x0319, "WM_APPCOMMAND" },
+ { 0x031A, "WM_THEMECHANGED" },
+ { 0x0358, "WM_HANDHELDFIRST" },
+ { 0x0359, "WM_HANDHELDFIRST + 1" },
+ { 0x035A, "WM_HANDHELDFIRST + 2" },
+ { 0x035B, "WM_HANDHELDFIRST + 3" },
+ { 0x035C, "WM_HANDHELDFIRST + 4" },
+ { 0x035D, "WM_HANDHELDFIRST + 5" },
+ { 0x035E, "WM_HANDHELDFIRST + 6" },
+ { 0x035F, "WM_HANDHELDLAST" },
+ { 0x0360, "WM_AFXFIRST" },
+ { 0x0361, "WM_AFXFIRST + 1" },
+ { 0x0362, "WM_AFXFIRST + 2" },
+ { 0x0363, "WM_AFXFIRST + 3" },
+ { 0x0364, "WM_AFXFIRST + 4" },
+ { 0x0365, "WM_AFXFIRST + 5" },
+ { 0x0366, "WM_AFXFIRST + 6" },
+ { 0x0367, "WM_AFXFIRST + 7" },
+ { 0x0368, "WM_AFXFIRST + 8" },
+ { 0x0369, "WM_AFXFIRST + 9" },
+ { 0x036A, "WM_AFXFIRST + 10" },
+ { 0x036B, "WM_AFXFIRST + 11" },
+ { 0x036C, "WM_AFXFIRST + 12" },
+ { 0x036D, "WM_AFXFIRST + 13" },
+ { 0x036E, "WM_AFXFIRST + 14" },
+ { 0x036F, "WM_AFXFIRST + 15" },
+ { 0x0370, "WM_AFXFIRST + 16" },
+ { 0x0371, "WM_AFXFIRST + 17" },
+ { 0x0372, "WM_AFXFIRST + 18" },
+ { 0x0373, "WM_AFXFIRST + 19" },
+ { 0x0374, "WM_AFXFIRST + 20" },
+ { 0x0375, "WM_AFXFIRST + 21" },
+ { 0x0376, "WM_AFXFIRST + 22" },
+ { 0x0377, "WM_AFXFIRST + 23" },
+ { 0x0378, "WM_AFXFIRST + 24" },
+ { 0x0379, "WM_AFXFIRST + 25" },
+ { 0x037A, "WM_AFXFIRST + 26" },
+ { 0x037B, "WM_AFXFIRST + 27" },
+ { 0x037C, "WM_AFXFIRST + 28" },
+ { 0x037D, "WM_AFXFIRST + 29" },
+ { 0x037E, "WM_AFXFIRST + 30" },
+ { 0x037F, "WM_AFXLAST" },
+ { 0x0380, "WM_PENWINFIRST" },
+ { 0x0381, "WM_PENWINFIRST + 1" },
+ { 0x0382, "WM_PENWINFIRST + 2" },
+ { 0x0383, "WM_PENWINFIRST + 3" },
+ { 0x0384, "WM_PENWINFIRST + 4" },
+ { 0x0385, "WM_PENWINFIRST + 5" },
+ { 0x0386, "WM_PENWINFIRST + 6" },
+ { 0x0387, "WM_PENWINFIRST + 7" },
+ { 0x0388, "WM_PENWINFIRST + 8" },
+ { 0x0389, "WM_PENWINFIRST + 9" },
+ { 0x038A, "WM_PENWINFIRST + 10" },
+ { 0x038B, "WM_PENWINFIRST + 11" },
+ { 0x038C, "WM_PENWINFIRST + 12" },
+ { 0x038D, "WM_PENWINFIRST + 13" },
+ { 0x038E, "WM_PENWINFIRST + 14" },
+ { 0x038F, "WM_PENWINLAST" },
+ { 0x0400, "WM_USER" },
+ { 0x8000, "WM_APP" },
+ { 0,0 }}; // End of known messages
+
+// Looks up the WM_ message in the table above
+static const char* findWMstr(uint msg)
+{
+ uint i = 0;
+ const char* result = 0;
+ // Known WM_'s
+ while (knownWM[i].str && (knownWM[i].WM != msg))
+ ++i;
+ result = knownWM[i].str;
+ return result;
+};
+
+// Convenience function for converting flags and values into readable strings
+struct FLAG_STRING_STRUCT
+{
+ uint value;
+ const char* str;
+};
+
+FLAG_STRING_STRUCT FLAG_STRING(int value = 0, const char *c = 0)
+{
+ FLAG_STRING_STRUCT s = {value, c};
+ return s;
+}
+
+#define FLGSTR(x) FLAG_STRING(x, #x)
+
+// Returns an ORed (" | ") together string for the flags active in the actual
+// value. (...) must consist of FLAG_STRING, with a FLAG_STRING() as the last
+// value in the list passed to the function
+QString flagCheck(uint actual, ...)
+{
+ va_list ap;
+ va_start(ap, actual);
+
+ QString result;
+ int count = 0;
+ FLAG_STRING_STRUCT v;
+ while((v=va_arg(ap,FLAG_STRING_STRUCT)).str) {
+ if ((actual & v.value) == v.value) {
+ if (count++)
+ result += QLatin1String(" | ");
+ result += QString::fromLatin1(v.str);
+ }
+ }
+ va_end(ap);
+ return result;
+};
+
+// Returns the string representation of the value in 'actual'. (...) must
+// consist of FLAG_STRING, with a FLAG_STRING() as the last value in the list
+// passed to the function
+QString valueCheck(uint actual, ...)
+{
+ va_list ap;
+ va_start(ap, actual);
+
+ QString result;
+ FLAG_STRING_STRUCT v;
+ while((v=va_arg(ap,FLAG_STRING_STRUCT)).str && (actual != v.value))
+ ;
+ result = QString::fromLatin1(v.str);
+
+ va_end(ap);
+ return result;
+};
+
+#ifdef Q_CC_BOR
+
+QString decodeMSG(const MSG& msg)
+{
+ return QString::fromLatin1("THis is not supported on Borland");
+}
+
+#else
+
+// Returns a "human readable" string representation of the MSG and the
+// information it points to
+QString decodeMSG(const MSG& msg)
+{
+ const WPARAM wParam = msg.wParam;
+ const LPARAM lParam = msg.lParam;
+ QString wmmsg = QString::fromLatin1(findWMstr(msg.message));
+ // Unknown WM_, so use number
+ if (wmmsg.isEmpty())
+ wmmsg = QString::fromLatin1("WM_(%1)").arg(msg.message);
+
+ QString rawParameters;
+ rawParameters.sprintf("hwnd(0x%p) ", (void *)msg.hwnd);
+
+ // Custom WM_'s
+ if (msg.message > WM_APP)
+ wmmsg = QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
+ else if (msg.message > WM_USER)
+ wmmsg = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
+
+ QString parameters;
+ switch (msg.message) {
+#ifdef WM_ACTIVATE
+ case WM_ACTIVATE:
+ {
+ QString activation = valueCheck(wParam,
+ FLAG_STRING(WA_ACTIVE, "Activate"),
+ FLAG_STRING(WA_INACTIVE, "Deactivate"),
+ FLAG_STRING(WA_CLICKACTIVE, "Activate by mouseclick"),
+ FLAG_STRING());
+ parameters.sprintf("%s Hwnd (0x%p)", activation.toLatin1().data(), (void *)msg.hwnd);
+ }
+ break;
+#endif
+#ifdef WM_CAPTURECHANGED
+ case WM_CAPTURECHANGED:
+ parameters.sprintf("Hwnd gaining capture (0x%p)", (void *)lParam);
+ break;
+#endif
+#ifdef WM_CREATE
+ case WM_CREATE:
+ {
+ LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
+ QString styles = flagCheck(lpcs->style,
+ FLGSTR(WS_BORDER),
+ FLGSTR(WS_CAPTION),
+ FLGSTR(WS_CHILD),
+ FLGSTR(WS_CLIPCHILDREN),
+ FLGSTR(WS_CLIPSIBLINGS),
+ FLGSTR(WS_DISABLED),
+ FLGSTR(WS_DLGFRAME),
+ FLGSTR(WS_GROUP),
+ FLGSTR(WS_HSCROLL),
+ FLGSTR(WS_OVERLAPPED),
+#if defined(WS_OVERLAPPEDWINDOW) && (WS_OVERLAPPEDWINDOW != 0)
+ FLGSTR(WS_OVERLAPPEDWINDOW),
+#endif
+#ifdef WS_ICONIC
+ FLGSTR(WS_ICONIC),
+#endif
+ FLGSTR(WS_MAXIMIZE),
+ FLGSTR(WS_MAXIMIZEBOX),
+ FLGSTR(WS_MINIMIZE),
+ FLGSTR(WS_MINIMIZEBOX),
+ FLGSTR(WS_OVERLAPPEDWINDOW),
+ FLGSTR(WS_POPUP),
+#ifdef WS_POPUPWINDOW
+ FLGSTR(WS_POPUPWINDOW),
+#endif
+ FLGSTR(WS_SIZEBOX),
+ FLGSTR(WS_SYSMENU),
+ FLGSTR(WS_TABSTOP),
+ FLGSTR(WS_THICKFRAME),
+#ifdef WS_TILED
+ FLGSTR(WS_TILED),
+#endif
+#ifdef WS_TILEDWINDOW
+ FLGSTR(WS_TILEDWINDOW),
+#endif
+ FLGSTR(WS_VISIBLE),
+ FLGSTR(WS_VSCROLL),
+ FLAG_STRING());
+
+ QString exStyles = flagCheck(lpcs->dwExStyle,
+#ifdef WS_EX_ACCEPTFILES
+ FLGSTR(WS_EX_ACCEPTFILES),
+#endif
+#ifdef WS_EX_APPWINDOW
+ FLGSTR(WS_EX_APPWINDOW),
+#endif
+ FLGSTR(WS_EX_CLIENTEDGE),
+ FLGSTR(WS_EX_DLGMODALFRAME),
+#ifdef WS_EX_LEFT
+ FLGSTR(WS_EX_LEFT),
+#endif
+ FLGSTR(WS_EX_LEFTSCROLLBAR),
+#ifdef WS_EX_LTRREADING
+ FLGSTR(WS_EX_LTRREADING),
+#endif
+#ifdef WS_EX_MDICHILD
+ FLGSTR(WS_EX_MDICHILD),
+#endif
+#ifdef WS_EX_NOACTIVATE
+ FLGSTR(WS_EX_NOACTIVATE),
+#endif
+#ifdef WS_EX_NOANIMATION
+ FLGSTR(WS_EX_NOANIMATION),
+#endif
+ FLGSTR(WS_EX_NOPARENTNOTIFY),
+ FLGSTR(WS_EX_OVERLAPPEDWINDOW),
+#ifdef WS_EX_PALETTEWINDOW
+ FLGSTR(WS_EX_PALETTEWINDOW),
+#endif
+#ifdef WS_EX_RIGHT
+ FLGSTR(WS_EX_RIGHT),
+#endif
+#ifdef WS_EX_RIGHTSCROLLBAR
+ FLGSTR(WS_EX_RIGHTSCROLLBAR),
+#endif
+#ifdef WS_EX_RTLREADING
+ FLGSTR(WS_EX_RTLREADING),
+#endif
+ FLGSTR(WS_EX_STATICEDGE),
+ FLGSTR(WS_EX_TOOLWINDOW),
+ FLGSTR(WS_EX_TOPMOST),
+#ifdef WS_EX_TRANSPARENT
+ FLGSTR(WS_EX_TRANSPARENT),
+#endif
+ FLGSTR(WS_EX_WINDOWEDGE),
+#ifdef WS_EX_CAPTIONOKBTN
+ FLGSTR(WS_EX_CAPTIONOKBTN),
+#endif
+ FLAG_STRING());
+
+ QString className;
+ if (lpcs->lpszClass != 0) {
+ if (HIWORD(lpcs->lpszClass) == 0) // Atom
+ className = QString::number(LOWORD(lpcs->lpszClass), 16);
+ else // String
+ className = QString((QChar*)lpcs->lpszClass,
+ (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszClass)));
+ }
+
+ QString windowName;
+ if (lpcs->lpszName != 0)
+ windowName = QString((QChar*)lpcs->lpszName,
+ (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszName)));
+
+ parameters.sprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
+ lpcs->x, lpcs->y, lpcs->cx, lpcs->cy, className.toLatin1().data(),
+ windowName.toLatin1().data(), (void *)lpcs->hwndParent,
+ styles.toLatin1().data(), exStyles.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_DESTROY
+ case WM_DESTROY:
+ parameters.sprintf("Destroy hwnd (0x%p)", (void *)msg.hwnd);
+ break;
+#endif
+#ifdef WM_IME_NOTIFY
+ case WM_IME_NOTIFY:
+ {
+ QString imnCommand = valueCheck(wParam,
+ FLGSTR(IMN_CHANGECANDIDATE),
+ FLGSTR(IMN_CLOSECANDIDATE),
+ FLGSTR(IMN_CLOSESTATUSWINDOW),
+ FLGSTR(IMN_GUIDELINE),
+ FLGSTR(IMN_OPENCANDIDATE),
+ FLGSTR(IMN_OPENSTATUSWINDOW),
+ FLGSTR(IMN_SETCANDIDATEPOS),
+ FLGSTR(IMN_SETCOMPOSITIONFONT),
+ FLGSTR(IMN_SETCOMPOSITIONWINDOW),
+ FLGSTR(IMN_SETCONVERSIONMODE),
+ FLGSTR(IMN_SETOPENSTATUS),
+ FLGSTR(IMN_SETSENTENCEMODE),
+ FLGSTR(IMN_SETSTATUSWINDOWPOS),
+ FLAG_STRING());
+ parameters.sprintf("Command(%s : 0x%p)", imnCommand.toLatin1().data(), (void *)lParam);
+ }
+ break;
+#endif
+#ifdef WM_IME_SETCONTEXT
+ case WM_IME_SETCONTEXT:
+ {
+ bool fSet = (BOOL)wParam;
+ DWORD fShow = (DWORD)lParam;
+ QString showFlgs = flagCheck(fShow,
+#ifdef ISC_SHOWUICOMPOSITIONWINDOW
+ FLGSTR(ISC_SHOWUICOMPOSITIONWINDOW),
+#endif
+#ifdef ISC_SHOWUIGUIDWINDOW
+ FLGSTR(ISC_SHOWUIGUIDWINDOW),
+#endif
+#ifdef ISC_SHOWUISOFTKBD
+ FLGSTR(ISC_SHOWUISOFTKBD),
+#endif
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 1),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 2),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 3),
+ FLAG_STRING());
+ parameters.sprintf("Input context(%s) Show flags(%s)", (fSet? "Active" : "Inactive"), showFlgs.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_KILLFOCUS
+ case WM_KILLFOCUS:
+ parameters.sprintf("Hwnd gaining keyboard focus (0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_CHAR
+ case WM_CHAR:
+#endif
+#ifdef WM_IME_CHAR
+ case WM_IME_CHAR:
+#endif
+#ifdef WM_KEYDOWN
+ case WM_KEYDOWN:
+#endif
+#ifdef WM_KEYUP
+ case WM_KEYUP:
+ {
+ int nVirtKey = (int)wParam;
+ long lKeyData = (long)lParam;
+ int repCount = (lKeyData & 0xffff); // Bit 0-15
+ int scanCode = (lKeyData & 0xf0000) >> 16; // Bit 16-23
+ bool contextCode = (lKeyData && 0x20000000); // Bit 29
+ bool prevState = (lKeyData && 0x40000000); // Bit 30
+ bool transState = (lKeyData && 0x80000000); // Bit 31
+ parameters.sprintf("Virual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
+ nVirtKey, scanCode, repCount, contextCode, prevState, transState);
+ }
+ break;
+#endif
+#ifdef WM_NCACTIVATE
+ case WM_NCACTIVATE:
+ {
+ parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
+ }
+ break;
+#endif
+#ifdef WM_MOUSEACTIVATE
+ case WM_MOUSEACTIVATE:
+ {
+ QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
+ parameters.sprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)", (void *)wParam, LOWORD(lParam), mouseMsg.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_MOUSELEAVE
+ case WM_MOUSELEAVE:
+ break; // wParam & lParam not used
+#endif
+#ifdef WM_MOUSEHOVER
+ case WM_MOUSEHOVER:
+#endif
+#ifdef WM_MOUSEWHEEL
+ case WM_MOUSEWHEEL:
+#endif
+#ifdef WM_MOUSEHWHEEL
+ case WM_MOUSEHWHEEL:
+#endif
+#ifdef WM_LBUTTONDBLCLK
+ case WM_LBUTTONDBLCLK:
+#endif
+#ifdef WM_LBUTTONDOWN
+ case WM_LBUTTONDOWN:
+#endif
+#ifdef WM_LBUTTONUP
+ case WM_LBUTTONUP:
+#endif
+#ifdef WM_MBUTTONDBLCLK
+ case WM_MBUTTONDBLCLK:
+#endif
+#ifdef WM_MBUTTONDOWN
+ case WM_MBUTTONDOWN:
+#endif
+#ifdef WM_MBUTTONUP
+ case WM_MBUTTONUP:
+#endif
+#ifdef WM_RBUTTONDBLCLK
+ case WM_RBUTTONDBLCLK:
+#endif
+#ifdef WM_RBUTTONDOWN
+ case WM_RBUTTONDOWN:
+#endif
+#ifdef WM_RBUTTONUP
+ case WM_RBUTTONUP:
+#endif
+#ifdef WM_MOUSEMOVE
+ case WM_MOUSEMOVE:
+ {
+ QString vrtKeys = flagCheck(wParam,
+ FLGSTR(MK_CONTROL),
+ FLGSTR(MK_LBUTTON),
+ FLGSTR(MK_MBUTTON),
+ FLGSTR(MK_RBUTTON),
+ FLGSTR(MK_SHIFT),
+#ifdef MK_XBUTTON1
+ FLGSTR(MK_XBUTTON1),
+#endif
+#ifdef MK_XBUTTON2
+ FLGSTR(MK_XBUTTON2),
+#endif
+ FLAG_STRING());
+ parameters.sprintf("x,y(%4d,%4d) Virtual Keys(%s)", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), vrtKeys.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_MOVE
+ case WM_MOVE:
+ parameters.sprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
+ break;
+#endif
+#if defined(WM_PAINT) && defined(WM_ERASEBKGND)
+ case WM_ERASEBKGND:
+ case WM_PAINT:
+ parameters.sprintf("hdc(0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_QUERYNEWPALETTE
+ case WM_QUERYNEWPALETTE:
+ break; // lParam & wParam are unused
+#endif
+#ifdef WM_SETCURSOR
+ case WM_SETCURSOR:
+ {
+ QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
+ parameters.sprintf("HitTestCode(0x%x) MouseMsg(%s)", LOWORD(lParam), mouseMsg.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_SETFOCUS
+ case WM_SETFOCUS:
+ parameters.sprintf("Lost Focus (0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_SETTEXT
+ case WM_SETTEXT:
+ parameters.sprintf("Set Text (%s)", QString((QChar*)lParam, (int)wcslen(reinterpret_cast<const wchar_t *>(lParam))).toLatin1().data()); //Unicode string
+ break;
+#endif
+#ifdef WM_SIZE
+ case WM_SIZE:
+ {
+ QString showMode = valueCheck(wParam,
+ FLGSTR(SIZE_MAXHIDE),
+ FLGSTR(SIZE_MAXIMIZED),
+ FLGSTR(SIZE_MAXSHOW),
+ FLGSTR(SIZE_MINIMIZED),
+ FLGSTR(SIZE_RESTORED),
+ FLAG_STRING());
+
+ parameters.sprintf("w,h(%4d,%4d) showmode(%s)", LOWORD(lParam), HIWORD(lParam), showMode.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_WINDOWPOSCHANGED
+ case WM_WINDOWPOSCHANGED:
+ {
+ LPWINDOWPOS winPos = (LPWINDOWPOS)lParam;
+ if (!winPos)
+ break;
+ QString hwndAfter = valueCheck(quint64(winPos->hwndInsertAfter),
+ FLAG_STRING((qptrdiff)HWND_BOTTOM, "HWND_BOTTOM"),
+ FLAG_STRING((qptrdiff)HWND_NOTOPMOST, "HWND_NOTOPMOST"),
+ FLAG_STRING((qptrdiff)HWND_TOP, "HWND_TOP"),
+ FLAG_STRING((qptrdiff)HWND_TOPMOST, "HWND_TOPMOST"),
+ FLAG_STRING());
+ if (hwndAfter.isEmpty())
+ hwndAfter = QString::number((quintptr)winPos->hwndInsertAfter, 16);
+ QString flags = flagCheck(winPos->flags,
+ FLGSTR(SWP_DRAWFRAME),
+ FLGSTR(SWP_FRAMECHANGED),
+ FLGSTR(SWP_HIDEWINDOW),
+ FLGSTR(SWP_NOACTIVATE),
+#ifdef SWP_NOCOPYBITS
+ FLGSTR(SWP_NOCOPYBITS),
+#endif
+ FLGSTR(SWP_NOMOVE),
+ FLGSTR(SWP_NOOWNERZORDER),
+ FLGSTR(SWP_NOREDRAW),
+ FLGSTR(SWP_NOREPOSITION),
+#ifdef SWP_NOSENDCHANGING
+ FLGSTR(SWP_NOSENDCHANGING),
+#endif
+ FLGSTR(SWP_NOSIZE),
+ FLGSTR(SWP_NOZORDER),
+ FLGSTR(SWP_SHOWWINDOW),
+ FLAG_STRING());
+ 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());
+ }
+ break;
+#endif
+ default:
+ parameters.sprintf("wParam(0x%p) lParam(0x%p)", (void *)wParam, (void *)lParam);
+ break;
+ }
+ // Yes, we want to give the WM_ names 20 chars of space before showing the
+ // decoded message, since some of the common messages are quite long, and
+ // we don't want the decoded information to vary in output position
+ QString message = QString::fromLatin1("%1: ").arg(wmmsg, 20);
+ message += rawParameters;
+ message += parameters;
+ return message;
+}
+
+#endif
+
+QDebug operator<<(QDebug dbg, const MSG &msg)
+{
+ dbg << decodeMSG(msg);
+ return dbg.nospace();
+}
+#endif
+
+QT_END_NAMESPACE