File: mfc.h

package info (click to toggle)
wxpython4.0 4.2.3%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 221,752 kB
  • sloc: cpp: 962,555; python: 230,573; ansic: 170,731; makefile: 51,756; sh: 9,342; perl: 1,564; javascript: 584; php: 326; xml: 200
file content (193 lines) | stat: -rw-r--r-- 5,538 bytes parent folder | download | duplicates (4)
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_