1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxDialog class 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  16 #include "wx/dialog.h" 
  20 #include "wx/settings.h" 
  25 #include "wx/os2/private.h" 
  27 #include "wx/evtloop.h" 
  28 #include "wx/ptr_scpd.h" 
  30 #define wxDIALOG_DEFAULT_X 300 
  31 #define wxDIALOG_DEFAULT_Y 300 
  33 #define wxDIALOG_DEFAULT_WIDTH 500 
  34 #define wxDIALOG_DEFAULT_HEIGHT 500 
  36 IMPLEMENT_DYNAMIC_CLASS(wxDialog
, wxTopLevelWindow
) 
  38 BEGIN_EVENT_TABLE(wxDialog
, wxDialogBase
) 
  39     EVT_BUTTON(wxID_OK
, wxDialog::OnOK
) 
  40     EVT_BUTTON(wxID_APPLY
, wxDialog::OnApply
) 
  41     EVT_BUTTON(wxID_CANCEL
, wxDialog::OnCancel
) 
  42     EVT_CHAR_HOOK(wxDialog::OnCharHook
) 
  43     EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged
) 
  44     EVT_CLOSE(wxDialog::OnCloseWindow
) 
  47 // ---------------------------------------------------------------------------- 
  49 // ---------------------------------------------------------------------------- 
  51 // this is simply a container for any data we need to implement modality which 
  52 // allows us to avoid changing wxDialog each time the implementation changes 
  53 class wxDialogModalData
 
  56     wxDialogModalData(wxDialog 
*dialog
) : m_evtLoop(dialog
) { } 
  69     wxModalEventLoop m_evtLoop
; 
  72 wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData
); 
  74 // ============================================================================ 
  76 // ============================================================================ 
  78 // ---------------------------------------------------------------------------- 
  79 // wxDialog construction 
  80 // ---------------------------------------------------------------------------- 
  84     m_pOldFocus 
= (wxWindow 
*)NULL
; 
  86     m_pWindowDisabler 
= (wxWindowDisabler 
*)NULL
; 
  88     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
  89 } // end of wxDialog::Init 
  91 bool wxDialog::Create( 
  94 , const wxString
&                   rsTitle
 
  98 , const wxString
&                   rsName
 
 102     SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG
); 
 105     // Save focus before doing anything which can potentially change it 
 107     m_pOldFocus 
= FindFocus(); 
 110     // All dialogs should really have this style 
 112     lStyle 
|= wxTAB_TRAVERSAL
; 
 114     if (!wxTopLevelWindow::Create( pParent
 
 123     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
 126     // Must defer setting the title until after dialog is created and sized 
 128     if (!rsTitle
.IsNull()) 
 131 } // end of wxDialog::Create 
 133 void wxDialog::SetModal( 
 139         m_windowStyle 
|= wxDIALOG_MODAL 
; 
 140         wxModelessWindows
.DeleteObject(this); 
 144         m_windowStyle 
&= ~wxDIALOG_MODAL 
; 
 145         wxModelessWindows
.Append(this); 
 147 } // end of wxDialog::SetModal 
 149 wxDialog::~wxDialog() 
 151     m_isBeingDeleted 
= TRUE
; 
 153 } // end of wxDialog::~wxDialog 
 156 // By default, pressing escape cancels the dialog 
 158 void wxDialog::OnCharHook( 
 164         if (rEvent
.m_keyCode 
== WXK_ESCAPE
) 
 167             // Behaviour changed in 2.0: we'll send a Cancel message 
 168             // to the dialog instead of Close. 
 170             wxCommandEvent          
vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
 
 174             vCancelEvent
.SetEventObject( this ); 
 175             GetEventHandler()->ProcessEvent(vCancelEvent
); 
 178             // Ensure that there is another message for this window so the 
 179             // ShowModal loop will exit and won't get stuck in GetMessage(). 
 181             ::WinPostMsg(GetHwnd(), WM_NULL
, 0, 0); 
 185     // We didn't process this event. 
 189 // ---------------------------------------------------------------------------- 
 190 // showing the dialogs 
 191 // ---------------------------------------------------------------------------- 
 193 bool wxDialog::IsModal() const 
 195     return (GetWindowStyleFlag() & wxDIALOG_MODAL
) != 0; 
 196 } // end of wxDialog::IsModal 
 198 bool wxDialog::IsModalShowing() const 
 200     return m_modalData 
!= NULL
; // const_cast 
 201 } // end of wxDialog::IsModalShowing 
 203 void wxDialog::DoShowModal() 
 205     wxWindow
*                       pParent 
= GetParent(); 
 206     wxWindow
*                       pOldFocus 
= m_pOldFocus
; 
 207     HWND                            hWndOldFocus 
= 0; 
 209     wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") ); 
 210     wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") ); 
 213         hWndOldFocus 
= (HWND
)pOldFocus
->GetHWND(); 
 216     // Remember where the focus was 
 222             hWndOldFocus 
= GetHwndOf(pParent
); 
 226     // Disable all other app windows 
 228     wxASSERT_MSG(!m_pWindowDisabler
, _T("disabling windows twice?")); 
 231     // Before entering the modal loop, reset the "is in OnIdle()" flag (see 
 232     // comment in app.cpp) 
 234     extern bool                     gbInOnIdle
; 
 235     bool                            bWasInOnIdle 
= gbInOnIdle
; 
 239     // enter the modal loop 
 241         wxDialogModalDataTiedPtr 
modalData(&m_modalData
, 
 242                                            new wxDialogModalData(this)); 
 243         modalData
->RunLoop(); 
 245     gbInOnIdle 
= bWasInOnIdle
; 
 249     // Note that this code MUST NOT access the dialog object's data 
 250     // in case the object has been deleted (which will be the case 
 251     // for a modal dialog that has been destroyed before calling EndModal). 
 253     if (pOldFocus 
&& (pOldFocus 
!= this) && ::WinIsWindow(vHabmain
, hWndOldFocus
)) 
 256         // This is likely to prove that the object still exists 
 258         if (wxFindWinFromHandle((WXHWND
) hWndOldFocus
) == pOldFocus
) 
 259             pOldFocus
->SetFocus(); 
 261 } // end of wxDialog::DoShowModal 
 270         // If we had disabled other app windows, reenable them back now because 
 271         // if they stay disabled Windows will activate another window (one 
 272         // which is enabled, anyhow) and we will lose activation.  We really don't 
 273         // do this in OS/2 since PM does this for us. 
 275         if (m_pWindowDisabler
) 
 277             delete m_pWindowDisabler
; 
 278             m_pWindowDisabler 
= NULL
; 
 281             m_modalData
->ExitLoop(); 
 285     // ShowModal() may be called for already shown dialog 
 287     if (!wxDialogBase::Show(bShow
) && !(bShow 
&& IsModal())) 
 297         // dialogs don't get WM_SIZE message after creation unlike most (all?) 
 298         // other windows and so could start their life non laid out correctly 
 299         // if we didn't call Layout() from here 
 301         // NB: normally we should call it just the first time but doing it 
 302         //     every time is simpler than keeping a flag 
 306         // Usually will result in TransferDataToWindow() being called 
 311     if (GetTitle().c_str()) 
 312         ::WinSetWindowText((HWND
)GetHwnd(), GetTitle().c_str()); 
 318             // Modal dialog needs a parent window, so try to find one 
 322                 wxWindow
*           pParent 
= wxTheApp
->GetTopWindow(); 
 324                 if ( pParent 
&& pParent 
!= this && pParent
->IsShown() ) 
 337 } // end of wxDialog::Show 
 340 // Replacement for Show(TRUE) for modal dialogs - returns return code 
 342 int wxDialog::ShowModal() 
 349     return GetReturnCode(); 
 350 } // end of wxDialog::ShowModal 
 352 void wxDialog::EndModal( 
 356     SetReturnCode(nRetCode
); 
 358 } // end of wxDialog::EndModal 
 360 // ---------------------------------------------------------------------------- 
 361 // wxWin event handlers 
 362 // ---------------------------------------------------------------------------- 
 364 void wxDialog::OnApply( 
 365   wxCommandEvent
&                   rEvent
 
 369         TransferDataFromWindow(); 
 370 } // end of wxDialog::OnApply 
 374   wxCommandEvent
&                   rEvent
 
 377     if ( Validate() && TransferDataFromWindow() ) 
 381 } // end of wxDialog::OnOK 
 383 void wxDialog::OnCancel( 
 384   wxCommandEvent
&                   rEvent
 
 387     EndModal(wxID_CANCEL
); 
 388 } // end of wxDialog::OnCancel 
 390 void wxDialog::OnCloseWindow( 
 395     // We'll send a Cancel message by default, 
 396     // which may close the dialog. 
 397     // Check for looping if the Cancel event handler calls Close(). 
 399     // Note that if a cancel button and handler aren't present in the dialog, 
 400     // nothing will happen when you close the dialog via the window manager, or 
 402     // We wouldn't want to destroy the dialog by default, since the dialog may have been 
 403     // created on the stack. 
 404     // However, this does mean that calling dialog->Close() won't delete the dialog 
 405     // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be 
 406     // sure to destroy the dialog. 
 407     // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog. 
 411     // Ugh???  This is not good but until I figure out a global list it'll have to do 
 413     static wxList closing
; 
 415     if ( closing
.Member(this) ) 
 418     closing
.Append(this); 
 420     wxCommandEvent                  
vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
 422     vCancelEvent
.SetEventObject( this ); 
 423     GetEventHandler()->ProcessEvent(vCancelEvent
); // This may close the dialog 
 425     closing
.DeleteObject(this); 
 426 } // end of wxDialog::OnCloseWindow 
 428 void wxDialog::OnSysColourChanged( 
 429   wxSysColourChangedEvent
&          rEvent
 
 432     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 434 } // end of wxDialog::OnSysColourChanged 
 436 MRESULT 
wxDialog::OS2WindowProc( 
 443     bool                            bProcessed 
= FALSE
; 
 449             // If we can't close, tell the system that we processed the 
 450             // message - otherwise it would close us 
 452             bProcessed 
= !Close(); 
 457         rc 
= wxWindow::OS2WindowProc( uMessage
 
 462 } // end of wxDialog::OS2WindowProc