Fix destruction of wxNativeContainerWindow in wxMSW.
WM_CLOSE was not processed at all for native windows wrapped by wxNativeContainerWindow because we don't handle it ourselves at wxWindow level but still mark it as processed in order to prevent DefWindowProc() from destroying the window. Unfortunately this also prevented the original handler for this message in the native window from being called. Calling just the original handler and not the wxWidgets one is not ideal neither but is much better as it allows to e.g. close MFC frames wrapped in wxNativeContainerWindow whereas before this didn't work at all as WM_CLOSE was completely ignored. Also call the original handler for WM_DESTROY to avoid similar potential problems with this message, even if it doesn't seem to create any with MFC. Extend the mfc sample to show how a wxPanel can be embedded into the existing CFrameWnd.
This commit is contained in:
@@ -70,6 +70,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/evtloop.h"
|
#include "wx/evtloop.h"
|
||||||
|
#include "wx/nativewin.h"
|
||||||
|
#include "wx/spinctrl.h"
|
||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
@@ -121,6 +123,38 @@ public:
|
|||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MyPanel : public wxPanel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyPanel(wxWindow *parent, const wxPoint& pos)
|
||||||
|
: wxPanel(parent, wxID_ANY, pos)
|
||||||
|
{
|
||||||
|
wxSizer* const sizer = new wxFlexGridSizer(2, wxSize(5, 5));
|
||||||
|
sizer->Add(new wxStaticText(this, wxID_ANY, "Enter your &name:"),
|
||||||
|
wxSizerFlags().Center().Right());
|
||||||
|
m_textName = new wxTextCtrl(this, wxID_ANY);
|
||||||
|
m_textName->SetHint("First Last");
|
||||||
|
sizer->Add(m_textName, wxSizerFlags().Expand().CenterVertical());
|
||||||
|
|
||||||
|
sizer->Add(new wxStaticText(this, wxID_ANY, "And your &age:"),
|
||||||
|
wxSizerFlags().Center().Right());
|
||||||
|
m_spinAge = new wxSpinCtrl(this, wxID_ANY);
|
||||||
|
sizer->Add(m_spinAge, wxSizerFlags().Expand().CenterVertical());
|
||||||
|
|
||||||
|
wxStaticBoxSizer* const
|
||||||
|
box = new wxStaticBoxSizer(wxVERTICAL, this, "wxWidgets box");
|
||||||
|
box->Add(sizer, wxSizerFlags(1).Expand());
|
||||||
|
SetSizer(box);
|
||||||
|
|
||||||
|
// We won't be resized automatically, so set our size ourselves.
|
||||||
|
SetSize(GetBestSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxTextCtrl* m_textName;
|
||||||
|
wxSpinCtrl* m_spinAge;
|
||||||
|
};
|
||||||
|
|
||||||
// ID for the menu quit command
|
// ID for the menu quit command
|
||||||
#define HELLO_QUIT 1
|
#define HELLO_QUIT 1
|
||||||
#define HELLO_NEW 2
|
#define HELLO_NEW 2
|
||||||
@@ -147,6 +181,18 @@ CMainWindow::CMainWindow()
|
|||||||
LoadAccelTable( wxT("MainAccelTable") );
|
LoadAccelTable( wxT("MainAccelTable") );
|
||||||
Create( NULL, wxT("Hello Foundation Application"),
|
Create( NULL, wxT("Hello Foundation Application"),
|
||||||
WS_OVERLAPPEDWINDOW, rectDefault, NULL, wxT("MainMenu") );
|
WS_OVERLAPPEDWINDOW, rectDefault, NULL, wxT("MainMenu") );
|
||||||
|
|
||||||
|
// Create a container representing the MFC window in wxWidgets window
|
||||||
|
// hierarchy.
|
||||||
|
m_containerWX = new wxNativeContainerWindow(m_hWnd);
|
||||||
|
|
||||||
|
// Now we can create children of this container as usual.
|
||||||
|
new MyPanel(m_containerWX, wxPoint(5, 5));
|
||||||
|
|
||||||
|
// An ugly but necessary workaround to prevent the container TLW from
|
||||||
|
// resizing the panel to fit its entire client area as it would do if it
|
||||||
|
// were its only child.
|
||||||
|
new wxWindow(m_containerWX, wxID_ANY, wxPoint(4, 4), wxSize(1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMainWindow::OnPaint()
|
void CMainWindow::OnPaint()
|
||||||
|
@@ -26,6 +26,9 @@ public:
|
|||||||
//}}AFX_MSG
|
//}}AFX_MSG
|
||||||
|
|
||||||
DECLARE_MESSAGE_MAP()
|
DECLARE_MESSAGE_MAP()
|
||||||
|
|
||||||
|
private:
|
||||||
|
class wxNativeContainerWindow* m_containerWX;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A dummy CWnd pointing to a wxWindow's HWND
|
// A dummy CWnd pointing to a wxWindow's HWND
|
||||||
|
@@ -69,11 +69,24 @@ WXLRESULT wxNativeContainerWindow::MSWWindowProc(WXUINT nMsg,
|
|||||||
WXWPARAM wParam,
|
WXWPARAM wParam,
|
||||||
WXLPARAM lParam)
|
WXLPARAM lParam)
|
||||||
{
|
{
|
||||||
if ( nMsg == WM_DESTROY )
|
switch ( nMsg )
|
||||||
{
|
{
|
||||||
OnNativeDestroyed();
|
case WM_CLOSE:
|
||||||
|
// wxWindow itself, unlike wxFrame, doesn't react to WM_CLOSE and
|
||||||
|
// just ignores it without even passing it to DefWindowProc(),
|
||||||
|
// which means that the original WM_CLOSE handler wouldn't be
|
||||||
|
// called if we didn't explicitly do it here.
|
||||||
|
return MSWDefWindowProc(nMsg, wParam, lParam);
|
||||||
|
|
||||||
return 0;
|
case WM_DESTROY:
|
||||||
|
// Send it to the original handler which may have some cleanup to
|
||||||
|
// do as well. Notice that we must do it before calling
|
||||||
|
// OnNativeDestroyed() as we can't use this object after doing it.
|
||||||
|
MSWDefWindowProc(nMsg, wParam, lParam);
|
||||||
|
|
||||||
|
OnNativeDestroyed();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wxTopLevelWindow::MSWWindowProc(nMsg, wParam, lParam);
|
return wxTopLevelWindow::MSWWindowProc(nMsg, wParam, lParam);
|
||||||
|
Reference in New Issue
Block a user