fix to segfault in system menu code

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14672 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2002-03-17 21:44:59 +00:00
parent 66858adfc4
commit 2279b45ad9

View File

@@ -602,8 +602,8 @@ class wxWin32SystemMenuEvtHandler;
class wxWin32FrameInputHandler : public wxStdFrameInputHandler
{
public:
wxWin32FrameInputHandler(wxInputHandler *handler)
: wxStdFrameInputHandler(handler), m_menuHandler(NULL) { }
wxWin32FrameInputHandler(wxInputHandler *handler);
~wxWin32FrameInputHandler();
virtual bool HandleMouse(wxInputConsumer *control,
const wxMouseEvent& event);
@@ -4350,6 +4350,108 @@ bool wxWin32StatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
// wxWin32FrameInputHandler
// ----------------------------------------------------------------------------
class wxWin32SystemMenuEvtHandler : public wxEvtHandler
{
public:
wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler);
void Attach(wxInputConsumer *consumer);
void Detach();
private:
DECLARE_EVENT_TABLE()
void OnSystemMenu(wxCommandEvent &event);
void OnCloseFrame(wxCommandEvent &event);
void OnClose(wxCloseEvent &event);
wxWin32FrameInputHandler *m_inputHnd;
wxTopLevelWindow *m_wnd;
wxAcceleratorTable m_oldAccelTable;
};
wxWin32SystemMenuEvtHandler::wxWin32SystemMenuEvtHandler(
wxWin32FrameInputHandler *handler)
{
m_inputHnd = handler;
m_wnd = NULL;
}
void wxWin32SystemMenuEvtHandler::Attach(wxInputConsumer *consumer)
{
wxASSERT_MSG( m_wnd == NULL, _T("can't attach the handler twice!") );
m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
m_wnd->PushEventHandler(this);
// VS: This code relies on using generic implementation of
// wxAcceleratorTable in wxUniv!
wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
m_oldAccelTable = table;
table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
m_wnd->SetAcceleratorTable(table);
}
void wxWin32SystemMenuEvtHandler::Detach()
{
if ( m_wnd )
{
m_wnd->SetAcceleratorTable(m_oldAccelTable);
m_wnd->RemoveEventHandler(this);
m_wnd = NULL;
}
}
BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
END_EVENT_TABLE()
void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
{
int border = ((m_wnd->GetWindowStyle() & wxRESIZE_BORDER) &&
!m_wnd->IsMaximized()) ?
RESIZEABLE_FRAME_BORDER_THICKNESS :
FRAME_BORDER_THICKNESS;
wxPoint pt = m_wnd->GetClientAreaOrigin();
pt.x = -pt.x + border;
pt.y = -pt.y + border + FRAME_TITLEBAR_HEIGHT;
wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
m_inputHnd->PopupSystemMenu(m_wnd, pt);
m_wnd->SetAcceleratorTable(table);
}
void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
{
m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
wxTOPLEVEL_BUTTON_CLOSE);
}
void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
{
m_wnd = NULL;
event.Skip();
}
wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler)
: wxStdFrameInputHandler(handler)
{
m_menuHandler = new wxWin32SystemMenuEvtHandler(this);
}
wxWin32FrameInputHandler::~wxWin32FrameInputHandler()
{
if ( m_menuHandler )
{
m_menuHandler->Detach();
delete m_menuHandler;
}
}
bool wxWin32FrameInputHandler::HandleMouse(wxInputConsumer *consumer,
const wxMouseEvent& event)
{
@@ -4417,104 +4519,17 @@ void wxWin32FrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window,
delete menu;
}
class wxWin32SystemMenuEvtHandler : public wxEvtHandler
{
public:
wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler,
wxInputConsumer *consumer);
void RemoveSelf();
private:
DECLARE_EVENT_TABLE()
void OnSystemMenu(wxCommandEvent &event);
void OnCloseFrame(wxCommandEvent &event);
void OnClose(wxCloseEvent &event);
wxWin32FrameInputHandler *m_inputHnd;
wxTopLevelWindow *m_wnd;
wxAcceleratorTable m_oldAccelTable;
};
wxWin32SystemMenuEvtHandler::wxWin32SystemMenuEvtHandler(
wxWin32FrameInputHandler *handler,
wxInputConsumer *consumer)
{
m_inputHnd = handler;
m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
m_wnd->PushEventHandler(this);
// VS: This code relies on using generic implementation of
// wxAcceleratorTable in wxUniv!
wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
m_oldAccelTable = table;
table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
m_wnd->SetAcceleratorTable(table);
}
void wxWin32SystemMenuEvtHandler::RemoveSelf()
{
if ( m_wnd )
{
m_wnd->SetAcceleratorTable(m_oldAccelTable);
m_wnd->RemoveEventHandler(this);
}
}
BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
END_EVENT_TABLE()
void wxWin32SystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
{
int border = ((m_wnd->GetWindowStyle() & wxRESIZE_BORDER) &&
!m_wnd->IsMaximized()) ?
RESIZEABLE_FRAME_BORDER_THICKNESS :
FRAME_BORDER_THICKNESS;
wxPoint pt = m_wnd->GetClientAreaOrigin();
pt.x = -pt.x + border;
pt.y = -pt.y + border + FRAME_TITLEBAR_HEIGHT;
wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
m_inputHnd->PopupSystemMenu(m_wnd, pt);
m_wnd->SetAcceleratorTable(table);
}
void wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
{
m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
wxTOPLEVEL_BUTTON_CLOSE);
}
void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
{
m_wnd = NULL;
event.Skip();
}
bool wxWin32FrameInputHandler::HandleActivation(wxInputConsumer *consumer,
bool activated)
{
if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
{
if ( !activated && m_menuHandler )
{
m_menuHandler->RemoveSelf();
wxDELETE(m_menuHandler);
}
else if ( activated )
{
if ( m_menuHandler )
{
m_menuHandler->RemoveSelf();
delete m_menuHandler;
}
// always detach if active frame changed:
m_menuHandler->Detach();
m_menuHandler = new wxWin32SystemMenuEvtHandler(this, consumer);
if ( activated )
{
m_menuHandler->Attach(consumer);
}
}