summaryrefslogtreecommitdiffstats
path: root/qtwinmigrate/qwinwidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qtwinmigrate/qwinwidget.cpp')
-rw-r--r--qtwinmigrate/qwinwidget.cpp331
1 files changed, 331 insertions, 0 deletions
diff --git a/qtwinmigrate/qwinwidget.cpp b/qtwinmigrate/qwinwidget.cpp
new file mode 100644
index 0000000..2c0929f
--- /dev/null
+++ b/qtwinmigrate/qwinwidget.cpp
@@ -0,0 +1,331 @@
+// 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>
+
+/*!
+ \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::WFlags 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::WFlags 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) {
+ // make the widget window style be WS_CHILD so SetParent will work
+ QT_WA({
+ SetWindowLong(winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+ }, {
+ SetWindowLongA(winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+ })
+ SetParent(winId(), hParent);
+
+ 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 = qFindChild<QWidget*>(this);
+ 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
+*/
+bool QWinWidget::winEvent(MSG *msg, long *)
+{
+ if (msg->message == WM_SETFOCUS) {
+ Qt::FocusReason reason;
+ 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;
+}