1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
///////////////////////////////////////////////////////////////////////////////
// Name: wx/msw/mfc.h
// Purpose: Helpers for applications using both wxWidgets and MFC
// Author: Julian Smart, Vadim Zeitlin
// Created: 2017-12-01 (mostly extracted from samples/mfc)
// Copyright: (c) 2017 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_MSW_MFC_H_
#define _WX_MSW_MFC_H_
#ifndef __AFXWIN_H__
#error "MFC headers must be included before including this file."
#endif
#include "wx/app.h"
#include "wx/evtloop.h"
#include "wx/window.h"
#include "wx/msw/winundef.h"
// ----------------------------------------------------------------------------
// MFC window class wrapping a window created by wxWidgets
// ----------------------------------------------------------------------------
class wxMFCWnd : public CWnd
{
public:
// If default ctor is used, Attach() must be called later.
wxMFCWnd()
{
}
// Combines default ctor and Attach().
explicit wxMFCWnd(wxWindow* w)
{
Attach(w);
}
void Attach(wxWindow* w)
{
CWnd::Attach(w->GetHWND());
}
~wxMFCWnd()
{
// Prevent MFC from destroying the wxWindow.
Detach();
}
};
// ----------------------------------------------------------------------------
// MFC application class forwarding everything to wxApp
// ----------------------------------------------------------------------------
// The template parameter here is an existing class deriving from CWinApp or,
// if there is no such class, just CWinApp itself.
template <typename T>
class wxMFCApp : public T
{
public:
typedef T BaseApp;
BOOL InitInstance() wxOVERRIDE
{
if ( !BaseApp::InitInstance() )
return FALSE;
if ( !wxEntryStart(BaseApp::m_hInstance) )
return FALSE;
if ( !wxTheApp || !wxTheApp->CallOnInit() )
return FALSE;
if ( !InitMainWnd() )
return FALSE;
return TRUE;
}
int ExitInstance() wxOVERRIDE
{
delete BaseApp::m_pMainWnd;
BaseApp::m_pMainWnd = NULL;
if ( wxTheApp )
wxTheApp->OnExit();
wxEntryCleanup();
return BaseApp::ExitInstance();
}
// Override this to provide messages pre-processing for wxWidgets windows.
BOOL PreTranslateMessage(MSG *msg) wxOVERRIDE
{
// Use the current event loop if there is one, or just fall back to the
// standard one otherwise, but make sure we pre-process messages in any
// case as otherwise many things would break (e.g. keyboard
// accelerators).
wxGUIEventLoop*
evtLoop = static_cast<wxGUIEventLoop *>(wxEventLoop::GetActive());
wxGUIEventLoop evtLoopStd;
if ( !evtLoop )
evtLoop = &evtLoopStd;
if ( evtLoop->PreProcessMessage(msg) )
return TRUE;
return BaseApp::PreTranslateMessage(msg);
}
BOOL OnIdle(LONG lCount) wxOVERRIDE
{
BOOL moreIdle = BaseApp::OnIdle(lCount);
if ( wxTheApp )
{
wxTheApp->ProcessPendingEvents();
if ( wxTheApp->ProcessIdle() )
moreIdle = TRUE;
}
return moreIdle;
}
protected:
// This virtual method can be overridden to create the main window using
// MFC code. The default implementation relies on wxApp::OnInit() creating
// a top level window which is then wrapped in an MFC window and used as
// the main window.
virtual BOOL InitMainWnd()
{
wxWindow* const w = wxTheApp->GetTopWindow();
if ( !w )
return FALSE;
// We need to initialize the main window to let the program continue
// running.
BaseApp::m_pMainWnd = new wxMFCWnd(w);
// We also need to reset m_pMainWnd when this window will be destroyed
// to prevent MFC from using an invalid HWND, which is probably not
// fatal but can result in at least asserts failures.
w->Bind(wxEVT_DESTROY, &wxMFCApp::OnMainWindowDestroyed, this);
// And we need to let wxWidgets know that it should exit the
// application when this window is closed, as OnRun(), which does this
// by default, won't be called when using MFC main message loop.
wxTheApp->SetExitOnFrameDelete(true);
return TRUE;
}
private:
void OnMainWindowDestroyed(wxWindowDestroyEvent& event)
{
event.Skip();
delete BaseApp::m_pMainWnd;
BaseApp::m_pMainWnd = NULL;
}
};
typedef wxMFCApp<CWinApp> wxMFCWinApp;
// ----------------------------------------------------------------------------
// wxWidgets application class to be used in MFC applications
// ----------------------------------------------------------------------------
class wxAppWithMFC : public wxApp
{
public:
void ExitMainLoop() wxOVERRIDE
{
// There is no wxEventLoop to exit, tell MFC to stop pumping messages
// instead.
::PostQuitMessage(0);
}
void WakeUpIdle() wxOVERRIDE
{
// As above, we can't wake up any wx event loop, so try to wake up the
// MFC one instead.
CWinApp* const mfcApp = AfxGetApp();
if ( mfcApp && mfcApp->m_pMainWnd )
{
::PostMessage(mfcApp->m_pMainWnd->m_hWnd, WM_NULL, 0, 0);
}
}
};
#endif // _WX_MSW_MFC_H_
|