解决非qt程序不能调用qt dll的问题
This commit is contained in:
parent
2e41e33a44
commit
146f0a1b7d
|
@ -1,6 +1,6 @@
|
|||
QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets gui-private
|
||||
|
||||
TEMPLATE = lib
|
||||
|
||||
|
@ -42,9 +42,18 @@ if (contains(DEFINES, OEM_HANWANG) || contains(DEFINES, OEM_LISICHENG) || contai
|
|||
}
|
||||
|
||||
win32 {
|
||||
SOURCES += ../../../modules/saneui/dllmain.cpp
|
||||
SOURCES += ../../../modules/saneui/qmfcapp.cpp
|
||||
SOURCES += ../../../modules/saneui/qwinhost.cpp
|
||||
SOURCES += ../../../modules/saneui/qwinwidget.cpp
|
||||
|
||||
HEADERS += ../../../modules/saneui/qmfcapp.h
|
||||
HEADERS += ../../../modules/saneui/qwinhost.h
|
||||
HEADERS += ../../../modules/saneui/qwinwidget.h
|
||||
|
||||
DEF_FILE = HGSaneUI.def
|
||||
DEFINES += _CRT_SECURE_NO_WARNINGS
|
||||
LIBS += -ladvapi32
|
||||
LIBS += -ladvapi32 -luser32
|
||||
|
||||
if (contains(DEFINES, OEM_HANWANG) || contains(DEFINES, OEM_LISICHENG) || contains(DEFINES, OEM_CANGTIAN) || contains(DEFINES, OEM_ZHONGJING) || contains(DEFINES, OEM_ZIGUANG)) {
|
||||
contains(DEFINES, OEM_HANWANG) {
|
||||
|
|
|
@ -2,4 +2,7 @@ TEMPLATE = subdirs
|
|||
|
||||
SUBDIRS += \
|
||||
HGSaneUI \
|
||||
HGDemo
|
||||
HGDemo
|
||||
|
||||
HGDemo.depends = \
|
||||
HGSaneUI
|
|
@ -1,28 +1,26 @@
|
|||
#include "HGSaneUI.h"
|
||||
#include "dialog_device_select.h"
|
||||
#include "dialog_device_scan.h"
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
|
||||
#ifdef HG_CMP_MSC
|
||||
#include "qwinwidget.h"
|
||||
extern HINSTANCE g_hInst;
|
||||
extern bool g_ownApplication;
|
||||
#endif
|
||||
|
||||
int show_devlist_ui(SANEAPI* saneApi, HGWindow parent, SANE_Handle *handle, char *devName, unsigned int maxLen)
|
||||
{
|
||||
if (nullptr == saneApi || nullptr == handle)
|
||||
return -1;
|
||||
|
||||
if (nullptr == qApp)
|
||||
{
|
||||
#ifdef HG_CMP_MSC
|
||||
// 创建WIN32窗口
|
||||
return -2;
|
||||
#else
|
||||
return -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
QWidget *qParent = nullptr;
|
||||
#ifdef HG_CMP_MSC
|
||||
qParent = QWidget::find((WId)parent);
|
||||
if (nullptr != parent && nullptr == qParent)
|
||||
return -2;
|
||||
if (!g_ownApplication)
|
||||
g_ownApplication = QMfcApp::pluginInstance(g_hInst);
|
||||
QWinWidget win(parent);
|
||||
win.showCentered();
|
||||
qParent = &win;
|
||||
#else
|
||||
qParent = parent;
|
||||
#endif
|
||||
|
@ -49,16 +47,6 @@ int show_setting_ui(SANEAPI* saneApi, SANE_Handle handle, HGWindow parent)
|
|||
if (nullptr == saneApi || nullptr == handle)
|
||||
return -1;
|
||||
|
||||
if (nullptr == qApp)
|
||||
{
|
||||
#ifdef HG_CMP_MSC
|
||||
// 创建WIN32窗口
|
||||
return -2;
|
||||
#else
|
||||
return -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -67,21 +55,13 @@ int show_scan_ui(SANEAPI* saneApi, SANE_Handle handle, HGWindow parent, show_sca
|
|||
if (nullptr == saneApi || nullptr == handle)
|
||||
return -1;
|
||||
|
||||
if (nullptr == qApp)
|
||||
{
|
||||
#ifdef HG_CMP_MSC
|
||||
// 创建WIN32窗口
|
||||
return -2;
|
||||
#else
|
||||
return -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
QWidget *qParent = nullptr;
|
||||
#ifdef HG_CMP_MSC
|
||||
qParent = QWidget::find((WId)parent);
|
||||
if (nullptr != parent && nullptr == qParent)
|
||||
return -2;
|
||||
if (!g_ownApplication)
|
||||
g_ownApplication = QMfcApp::pluginInstance(g_hInst);
|
||||
QWinWidget win(parent);
|
||||
win.showCentered();
|
||||
qParent = &win;
|
||||
#else
|
||||
qParent = parent;
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#include "qmfcapp.h"
|
||||
#include "qwinwidget.h"
|
||||
#include <windows.h>
|
||||
|
||||
HINSTANCE g_hInst = NULL;
|
||||
bool g_ownApplication = FALSE;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/)
|
||||
{
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
g_hInst = hInstance;
|
||||
}
|
||||
else if (dwReason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
if (g_ownApplication)
|
||||
delete qApp;
|
||||
g_hInst = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,427 @@
|
|||
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Implementation of the QMfcApp classes
|
||||
|
||||
#ifdef QT3_SUPPORT
|
||||
#undef QT3_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifdef UNICODE
|
||||
#undef UNICODE
|
||||
#endif
|
||||
|
||||
#include "qmfcapp.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QWidget>
|
||||
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
#include <afxwin.h>
|
||||
#else
|
||||
#include <qt_windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
CWinApp *QMfcApp::mfc_app = 0;
|
||||
char **QMfcApp::mfc_argv = 0;
|
||||
int QMfcApp::mfc_argc = 0;
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#define QT_WA(unicode, ansi) unicode
|
||||
|
||||
QMfcAppEventFilter::QMfcAppEventFilter() : QAbstractNativeEventFilter()
|
||||
{
|
||||
}
|
||||
|
||||
bool QMfcAppEventFilter::nativeEventFilter(const QByteArray &, void *message, long *result)
|
||||
{
|
||||
return static_cast<QMfcApp*>(qApp)->winEventFilter((MSG*)message, result);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! \class QMfcApp qmfcapp.h
|
||||
\brief The QMfcApp class provides merging of the MFC and Qt event loops.
|
||||
|
||||
QMfcApp is responsible for driving both the Qt and MFC event loop.
|
||||
It replaces the standard MFC event loop provided by
|
||||
CWinApp::Run(), and is used instead of the QApplication parent
|
||||
class.
|
||||
|
||||
To replace the MFC event loop reimplement the CWinApp::Run()
|
||||
function in the CWinApp subclass usually created by the MFC
|
||||
Application Wizard, and use either the static run() function, or
|
||||
an instance of QMfcApp created earlier through the static
|
||||
instance() function or the constructor.
|
||||
|
||||
The QMfcApp class also provides a static API pluginInstance() that
|
||||
drives the Qt event loop when loaded into an MFC or Win32 application.
|
||||
This is useful for developing Qt based DLLs or plugins, or if the
|
||||
MFC application's event handling can not be modified.
|
||||
*/
|
||||
|
||||
static int modalLoopCount = 0;
|
||||
|
||||
HHOOK hhook;
|
||||
LRESULT CALLBACK QtFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (qApp) {
|
||||
// don't process deferred-deletes while in a modal loop
|
||||
if (modalLoopCount)
|
||||
qApp->sendPostedEvents();
|
||||
else
|
||||
qApp->sendPostedEvents(0, -1);
|
||||
}
|
||||
|
||||
return CallNextHookEx(hhook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
/*!
|
||||
Inform Qt that a modal loop is about to be entered, and that DeferredDelete
|
||||
events should not be processed. Call this function before calling Win32
|
||||
or MFC functions that enter a modal event loop (i.e. MessageBox).
|
||||
|
||||
This is only required if the Qt UI code hooks into an existing Win32
|
||||
event loop using QMfcApp::pluginInstance.
|
||||
|
||||
\sa exitModalLoop()
|
||||
*/
|
||||
void QMfcApp::enterModalLoop()
|
||||
{
|
||||
++modalLoopCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
Inform Qt that a modal loop has been exited, and that DeferredDelete
|
||||
events should not be processed. Call this function after the blocking
|
||||
Win32 or MFC function (i.e. MessageBox) returned.
|
||||
|
||||
This is only required if the Qt UI code hooks into an existing Win32
|
||||
event loop using QMfcApp::pluginInstance.
|
||||
|
||||
\sa enterModalLoop()
|
||||
*/
|
||||
void QMfcApp::exitModalLoop()
|
||||
{
|
||||
--modalLoopCount;
|
||||
Q_ASSERT(modalLoopCount >= 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
If there is no global QApplication object (i.e. qApp is null) this
|
||||
function creates a QApplication instance and returns true;
|
||||
otherwise it does nothing and returns false.
|
||||
|
||||
The application installs an event filter that drives the Qt event
|
||||
loop while the MFC or Win32 application continues to own the event
|
||||
loop.
|
||||
|
||||
Use this static function if the application event loop code can not be
|
||||
easily modified, or when developing a plugin or DLL that will be loaded
|
||||
into an existing Win32 or MFC application. If \a plugin is non-null then
|
||||
the function loads the respective DLL explicitly to avoid unloading from
|
||||
memory.
|
||||
|
||||
\code
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved)
|
||||
{
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
QMfcApp::pluginInstance(hInstance);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
\endcode
|
||||
|
||||
Set \a plugin to 0 when calling this function from within the same executable
|
||||
module.
|
||||
|
||||
If this function is used, call enterModalLoop and exitModalLoop whenever you
|
||||
call a Win32 or MFC function that opens a local event loop.
|
||||
|
||||
\code
|
||||
void Dialog::someSlot()
|
||||
{
|
||||
QMfcApp::enterModalLoop();
|
||||
MessageBox(...);
|
||||
QMfcApp::exitModalLoop();
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
bool QMfcApp::pluginInstance(Qt::HANDLE plugin)
|
||||
{
|
||||
if (qApp)
|
||||
return FALSE;
|
||||
|
||||
QT_WA({
|
||||
hhook = SetWindowsHookExW(WH_GETMESSAGE, QtFilterProc, 0, GetCurrentThreadId());
|
||||
}, {
|
||||
hhook = SetWindowsHookExA(WH_GETMESSAGE, QtFilterProc, 0, GetCurrentThreadId());
|
||||
});
|
||||
|
||||
int argc = 0;
|
||||
(void)new QApplication(argc, 0);
|
||||
|
||||
if (plugin) {
|
||||
char filename[256];
|
||||
if (GetModuleFileNameA((HINSTANCE)plugin, filename, 255))
|
||||
LoadLibraryA(filename);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
Q_GLOBAL_STATIC(QMfcAppEventFilter, qmfcEventFilter);
|
||||
#endif
|
||||
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
/*!
|
||||
Runs the event loop for both Qt and the MFC application object \a
|
||||
mfcApp, and returns the result. This function calls \c instance()
|
||||
if no QApplication object exists and deletes the object it
|
||||
created.
|
||||
|
||||
Calling this static function in a reimplementation of
|
||||
CWinApp::Run() is the simpliest way to use the QMfcApp class:
|
||||
|
||||
\code
|
||||
int MyMfcApp::Run()
|
||||
{
|
||||
return QMfcApp::run(this);
|
||||
}
|
||||
\endcode
|
||||
|
||||
Since a QApplication object must exist before Qt widgets can be
|
||||
created you cannot use this function if you want to use Qt-based
|
||||
user interface elements in, for example, the InitInstance()
|
||||
function of CWinApp. In such cases, create an instance of
|
||||
QApplication explicitly using instance() or the constructor.
|
||||
|
||||
\sa instance()
|
||||
*/
|
||||
int QMfcApp::run(CWinApp *mfcApp)
|
||||
{
|
||||
bool ownInstance = !qApp;
|
||||
if (ownInstance)
|
||||
instance(mfcApp);
|
||||
int result = qApp->exec();
|
||||
|
||||
if (mfcApp) {
|
||||
int mfcRes = mfcApp->ExitInstance();
|
||||
if (mfcRes && !result)
|
||||
result = mfcRes;
|
||||
}
|
||||
|
||||
if (ownInstance)
|
||||
delete qApp;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates an instance of QApplication, passing the command line of
|
||||
\a mfcApp to the QApplication constructor, and returns the new
|
||||
object. The returned object must be destroyed by the caller.
|
||||
|
||||
Use this static function if you want to perform additional
|
||||
initializations after creating the application object, or if you
|
||||
want to create Qt GUI elements in the InitInstance()
|
||||
reimplementation of CWinApp:
|
||||
|
||||
\code
|
||||
BOOL MyMfcApp::InitInstance()
|
||||
{
|
||||
// standard MFC initialization
|
||||
// ...
|
||||
|
||||
// This sets the global qApp pointer
|
||||
QMfcApp::instance(this);
|
||||
|
||||
// Qt GUI initialization
|
||||
}
|
||||
|
||||
BOOL MyMfcApp::Run()
|
||||
{
|
||||
int result = QMfcApp::run(this);
|
||||
delete qApp;
|
||||
return result;
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa run()
|
||||
*/
|
||||
QApplication *QMfcApp::instance(CWinApp *mfcApp)
|
||||
{
|
||||
mfc_app = mfcApp;
|
||||
if (mfc_app) {
|
||||
#if defined(UNICODE)
|
||||
QString exeName((QChar*)mfc_app->m_pszExeName, wcslen(mfc_app->m_pszExeName));
|
||||
QString cmdLine((QChar*)mfc_app->m_lpCmdLine, wcslen(mfc_app->m_lpCmdLine));
|
||||
#else
|
||||
QString exeName = QString::fromLocal8Bit(mfc_app->m_pszExeName);
|
||||
QString cmdLine = QString::fromLocal8Bit(mfc_app->m_lpCmdLine);
|
||||
#endif
|
||||
QStringList arglist = QString(exeName + " " + cmdLine).split(' ');
|
||||
|
||||
mfc_argc = arglist.count();
|
||||
mfc_argv = new char*[mfc_argc+1];
|
||||
int a;
|
||||
for (a = 0; a < mfc_argc; ++a) {
|
||||
QString arg = arglist[a];
|
||||
mfc_argv[a] = new char[arg.length()+1];
|
||||
qstrcpy(mfc_argv[a], arg.toLocal8Bit().data());
|
||||
}
|
||||
mfc_argv[a] = 0;
|
||||
}
|
||||
|
||||
return new QMfcApp(mfcApp, mfc_argc, mfc_argv);
|
||||
}
|
||||
|
||||
|
||||
static bool qmfc_eventFilter(void *message)
|
||||
{
|
||||
long result = 0;
|
||||
return static_cast<QMfcApp*>(qApp)->winEventFilter((MSG*)message, &result);
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates an instance of QMfcApp. \a mfcApp must point to the
|
||||
existing instance of CWinApp. \a argc and \a argv are passed on
|
||||
to the QApplication constructor.
|
||||
|
||||
Use the static function instance() to automatically use the
|
||||
command line passed to the CWinApp.
|
||||
|
||||
\code
|
||||
QMfcApp *qtApp;
|
||||
|
||||
BOOL MyMfcApp::InitInstance()
|
||||
{
|
||||
// standard MFC initialization
|
||||
|
||||
int argc = ...
|
||||
char **argv = ...
|
||||
|
||||
qtApp = new QMfcApp(this, argc, argv);
|
||||
|
||||
// Qt GUI initialization
|
||||
}
|
||||
|
||||
BOOL MyMfcApp::Run()
|
||||
{
|
||||
int result = qtApp->exec();
|
||||
delete qtApp;
|
||||
qtApp = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa instance() run()
|
||||
*/
|
||||
QMfcApp::QMfcApp(CWinApp *mfcApp, int &argc, char **argv)
|
||||
: QApplication(argc, argv), idleCount(0), doIdle(FALSE)
|
||||
{
|
||||
mfc_app = mfcApp;
|
||||
#if QT_VERSION >= 0x050000
|
||||
QAbstractEventDispatcher::instance()->installNativeEventFilter(qmfcEventFilter());
|
||||
#else
|
||||
QAbstractEventDispatcher::instance()->setEventFilter(qmfc_eventFilter);
|
||||
#endif
|
||||
setQuitOnLastWindowClosed(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
QMfcApp::QMfcApp(int &argc, char **argv) : QApplication(argc, argv)
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
QAbstractEventDispatcher::instance()->installNativeEventFilter(qmfcEventFilter());
|
||||
#endif
|
||||
}
|
||||
/*!
|
||||
Destroys the QMfcApp object, freeing all allocated resources.
|
||||
*/
|
||||
QMfcApp::~QMfcApp()
|
||||
{
|
||||
if (hhook) {
|
||||
UnhookWindowsHookEx(hhook);
|
||||
hhook = 0;
|
||||
}
|
||||
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
for (int a = 0; a < mfc_argc; ++a) {
|
||||
char *arg = mfc_argv[a];
|
||||
delete[] arg;
|
||||
}
|
||||
delete []mfc_argv;
|
||||
|
||||
mfc_argc = 0;
|
||||
mfc_argv = 0;
|
||||
mfc_app = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QMfcApp::winEventFilter(MSG *msg, long *result)
|
||||
{
|
||||
static bool recursion = false;
|
||||
if (recursion)
|
||||
return false;
|
||||
|
||||
recursion = true;
|
||||
|
||||
QWidget *widget = QWidget::find((WId)msg->hwnd);
|
||||
HWND toplevel = 0;
|
||||
if (widget) {
|
||||
HWND parent = (HWND)widget->winId();
|
||||
while(parent) {
|
||||
toplevel = parent;
|
||||
parent = GetParent(parent);
|
||||
}
|
||||
HMENU menu = toplevel ? GetMenu(toplevel) : 0;
|
||||
if (menu && GetFocus() == msg->hwnd) {
|
||||
if (msg->message == WM_SYSKEYUP && msg->wParam == VK_MENU) {
|
||||
// activate menubar on Alt-up and move focus away
|
||||
SetFocus(toplevel);
|
||||
SendMessage(toplevel, msg->message, msg->wParam, msg->lParam);
|
||||
widget->setFocus();
|
||||
recursion = false;
|
||||
return TRUE;
|
||||
} else if (msg->message == WM_SYSKEYDOWN && msg->wParam != VK_MENU) {
|
||||
SendMessage(toplevel, msg->message, msg->wParam, msg->lParam);
|
||||
SendMessage(toplevel, WM_SYSKEYUP, VK_MENU, msg->lParam);
|
||||
recursion = false;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
else if (mfc_app) {
|
||||
MSG tmp;
|
||||
while (doIdle && !PeekMessage(&tmp, 0, 0, 0, PM_NOREMOVE)) {
|
||||
if (!mfc_app->OnIdle(idleCount++))
|
||||
doIdle = FALSE;
|
||||
}
|
||||
if (mfc_app->IsIdleMessage(msg)) {
|
||||
doIdle = TRUE;
|
||||
idleCount = 0;
|
||||
}
|
||||
}
|
||||
if (mfc_app && mfc_app->PreTranslateMessage(msg)) {
|
||||
recursion = false;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
recursion = false;
|
||||
#if QT_VERSION < 0x050000
|
||||
return QApplication::winEventFilter(msg, result);
|
||||
#else
|
||||
Q_UNUSED(result);
|
||||
return false;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
// Declaration of the QMfcApp classes
|
||||
|
||||
#ifndef QMFCAPP_H
|
||||
#define QMFCAPP_H
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#if defined(_AFXDLL) && defined(_MSC_VER)
|
||||
#define QTWINMIGRATE_WITHMFC
|
||||
class CWinApp;
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
class QMfcAppEventFilter : public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
QMfcAppEventFilter();
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
|
||||
};
|
||||
#endif
|
||||
|
||||
class QMfcApp : public QApplication
|
||||
{
|
||||
public:
|
||||
static bool pluginInstance(Qt::HANDLE plugin = 0);
|
||||
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
static int run(CWinApp *mfcApp);
|
||||
static QApplication *instance(CWinApp *mfcApp);
|
||||
QMfcApp(CWinApp *mfcApp, int &argc, char **argv);
|
||||
#endif
|
||||
QMfcApp(int &argc, char **argv);
|
||||
~QMfcApp();
|
||||
|
||||
bool winEventFilter(MSG *msg, long *result);
|
||||
|
||||
static void enterModalLoop();
|
||||
static void exitModalLoop();
|
||||
|
||||
private:
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
static char ** mfc_argv;
|
||||
static int mfc_argc;
|
||||
static CWinApp *mfc_app;
|
||||
#endif
|
||||
|
||||
int idleCount;
|
||||
bool doIdle;
|
||||
};
|
||||
|
||||
#endif // QMFCAPP_H
|
|
@ -0,0 +1,325 @@
|
|||
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Implementation of the QWinHost classes
|
||||
|
||||
#ifdef QT3_SUPPORT
|
||||
#undef QT3_SUPPORT
|
||||
#endif
|
||||
|
||||
#include "qwinhost.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <qt_windows.h>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#define QT_WA(unicode, ansi) unicode
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\class QWinHost qwinhost.h
|
||||
\brief The QWinHost class provides an API to use native Win32
|
||||
windows in Qt applications.
|
||||
|
||||
QWinHost exists to provide a QWidget that can act as a parent for
|
||||
any native Win32 control. Since QWinHost is a proper QWidget, it
|
||||
can be used as a toplevel widget (e.g. 0 parent) or as a child of
|
||||
any other QWidget.
|
||||
|
||||
QWinHost integrates the native control into the Qt user interface,
|
||||
e.g. handles focus switches and laying out.
|
||||
|
||||
Applications moving to Qt may have custom Win32 controls that will
|
||||
take time to rewrite with Qt. Such applications can use these
|
||||
custom controls as children of QWinHost widgets. This allows the
|
||||
application's user interface to be replaced gradually.
|
||||
|
||||
When the QWinHost is destroyed, and the Win32 window hasn't been
|
||||
set with setWindow(), the window will also be destroyed.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Creates an instance of QWinHost. \a parent and \a f are
|
||||
passed on to the QWidget constructor. The widget has by default
|
||||
no background.
|
||||
|
||||
\warning You cannot change the parent widget of the QWinHost instance
|
||||
after the native window has been created, i.e. do not call
|
||||
QWidget::setParent or move the QWinHost into a different layout.
|
||||
*/
|
||||
QWinHost::QWinHost(QWidget *parent, Qt::WindowFlags f)
|
||||
: QWidget(parent, f), wndproc(0),own_hwnd(false), hwnd(0)
|
||||
{
|
||||
setAttribute(Qt::WA_NoBackground);
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the QWinHost object. If the hosted Win32 window has not
|
||||
been set explicitly using setWindow() the window will be
|
||||
destroyed.
|
||||
*/
|
||||
QWinHost::~QWinHost()
|
||||
{
|
||||
if (wndproc) {
|
||||
#if defined(GWLP_WNDPROC)
|
||||
QT_WA({
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc);
|
||||
},{
|
||||
SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc);
|
||||
})
|
||||
#else
|
||||
QT_WA({
|
||||
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wndproc);
|
||||
},{
|
||||
SetWindowLongA(hwnd, GWL_WNDPROC, (LONG)wndproc);
|
||||
})
|
||||
#endif
|
||||
}
|
||||
|
||||
if (hwnd && own_hwnd)
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
/*!
|
||||
Reimplement this virtual function to create and return the native
|
||||
Win32 window. \a parent is the handle to this widget, and \a
|
||||
instance is the handle to the application instance. The returned HWND
|
||||
must be a child of the \a parent HWND.
|
||||
|
||||
The default implementation returns null. The window returned by a
|
||||
reimplementation of this function is owned by this QWinHost
|
||||
instance and will be destroyed in the destructor.
|
||||
|
||||
This function is called by the implementation of polish() if no
|
||||
window has been set explicitly using setWindow(). Call polish() to
|
||||
force this function to be called.
|
||||
|
||||
\sa setWindow()
|
||||
*/
|
||||
HWND QWinHost::createWindow(HWND parent, HINSTANCE instance)
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
Q_UNUSED(instance);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Ensures that the window provided a child of this widget, unless
|
||||
it is a WS_OVERLAPPED window.
|
||||
*/
|
||||
void QWinHost::fixParent()
|
||||
{
|
||||
if (!hwnd)
|
||||
return;
|
||||
if (!::IsWindow(hwnd)) {
|
||||
hwnd = 0;
|
||||
return;
|
||||
}
|
||||
if (::GetParent(hwnd) == (HWND)winId())
|
||||
return;
|
||||
long style = GetWindowLong(hwnd, GWL_STYLE);
|
||||
if (style & WS_OVERLAPPED)
|
||||
return;
|
||||
::SetParent(hwnd, (HWND)winId());
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the native Win32 window to \a window. If \a window is not a child
|
||||
window of this widget, then it is reparented to become one. If \a window
|
||||
is not a child window (i.e. WS_OVERLAPPED is set), then this function does nothing.
|
||||
|
||||
The lifetime of the window handle will be managed by Windows, QWinHost does not
|
||||
call DestroyWindow. To verify that the handle is destroyed when expected, handle
|
||||
WM_DESTROY in the window procedure.
|
||||
|
||||
\sa window(), createWindow()
|
||||
*/
|
||||
void QWinHost::setWindow(HWND window)
|
||||
{
|
||||
if (hwnd && own_hwnd)
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
hwnd = window;
|
||||
fixParent();
|
||||
|
||||
own_hwnd = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the handle to the native Win32 window, or null if no
|
||||
window has been set or created yet.
|
||||
|
||||
\sa setWindow(), createWindow()
|
||||
*/
|
||||
HWND QWinHost::window() const
|
||||
{
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
void *getWindowProc(QWinHost *host)
|
||||
{
|
||||
return host ? host->wndproc : 0;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WinHostProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
QWinHost *widget = qobject_cast<QWinHost*>(QWidget::find((WId)::GetParent(hwnd)));
|
||||
WNDPROC oldproc = (WNDPROC)getWindowProc(widget);
|
||||
if (widget) {
|
||||
switch(msg) {
|
||||
case WM_LBUTTONDOWN:
|
||||
if (::GetFocus() != hwnd && (widget->focusPolicy() & Qt::ClickFocus)) {
|
||||
widget->setFocus(Qt::MouseFocusReason);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
QT_WA({
|
||||
SendMessage((HWND)widget->winId(), msg, wParam, lParam);
|
||||
}, {
|
||||
SendMessageA((HWND)widget->winId(), msg, wParam, lParam);
|
||||
})
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
if (wParam == VK_TAB) {
|
||||
QT_WA({
|
||||
SendMessage((HWND)widget->winId(), msg, wParam, lParam);
|
||||
}, {
|
||||
SendMessageA((HWND)widget->winId(), msg, wParam, lParam);
|
||||
})
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QT_WA({
|
||||
if (oldproc)
|
||||
return CallWindowProc(oldproc, hwnd, msg, wParam, lParam);
|
||||
return DefWindowProc(hwnd,msg,wParam,lParam);
|
||||
}, {
|
||||
if (oldproc)
|
||||
return CallWindowProcA(oldproc, hwnd, msg, wParam, lParam);
|
||||
return DefWindowProcA(hwnd,msg,wParam,lParam);
|
||||
})
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QWinHost::event(QEvent *e)
|
||||
{
|
||||
switch(e->type()) {
|
||||
case QEvent::Polish:
|
||||
if (!hwnd) {
|
||||
hwnd = createWindow(HWND(winId()), GetModuleHandle(0));
|
||||
fixParent();
|
||||
own_hwnd = hwnd != 0;
|
||||
}
|
||||
if (hwnd && !wndproc && GetParent(hwnd) == (HWND)winId()) {
|
||||
#if defined(GWLP_WNDPROC)
|
||||
QT_WA({
|
||||
wndproc = (void*)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WinHostProc);
|
||||
}, {
|
||||
wndproc = (void*)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
|
||||
SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)WinHostProc);
|
||||
})
|
||||
#else
|
||||
QT_WA({
|
||||
wndproc = (void*)GetWindowLong(hwnd, GWL_WNDPROC);
|
||||
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WinHostProc);
|
||||
}, {
|
||||
wndproc = (void*)GetWindowLongA(hwnd, GWL_WNDPROC);
|
||||
SetWindowLongA(hwnd, GWL_WNDPROC, (LONG)WinHostProc);
|
||||
})
|
||||
#endif
|
||||
|
||||
LONG style;
|
||||
QT_WA({
|
||||
style = GetWindowLong(hwnd, GWL_STYLE);
|
||||
}, {
|
||||
style = GetWindowLongA(hwnd, GWL_STYLE);
|
||||
})
|
||||
if (style & WS_TABSTOP)
|
||||
setFocusPolicy(Qt::FocusPolicy(focusPolicy() | Qt::StrongFocus));
|
||||
}
|
||||
break;
|
||||
case QEvent::WindowBlocked:
|
||||
if (hwnd)
|
||||
EnableWindow(hwnd, false);
|
||||
break;
|
||||
case QEvent::WindowUnblocked:
|
||||
if (hwnd)
|
||||
EnableWindow(hwnd, true);
|
||||
break;
|
||||
}
|
||||
return QWidget::event(e);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QWinHost::showEvent(QShowEvent *e)
|
||||
{
|
||||
QWidget::showEvent(e);
|
||||
|
||||
if (hwnd)
|
||||
SetWindowPos(hwnd, HWND_TOP, 0, 0, width(), height(), SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QWinHost::focusInEvent(QFocusEvent *e)
|
||||
{
|
||||
QWidget::focusInEvent(e);
|
||||
|
||||
if (hwnd)
|
||||
::SetFocus(hwnd);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QWinHost::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QWidget::resizeEvent(e);
|
||||
|
||||
if (hwnd)
|
||||
SetWindowPos(hwnd, HWND_TOP, 0, 0, width(), height(), 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
#if QT_VERSION >= 0x050000
|
||||
bool QWinHost::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||
#else
|
||||
bool QWinHost::winEvent(MSG *msg, long *result)
|
||||
#endif
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
MSG *msg = (MSG *)message;
|
||||
#endif
|
||||
switch (msg->message)
|
||||
{
|
||||
case WM_SETFOCUS:
|
||||
if (hwnd) {
|
||||
::SetFocus(hwnd);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if QT_VERSION >= 0x050000
|
||||
return QWidget::nativeEvent(eventType, message, result);
|
||||
#else
|
||||
return QWidget::winEvent(msg, result);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
// Declaration of the QWinHost classes
|
||||
|
||||
#ifndef QWINHOST_H
|
||||
#define QWINHOST_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QWinHost : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QWinHost(QWidget *parent = 0, Qt::WindowFlags f = 0);
|
||||
~QWinHost();
|
||||
|
||||
void setWindow(HWND);
|
||||
HWND window() const;
|
||||
|
||||
protected:
|
||||
virtual HWND createWindow(HWND parent, HINSTANCE instance);
|
||||
|
||||
bool event(QEvent *e);
|
||||
void showEvent(QShowEvent *);
|
||||
void focusInEvent(QFocusEvent*);
|
||||
void resizeEvent(QResizeEvent*);
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||
#else
|
||||
bool winEvent(MSG *msg, long *result);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void fixParent();
|
||||
friend void* getWindowProc(QWinHost*);
|
||||
|
||||
void *wndproc;
|
||||
bool own_hwnd;
|
||||
HWND hwnd;
|
||||
};
|
||||
|
||||
#endif // QWINHOST_H
|
|
@ -0,0 +1,359 @@
|
|||
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Implementation of the QWinWidget classes
|
||||
|
||||
#ifdef QT3_SUPPORT
|
||||
#undef QT3_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifdef UNICODE
|
||||
#undef UNICODE
|
||||
#endif
|
||||
|
||||
#include "qmfcapp.h"
|
||||
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
#include <afxwin.h>
|
||||
#endif
|
||||
|
||||
#include <qevent.h>
|
||||
|
||||
#include "qwinwidget.h"
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QWindow>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#define QT_WA(unicode, ansi) unicode
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\class QWinWidget qwinwidget.h
|
||||
\brief The QWinWidget class is a Qt widget that can be child of a
|
||||
native Win32 widget.
|
||||
|
||||
The QWinWidget class is the bridge between an existing application
|
||||
user interface developed using native Win32 APIs or toolkits like
|
||||
MFC, and Qt based GUI elements.
|
||||
|
||||
Using QWinWidget as the parent of QDialogs will ensure that
|
||||
modality, placement and stacking works properly throughout the
|
||||
entire application. If the child widget is a top level window that
|
||||
uses the \c WDestructiveClose flag, QWinWidget will destroy itself
|
||||
when the child window closes down.
|
||||
|
||||
Applications moving to Qt can use QWinWidget to add new
|
||||
functionality, and gradually replace the existing interface.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Creates an instance of QWinWidget. \a hParentWnd is the handle to
|
||||
the native Win32 parent. If a \a parent is provided the object is
|
||||
owned by that QObject. \a f is passed on to the QWidget constructor.
|
||||
*/
|
||||
QWinWidget::QWinWidget(HWND hParentWnd, QObject *parent, Qt::WindowFlags f)
|
||||
: QWidget(0, f), hParent(hParentWnd), prevFocus(0), reenable_parent(false)
|
||||
{
|
||||
if (parent)
|
||||
QObject::setParent(parent);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
/*!
|
||||
\overload
|
||||
|
||||
Creates an instance of QWinWidget. \a parentWnd is a pointer to an
|
||||
MFC window object. If a \a parent is provided the object is owned
|
||||
by that QObject. \a f is passed on to the QWidget constructor.
|
||||
*/
|
||||
QWinWidget::QWinWidget(CWnd *parentWnd, QObject *parent, Qt::WindowFlags f)
|
||||
: QWidget(0, f), hParent(parentWnd ? parentWnd->m_hWnd : 0), prevFocus(0), reenable_parent(false)
|
||||
{
|
||||
if (parent)
|
||||
QObject::setParent(parent);
|
||||
|
||||
init();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void QWinWidget::init()
|
||||
{
|
||||
Q_ASSERT(hParent);
|
||||
|
||||
if (hParent) {
|
||||
#if QT_VERSION >= 0x050000
|
||||
setProperty("_q_embedded_native_parent_handle", WId(hParent));
|
||||
#endif
|
||||
// make the widget window style be WS_CHILD so SetParent will work
|
||||
QT_WA({
|
||||
SetWindowLong((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
|
||||
}, {
|
||||
SetWindowLongA((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
|
||||
})
|
||||
#if QT_VERSION >= 0x050000
|
||||
QWindow *window = windowHandle();
|
||||
HWND h = static_cast<HWND>(QGuiApplication::platformNativeInterface()->
|
||||
nativeResourceForWindow("handle", window));
|
||||
SetParent(h, hParent);
|
||||
window->setFlags(Qt::FramelessWindowHint);
|
||||
#else
|
||||
SetParent(winId(), hParent);
|
||||
#endif
|
||||
QEvent e(QEvent::EmbeddingControl);
|
||||
QApplication::sendEvent(this, &e);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys this object, freeing all allocated resources.
|
||||
*/
|
||||
QWinWidget::~QWinWidget()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the handle of the native Win32 parent window.
|
||||
*/
|
||||
HWND QWinWidget::parentWindow() const
|
||||
{
|
||||
return hParent;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QWinWidget::childEvent(QChildEvent *e)
|
||||
{
|
||||
QObject *obj = e->child();
|
||||
if (obj->isWidgetType()) {
|
||||
if (e->added()) {
|
||||
if (obj->isWidgetType()) {
|
||||
obj->installEventFilter(this);
|
||||
}
|
||||
} else if (e->removed() && reenable_parent) {
|
||||
reenable_parent = false;
|
||||
EnableWindow(hParent, true);
|
||||
obj->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
QWidget::childEvent(e);
|
||||
}
|
||||
|
||||
/*! \internal */
|
||||
void QWinWidget::saveFocus()
|
||||
{
|
||||
if (!prevFocus)
|
||||
prevFocus = ::GetFocus();
|
||||
if (!prevFocus)
|
||||
prevFocus = parentWindow();
|
||||
}
|
||||
|
||||
/*!
|
||||
Shows this widget. Overrides QWidget::show().
|
||||
|
||||
\sa showCentered()
|
||||
*/
|
||||
void QWinWidget::show()
|
||||
{
|
||||
saveFocus();
|
||||
QWidget::show();
|
||||
}
|
||||
|
||||
/*!
|
||||
Centers this widget over the native parent window. Use this
|
||||
function to have Qt toplevel windows (i.e. dialogs) positioned
|
||||
correctly over their native parent windows.
|
||||
|
||||
\code
|
||||
QWinWidget qwin(hParent);
|
||||
qwin.center();
|
||||
|
||||
QMessageBox::information(&qwin, "Caption", "Information Text");
|
||||
\endcode
|
||||
|
||||
This will center the message box over the client area of hParent.
|
||||
*/
|
||||
void QWinWidget::center()
|
||||
{
|
||||
const QWidget *child = findChild<QWidget*>();
|
||||
if (child && !child->isWindow()) {
|
||||
qWarning("QWinWidget::center: Call this function only for QWinWidgets with toplevel children");
|
||||
}
|
||||
RECT r;
|
||||
GetWindowRect(hParent, &r);
|
||||
setGeometry((r.right-r.left)/2+r.left, (r.bottom-r.top)/2+r.top,0,0);
|
||||
}
|
||||
|
||||
/*!
|
||||
\obsolete
|
||||
|
||||
Call center() instead.
|
||||
*/
|
||||
void QWinWidget::showCentered()
|
||||
{
|
||||
center();
|
||||
show();
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the focus to the window that had the focus before this widget
|
||||
was shown, or if there was no previous window, sets the focus to
|
||||
the parent window.
|
||||
*/
|
||||
void QWinWidget::resetFocus()
|
||||
{
|
||||
if (prevFocus)
|
||||
::SetFocus(prevFocus);
|
||||
else
|
||||
::SetFocus(parentWindow());
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
*/
|
||||
#if QT_VERSION >= 0x050000
|
||||
bool QWinWidget::nativeEvent(const QByteArray &, void *message, long *)
|
||||
#else
|
||||
bool QWinWidget::winEvent(MSG *msg, long *)
|
||||
#endif
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
MSG *msg = (MSG *)message;
|
||||
#endif
|
||||
if (msg->message == WM_SETFOCUS) {
|
||||
Qt::FocusReason reason;
|
||||
if (::GetKeyState(VK_LBUTTON) < 0 || ::GetKeyState(VK_RBUTTON) < 0)
|
||||
reason = Qt::MouseFocusReason;
|
||||
else if (::GetKeyState(VK_SHIFT) < 0)
|
||||
reason = Qt::BacktabFocusReason;
|
||||
else
|
||||
reason = Qt::TabFocusReason;
|
||||
QFocusEvent e(QEvent::FocusIn, reason);
|
||||
QApplication::sendEvent(this, &e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QWinWidget::eventFilter(QObject *o, QEvent *e)
|
||||
{
|
||||
QWidget *w = (QWidget*)o;
|
||||
|
||||
switch (e->type()) {
|
||||
case QEvent::WindowDeactivate:
|
||||
if (w->isModal() && w->isHidden())
|
||||
BringWindowToTop(hParent);
|
||||
break;
|
||||
|
||||
case QEvent::Hide:
|
||||
if (reenable_parent) {
|
||||
EnableWindow(hParent, true);
|
||||
reenable_parent = false;
|
||||
}
|
||||
resetFocus();
|
||||
if (w->testAttribute(Qt::WA_DeleteOnClose) && w->isWindow())
|
||||
deleteLater();
|
||||
break;
|
||||
|
||||
case QEvent::Show:
|
||||
if (w->isWindow()) {
|
||||
saveFocus();
|
||||
hide();
|
||||
if (w->isModal() && !reenable_parent) {
|
||||
EnableWindow(hParent, false);
|
||||
reenable_parent = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case QEvent::Close:
|
||||
::SetActiveWindow(hParent);
|
||||
if (w->testAttribute(Qt::WA_DeleteOnClose))
|
||||
deleteLater();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(o, e);
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
*/
|
||||
void QWinWidget::focusInEvent(QFocusEvent *e)
|
||||
{
|
||||
QWidget *candidate = this;
|
||||
|
||||
switch (e->reason()) {
|
||||
case Qt::TabFocusReason:
|
||||
case Qt::BacktabFocusReason:
|
||||
while (!(candidate->focusPolicy() & Qt::TabFocus)) {
|
||||
candidate = candidate->nextInFocusChain();
|
||||
if (candidate == this) {
|
||||
candidate = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (candidate) {
|
||||
candidate->setFocus(e->reason());
|
||||
if (e->reason() == Qt::BacktabFocusReason || e->reason() == Qt::TabFocusReason) {
|
||||
candidate->setAttribute(Qt::WA_KeyboardFocusChange);
|
||||
candidate->window()->setAttribute(Qt::WA_KeyboardFocusChange);
|
||||
}
|
||||
if (e->reason() == Qt::BacktabFocusReason)
|
||||
QWidget::focusNextPrevChild(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
*/
|
||||
bool QWinWidget::focusNextPrevChild(bool next)
|
||||
{
|
||||
QWidget *curFocus = focusWidget();
|
||||
if (!next) {
|
||||
if (!curFocus->isWindow()) {
|
||||
QWidget *nextFocus = curFocus->nextInFocusChain();
|
||||
QWidget *prevFocus = 0;
|
||||
QWidget *topLevel = 0;
|
||||
while (nextFocus != curFocus) {
|
||||
if (nextFocus->focusPolicy() & Qt::TabFocus) {
|
||||
prevFocus = nextFocus;
|
||||
topLevel = 0;
|
||||
} else if (nextFocus->isWindow()) {
|
||||
topLevel = nextFocus;
|
||||
}
|
||||
nextFocus = nextFocus->nextInFocusChain();
|
||||
}
|
||||
|
||||
if (!topLevel) {
|
||||
return QWidget::focusNextPrevChild(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QWidget *nextFocus = curFocus;
|
||||
while (1) {
|
||||
nextFocus = nextFocus->nextInFocusChain();
|
||||
if (nextFocus->isWindow())
|
||||
break;
|
||||
if (nextFocus->focusPolicy() & Qt::TabFocus) {
|
||||
return QWidget::focusNextPrevChild(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::SetFocus(hParent);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
// Declaration of the QWinWidget classes
|
||||
|
||||
#ifndef QWINWIDGET_H
|
||||
#define QWINWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "qmfcapp.h"
|
||||
|
||||
class CWnd;
|
||||
|
||||
class QWinWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QWinWidget( HWND hParentWnd, QObject *parent = 0, Qt::WindowFlags f = 0 );
|
||||
#ifdef QTWINMIGRATE_WITHMFC
|
||||
QWinWidget( CWnd *parnetWnd, QObject *parent = 0, Qt::WindowFlags f = 0 );
|
||||
#endif
|
||||
~QWinWidget();
|
||||
|
||||
void show();
|
||||
void center();
|
||||
void showCentered();
|
||||
|
||||
HWND parentWindow() const;
|
||||
|
||||
protected:
|
||||
void childEvent( QChildEvent *e );
|
||||
bool eventFilter( QObject *o, QEvent *e );
|
||||
|
||||
bool focusNextPrevChild(bool next);
|
||||
void focusInEvent(QFocusEvent *e);
|
||||
#if QT_VERSION >= 0x050000
|
||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||
#else
|
||||
bool winEvent(MSG *msg, long *result);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
void saveFocus();
|
||||
void resetFocus();
|
||||
|
||||
HWND hParent;
|
||||
HWND prevFocus;
|
||||
bool reenable_parent;
|
||||
};
|
||||
|
||||
#endif // QWINWIDGET_H
|
Loading…
Reference in New Issue