wxModalWindow class - now a general modal window to use.

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Post Reply
jmason1182
Earned some good credits
Earned some good credits
Posts: 149
Joined: Fri Dec 14, 2007 3:40 pm
Location: Midland, TX
Contact:

wxModalWindow class - now a general modal window to use.

Post 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.
John A. Mason
Midland, TX
cdpadmin
In need of some credit
In need of some credit
Posts: 4
Joined: Mon Jan 23, 2012 5:14 am

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

Post by cdpadmin »

Hope this helps somebody.
Very much so. Thanks.
wxProgrammer
Experienced Solver
Experienced Solver
Posts: 96
Joined: Thu Apr 17, 2014 10:10 am

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

Post by wxProgrammer »

Nice work, good! :D
I'm Italian but we can speak C++ :)
Post Reply