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 wxWindowList wxModalDialogs
;
38 IMPLEMENT_DYNAMIC_CLASS(wxDialog
, wxTopLevelWindow
)
40 BEGIN_EVENT_TABLE(wxDialog
, wxDialogBase
)
41 EVT_BUTTON(wxID_OK
, wxDialog::OnOK
)
42 EVT_BUTTON(wxID_APPLY
, wxDialog::OnApply
)
43 EVT_BUTTON(wxID_CANCEL
, wxDialog::OnCancel
)
44 EVT_CHAR_HOOK(wxDialog::OnCharHook
)
45 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged
)
46 EVT_CLOSE(wxDialog::OnCloseWindow
)
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 // this is simply a container for any data we need to implement modality which
54 // allows us to avoid changing wxDialog each time the implementation changes
55 class wxDialogModalData
58 wxDialogModalData(wxDialog
*dialog
) : m_evtLoop(dialog
) { }
71 wxModalEventLoop m_evtLoop
;
74 wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData
);
76 // ============================================================================
78 // ============================================================================
80 // ----------------------------------------------------------------------------
81 // wxDialog construction
82 // ----------------------------------------------------------------------------
86 m_pOldFocus
= (wxWindow
*)NULL
;
88 m_pWindowDisabler
= (wxWindowDisabler
*)NULL
;
89 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
90 } // end of wxDialog::Init
92 bool wxDialog::Create(
95 , const wxString
& rsTitle
99 , const wxString
& rsName
104 long lWidth
= rSize
.x
;
105 long lHeight
= rSize
.y
;
107 WXDWORD dwExtendedStyle
= 0L;
111 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG
);
114 // Save focus before doing anything which can potentially change it
116 m_pOldFocus
= FindFocus();
119 // All dialogs should really have this style
121 lStyle
|= wxTAB_TRAVERSAL
;
123 if (!wxTopLevelWindow::Create( pParent
132 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
135 // Must defer setting the title until after dialog is created and sized
137 if (!rsTitle
.IsNull())
140 } // end of wxDialog::Create
142 void wxDialog::SetModal(
148 m_windowStyle
|= wxDIALOG_MODAL
;
149 wxModelessWindows
.DeleteObject(this);
153 m_windowStyle
&= ~wxDIALOG_MODAL
;
154 wxModelessWindows
.Append(this);
156 } // end of wxDialog::SetModal
158 wxDialog::~wxDialog()
160 m_isBeingDeleted
= TRUE
;
162 } // end of wxDialog::~wxDialog
165 // By default, pressing escape cancels the dialog
167 void wxDialog::OnCharHook(
173 if (rEvent
.m_keyCode
== WXK_ESCAPE
)
176 // Behaviour changed in 2.0: we'll send a Cancel message
177 // to the dialog instead of Close.
179 wxCommandEvent
vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
183 vCancelEvent
.SetEventObject( this );
184 GetEventHandler()->ProcessEvent(vCancelEvent
);
187 // Ensure that there is another message for this window so the
188 // ShowModal loop will exit and won't get stuck in GetMessage().
190 ::WinPostMsg(GetHwnd(), WM_NULL
, 0, 0);
194 // We didn't process this event.
198 // ----------------------------------------------------------------------------
199 // showing the dialogs
200 // ----------------------------------------------------------------------------
202 bool wxDialog::IsModal() const
204 return (GetWindowStyleFlag() & wxDIALOG_MODAL
) != 0;
205 } // end of wxDialog::IsModal
207 bool wxDialog::IsModalShowing() const
209 return wxModalDialogs
.Find((wxDialog
*)this) != NULL
; // const_cast
210 } // end of wxDialog::IsModalShowing
212 void wxDialog::DoShowModal()
214 wxWindow
* pParent
= GetParent();
215 wxWindow
* pOldFocus
= m_pOldFocus
;
216 HWND hWndOldFocus
= 0;
218 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
219 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
221 wxModalDialogs
.Append(this);
223 hWndOldFocus
= (HWND
)pOldFocus
->GetHWND();
226 // Remember where the focus was
232 hWndOldFocus
= GetHwndOf(pParent
);
236 // Disable all other app windows
238 wxASSERT_MSG(!m_pWindowDisabler
, _T("disabling windows twice?"));
241 // Disables other app windows and window proc message processing
242 // until WinDismissDlg called
244 ::WinProcessDlg((HWND
)GetHwnd());
247 // Before entering the modal loop, reset the "is in OnIdle()" flag (see
248 // comment in app.cpp)
250 extern bool gbInOnIdle
;
251 bool bWasInOnIdle
= gbInOnIdle
;
255 // enter the modal loop
257 wxDialogModalDataTiedPtr
modalData(&m_modalData
,
258 new wxDialogModalData(this));
259 modalData
->RunLoop();
261 gbInOnIdle
= bWasInOnIdle
;
265 // Note that this code MUST NOT access the dialog object's data
266 // in case the object has been deleted (which will be the case
267 // for a modal dialog that has been destroyed before calling EndModal).
269 if (pOldFocus
&& (pOldFocus
!= this) && ::WinIsWindow(vHabmain
, hWndOldFocus
))
272 // This is likely to prove that the object still exists
274 if (wxFindWinFromHandle((WXHWND
) hWndOldFocus
) == pOldFocus
)
275 pOldFocus
->SetFocus();
277 } // end of wxDialog::DoShowModal
286 // If we had disabled other app windows, reenable them back now because
287 // if they stay disabled Windows will activate another window (one
288 // which is enabled, anyhow) and we will lose activation. We really don't
289 // do this in OS/2 since PM does this for us.
291 if (m_pWindowDisabler
)
293 delete m_pWindowDisabler
;
294 m_pWindowDisabler
= NULL
;
299 // ShowModal() may be called for already shown dialog
301 if (!wxDialogBase::Show(bShow
) && !(bShow
&& IsModal()))
312 // Usually will result in TransferDataToWindow() being called
317 if (GetTitle().c_str())
318 ::WinSetWindowText((HWND
)GetHwnd(), GetTitle().c_str());
324 // Modal dialog needs a parent window, so try to find one
328 wxWindow
* pParent
= wxTheApp
->GetTopWindow();
330 if ( pParent
&& pParent
!= this && pParent
->IsShown() )
341 else // end of modal dialog
344 // This will cause IsModalShowing() return FALSE and our local
345 // message loop will terminate
347 wxModalDialogs
.DeleteObject(this);
351 } // end of wxDialog::Show
354 // Replacement for Show(TRUE) for modal dialogs - returns return code
356 int wxDialog::ShowModal()
363 return GetReturnCode();
364 } // end of wxDialog::ShowModal
366 void wxDialog::EndModal(
370 SetReturnCode(nRetCode
);
372 ::WinDismissDlg((HWND
)GetHwnd(), nRetCode
);
373 } // end of wxDialog::EndModal
375 // ----------------------------------------------------------------------------
376 // wxWin event handlers
377 // ----------------------------------------------------------------------------
379 void wxDialog::OnApply(
380 wxCommandEvent
& rEvent
384 TransferDataFromWindow();
385 } // end of wxDialog::OnApply
389 wxCommandEvent
& rEvent
392 if ( Validate() && TransferDataFromWindow() )
396 } // end of wxDialog::OnOK
398 void wxDialog::OnCancel(
399 wxCommandEvent
& rEvent
402 EndModal(wxID_CANCEL
);
403 } // end of wxDialog::OnCancel
405 void wxDialog::OnCloseWindow(
410 // We'll send a Cancel message by default,
411 // which may close the dialog.
412 // Check for looping if the Cancel event handler calls Close().
414 // Note that if a cancel button and handler aren't present in the dialog,
415 // nothing will happen when you close the dialog via the window manager, or
417 // We wouldn't want to destroy the dialog by default, since the dialog may have been
418 // created on the stack.
419 // However, this does mean that calling dialog->Close() won't delete the dialog
420 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
421 // sure to destroy the dialog.
422 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
426 // Ugh??? This is not good but until I figure out a global list it'll have to do
428 static wxList closing
;
430 if ( closing
.Member(this) )
433 closing
.Append(this);
435 wxCommandEvent
vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
);
437 vCancelEvent
.SetEventObject( this );
438 GetEventHandler()->ProcessEvent(vCancelEvent
); // This may close the dialog
440 closing
.DeleteObject(this);
441 } // end of wxDialog::OnCloseWindow
443 void wxDialog::OnSysColourChanged(
444 wxSysColourChangedEvent
& rEvent
447 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
449 } // end of wxDialog::OnSysColourChanged
451 MRESULT
wxDialog::OS2WindowProc(
458 bool bProcessed
= FALSE
;
464 // If we can't close, tell the system that we processed the
465 // message - otherwise it would close us
467 bProcessed
= !Close();
472 rc
= wxWindow::OS2WindowProc( uMessage
477 } // end of wxDialog::OS2WindowProc