The purpose of this... extension... was because I needed to add a menu to a dialog OR to make a frame modal. But since I couldn't get either to work very well, I began searching to see who had done it before. Yes, I can call MakeModal on a frame... but it didn't behave the way I wanted it to. Thus, I made a general class that can allow the simple yet important ability to have a Modal Window with a Menu.
wx\modalwindow.h
Code: Select all
/**********************************************************************************************
*
* Filename : modalwindow.h
* Purpose : Allow a modalwindow like wxDialog but allowing menus and such.
* Author : John A. Mason
* Created : 8/27/2008 07:54:12 AM
* Copyright : Released under wxWidgets original license.
*
**********************************************************************************************/
#ifndef __wx_ModalWindow_h__
#define __wx_ModalWindow_h__
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include <wx/frame.h>
#ifndef WX_PRECOMP
#include <wx/utils.h>
#include <wx/app.h>
#endif
#include <wx/evtloop.h>
class wxModalWindow : public wxFrame {
private:
// while we are showing a modal window we disable the other windows using
// this object
wxWindowDisabler *m_windowDisabler;
// modal window runs its own event loop
wxEventLoop *m_eventLoop;
// is modal right now?
bool m_isShowingModal;
//The return code of a modal window
int m_returnCode;
public:
wxModalWindow();
wxModalWindow(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE, const wxString& name = "modalwindow");
virtual ~wxModalWindow();
void Init();
bool Show(bool show);
bool IsModal() const;
int ShowModal();
void EndModal(int retCode);
void SetReturnCode(int retCode);
int GetReturnCode() const;
};
#endif
wx\modalwindow.cpp
Code: Select all
/**********************************************************************************************
*
* Filename : modalwindow.cpp
* Purpose : Allow a modalwindow like wxDialog but allowing menus and such.
* Author : John A. Mason
* Created : 8/27/2008 07:54:12 AM
* Copyright : Released under wxWidgets original license.
*
**********************************************************************************************/
#include "modalwindow.h"
wxModalWindow::wxModalWindow()
: wxFrame() {
Init();
}
wxModalWindow::wxModalWindow(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
: wxFrame(parent, id, title, pos, size, style, name) {
Init();
}
wxModalWindow::~wxModalWindow() {
delete m_eventLoop;
}
void wxModalWindow::Init()
{
m_returnCode = 0;
m_windowDisabler = NULL;
m_eventLoop = NULL;
m_isShowingModal = false;
}
bool wxModalWindow::Show(bool show)
{
if ( !show )
{
// if we had disabled other app windows, reenable them back now because
// if they stay disabled Windows will activate another window (one
// which is enabled, anyhow) and we will lose activation
if ( m_windowDisabler )
{
delete m_windowDisabler;
m_windowDisabler = NULL;
}
if ( IsModal() )
EndModal(wxID_CANCEL);
}
bool ret = wxFrame::Show(show);
//I don't think we need this. Since it is a wxFrame that we are extending,
// we don't need wxEVT_INIT_DIALOG firing off - that's what InitDialog does...
// and this would only make sense if we have a wxDialog and validators
// if ( show )
//InitDialog();
return ret;
}
bool wxModalWindow::IsModal() const {
return m_isShowingModal;
}
int wxModalWindow::ShowModal() {
if ( IsModal() )
{
wxFAIL_MSG( wxT("wxModalWindow:ShowModal called twice") );
return GetReturnCode();
}
// use the apps top level window as parent if none given unless explicitly
// forbidden
if ( !GetParent() )
{
wxWindow *parent = wxTheApp->GetTopWindow();
if ( parent && parent != this )
{
m_parent = parent;
}
}
Show(true);
m_isShowingModal = true;
wxASSERT_MSG( !m_windowDisabler, _T("disabling windows twice?") );
#if defined(__WXGTK__) || defined(__WXMGL__)
wxBusyCursorSuspender suspender;
// FIXME (FIXME_MGL) - make sure busy cursor disappears under MSW too
#endif
m_windowDisabler = new wxWindowDisabler(this);
if ( !m_eventLoop )
m_eventLoop = new wxEventLoop;
m_eventLoop->Run();
return GetReturnCode();
}
void wxModalWindow::EndModal(int retCode) {
wxASSERT_MSG( m_eventLoop, _T("wxModalWindow is not modal") );
SetReturnCode(retCode);
if ( !IsModal() )
{
wxFAIL_MSG( wxT("wxModalWindow:EndModal called twice") );
return;
}
m_isShowingModal = false;
m_eventLoop->Exit();
Show(false);
}
void wxModalWindow::SetReturnCode(int retCode) {
m_returnCode=retCode;
}
int wxModalWindow::GetReturnCode() const {
return m_returnCode;
}
Usage: Use it like a wxFrame... ie:
Code: Select all
class UnitDisplay : public wxModalWindow {
...
and
...
UnitDisplay::UnitDisplay(wxWindow* parent)
: wxModalWindow(parent,wxID_ANY,wxT("Title"),wxDefaultPosition,wxDefaultSize,wxFRAME_NO_TASKBAR | wxFRAME_OTHER_OPTIONS...) {
...
Hope this helps somebody.