Page 1 of 1

wxModalWindow class - now a general modal window to use.

Posted: Wed Aug 27, 2008 2:12 pm
by jmason1182
I went ahead and created a wxModalWindow class. It inherits from wxFrame... so menus and other behaviors mimic a wxFrame. BUT, it behaves like a wxDialog when it comes to modal status. I even added the eventloop and windowDisabler just like wxDialog does. So technically it is a simplified wxDialog (without restrictions.) As far as I know it handles native controls/windows the same as wxFrame... but I haven't tested it beyond my needs. Feel free to add/change/delete to fix any bugs that I didn't test.

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.

Re: wxModalWindow class - now a general modal window to use.

Posted: Fri May 10, 2013 3:47 pm
by cdpadmin
Hope this helps somebody.
Very much so. Thanks.

Re: wxModalWindow class - now a general modal window to use.

Posted: Fri Nov 28, 2014 10:55 am
by wxProgrammer
Nice work, good! :D