///////////////////////////////////////////////////////////////////////////// // Name: dialog.cpp // Purpose: wxDialog class // Author: David Webster // Modified by: // Created: 10/14/99 // RCS-ID: $Id$ // Copyright: (c) David Webster // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/dialog.h" #include "wx/utils.h" #include "wx/frame.h" #include "wx/app.h" #include "wx/settings.h" #include "wx/intl.h" #include "wx/log.h" #endif #include "wx/os2/private.h" #include "wx/log.h" #define wxDIALOG_DEFAULT_X 300 #define wxDIALOG_DEFAULT_Y 300 #define wxDIALOG_DEFAULT_WIDTH 500 #define wxDIALOG_DEFAULT_HEIGHT 500 wxWindowList wxModalDialogs; IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow) BEGIN_EVENT_TABLE(wxDialog, wxDialogBase) EVT_BUTTON(wxID_OK, wxDialog::OnOK) EVT_BUTTON(wxID_APPLY, wxDialog::OnApply) EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel) EVT_CHAR_HOOK(wxDialog::OnCharHook) EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged) EVT_CLOSE(wxDialog::OnCloseWindow) END_EVENT_TABLE() void wxDialog::Init() { m_pOldFocus = (wxWindow *)NULL; m_isShown = FALSE; m_pWindowDisabler = (wxWindowDisabler *)NULL; SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); } // end of wxDialog::Init bool wxDialog::Create( wxWindow* pParent , wxWindowID vId , const wxString& rsTitle , const wxPoint& rPos , const wxSize& rSize , long lStyle , const wxString& rsName ) { long lX = rPos.x; long lY = rPos.y; long lWidth = rSize.x; long lHeight = rSize.y; const char* zDlg; WXDWORD dwExtendedStyle = 0L; HWND hWnd; Init(); SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG); // // Save focus before doing anything which can potentially change it // m_pOldFocus = FindFocus(); // // All dialogs should really have this style // lStyle |= wxTAB_TRAVERSAL; if (!wxTopLevelWindow::Create( pParent ,vId ,rsTitle ,rPos ,rSize ,lStyle ,rsName )) return FALSE; SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); // // Must defer setting the title until after dialog is created and sized // if (!rsTitle.IsNull()) SetTitle(rsTitle); return TRUE; } // end of wxDialog::Create void wxDialog::SetModal( bool bFlag ) { if (bFlag) { m_windowStyle |= wxDIALOG_MODAL ; wxModelessWindows.DeleteObject(this); } else { m_windowStyle &= ~wxDIALOG_MODAL ; wxModelessWindows.Append(this); } } // end of wxDialog::SetModal wxDialog::~wxDialog() { m_isBeingDeleted = TRUE; Show(FALSE); } // end of wxDialog::~wxDialog // // By default, pressing escape cancels the dialog // void wxDialog::OnCharHook( wxKeyEvent& rEvent ) { if (GetHWND()) { if (rEvent.m_keyCode == WXK_ESCAPE) { // // Behaviour changed in 2.0: we'll send a Cancel message // to the dialog instead of Close. // wxCommandEvent vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED ,wxID_CANCEL ); vCancelEvent.SetEventObject( this ); GetEventHandler()->ProcessEvent(vCancelEvent); // // Ensure that there is another message for this window so the // ShowModal loop will exit and won't get stuck in GetMessage(). // ::WinPostMsg(GetHwnd(), WM_NULL, 0, 0); return; } } // We didn't process this event. rEvent.Skip(); } // ---------------------------------------------------------------------------- // showing the dialogs // ---------------------------------------------------------------------------- bool wxDialog::IsModal() const { return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0; } // end of wxDialog::IsModal bool wxDialog::IsModalShowing() const { return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast } // end of wxDialog::IsModalShowing void wxDialog::DoShowModal() { wxWindow* pParent = GetParent(); wxWindow* pOldFocus = m_pOldFocus; HWND hWndOldFocus = 0; wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") ); wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") ); wxModalDialogs.Append(this); if (pOldFocus) hWndOldFocus = (HWND)pOldFocus->GetHWND(); // // Remember where the focus was // if (!pOldFocus) { pOldFocus = pParent; if (pParent) hWndOldFocus = GetHwndOf(pParent); } // // Disable all other app windows // wxASSERT_MSG(!m_pWindowDisabler, _T("disabling windows twice?")); // // Disables other app windows and window proc message processing // until WinDismissDlg called // ::WinProcessDlg((HWND)GetHwnd()); // // Enter the modal loop // while ( IsModalShowing() ) { #if wxUSE_THREADS wxMutexGuiLeaveOrEnter(); #endif // wxUSE_THREADS while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() ) ; // a message came or no more idle processing to do wxTheApp->DoMessage(); } // // Snd restore focus // Note that this code MUST NOT access the dialog object's data // in case the object has been deleted (which will be the case // for a modal dialog that has been destroyed before calling EndModal). // if (pOldFocus && (pOldFocus != this) && ::WinIsWindow(vHabmain, hWndOldFocus)) { // // This is likely to prove that the object still exists // if (wxFindWinFromHandle((WXHWND) hWndOldFocus) == pOldFocus) pOldFocus->SetFocus(); } } // end of wxDialog::DoShowModal bool wxDialog::Show( bool bShow ) { if (!bShow) { // // 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. We really don't // do this in OS/2 since PM does this for us. // if (m_pWindowDisabler) { delete m_pWindowDisabler; m_pWindowDisabler = NULL; } } // // ShowModal() may be called for already shown dialog // if (!wxDialogBase::Show(bShow) && !(bShow && IsModal())) { // // Nothing to do // return FALSE; } if (bShow) { // // Usually will result in TransferDataToWindow() being called // InitDialog(); } if (GetTitle().c_str()) ::WinSetWindowText((HWND)GetHwnd(), GetTitle().c_str()); if (IsModal()) { if (bShow) { // // Modal dialog needs a parent window, so try to find one // if (!GetParent()) { wxWindow* pParent = wxTheApp->GetTopWindow(); if ( pParent && pParent != this && pParent->IsShown() ) { // // Use it // m_parent = pParent; } } DoShowModal(); } else // end of modal dialog { // // This will cause IsModalShowing() return FALSE and our local // message loop will terminate // wxModalDialogs.DeleteObject(this); } } return TRUE; } // end of wxDialog::Show // // Replacement for Show(TRUE) for modal dialogs - returns return code // int wxDialog::ShowModal() { if (!IsModal()) { SetModal(TRUE); } Show(TRUE); return GetReturnCode(); } // end of wxDialog::ShowModal void wxDialog::EndModal( int nRetCode ) { SetReturnCode(nRetCode); Show(FALSE); ::WinDismissDlg((HWND)GetHwnd(), nRetCode); } // end of wxDialog::EndModal // ---------------------------------------------------------------------------- // wxWin event handlers // ---------------------------------------------------------------------------- void wxDialog::OnApply( wxCommandEvent& rEvent ) { if (Validate()) TransferDataFromWindow(); } // end of wxDialog::OnApply // Standard buttons void wxDialog::OnOK( wxCommandEvent& rEvent ) { if ( Validate() && TransferDataFromWindow() ) { EndModal(wxID_OK); } } // end of wxDialog::OnOK void wxDialog::OnCancel( wxCommandEvent& rEvent ) { EndModal(wxID_CANCEL); } // end of wxDialog::OnCancel void wxDialog::OnCloseWindow( wxCloseEvent& rEvent ) { // // We'll send a Cancel message by default, // which may close the dialog. // Check for looping if the Cancel event handler calls Close(). // // Note that if a cancel button and handler aren't present in the dialog, // nothing will happen when you close the dialog via the window manager, or // via Close(). // We wouldn't want to destroy the dialog by default, since the dialog may have been // created on the stack. // However, this does mean that calling dialog->Close() won't delete the dialog // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be // sure to destroy the dialog. // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog. // // // Ugh??? This is not good but until I figure out a global list it'll have to do // static wxList closing; if ( closing.Member(this) ) return; closing.Append(this); wxCommandEvent vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); vCancelEvent.SetEventObject( this ); GetEventHandler()->ProcessEvent(vCancelEvent); // This may close the dialog closing.DeleteObject(this); } // end of wxDialog::OnCloseWindow void wxDialog::OnSysColourChanged( wxSysColourChangedEvent& rEvent ) { SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); Refresh(); } // end of wxDialog::OnSysColourChanged MRESULT wxDialog::OS2WindowProc( WXUINT uMessage , WXWPARAM wParam , WXLPARAM lParam ) { MRESULT rc = 0; bool bProcessed = FALSE; switch (uMessage) { case WM_CLOSE: // // If we can't close, tell the system that we processed the // message - otherwise it would close us // bProcessed = !Close(); break; } if (!bProcessed) rc = wxWindow::OS2WindowProc( uMessage ,wParam ,lParam ); return rc; } // end of wxDialog::OS2WindowProc