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"
28 #define wxDIALOG_DEFAULT_X 300
29 #define wxDIALOG_DEFAULT_Y 300
31 #define wxDIALOG_DEFAULT_WIDTH 500
32 #define wxDIALOG_DEFAULT_HEIGHT 500
34 wxWindowList wxModalDialogs
;
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
)
49 m_pOldFocus
= (wxWindow
*)NULL
;
51 m_pWindowDisabler
= (wxWindowDisabler
*)NULL
;
52 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
53 } // end of wxDialog::Init
55 bool wxDialog::Create(
58 , const wxString
& rsTitle
62 , const wxString
& rsName
67 long lWidth
= rSize
.x
;
68 long lHeight
= rSize
.y
;
70 WXDWORD dwExtendedStyle
= 0L;
74 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG
);
77 // Save focus before doing anything which can potentially change it
79 m_pOldFocus
= FindFocus();
82 // All dialogs should really have this style
84 lStyle
|= wxTAB_TRAVERSAL
;
86 if (!wxTopLevelWindow::Create( pParent
95 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
));
98 // Must defer setting the title until after dialog is created and sized
100 if (!rsTitle
.IsNull())
103 } // end of wxDialog::Create
105 void wxDialog::SetModal(
111 m_windowStyle
|= wxDIALOG_MODAL
;
112 wxModelessWindows
.DeleteObject(this);
116 m_windowStyle
&= ~wxDIALOG_MODAL
;
117 wxModelessWindows
.Append(this);
119 } // end of wxDialog::SetModal
121 wxDialog::~wxDialog()
123 m_isBeingDeleted
= TRUE
;
125 } // end of wxDialog::~wxDialog
128 // By default, pressing escape cancels the dialog
130 void wxDialog::OnCharHook(
136 if (rEvent
.m_keyCode
== WXK_ESCAPE
)
139 // Behaviour changed in 2.0: we'll send a Cancel message
140 // to the dialog instead of Close.
142 wxCommandEvent
vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
146 vCancelEvent
.SetEventObject( this );
147 GetEventHandler()->ProcessEvent(vCancelEvent
);
150 // Ensure that there is another message for this window so the
151 // ShowModal loop will exit and won't get stuck in GetMessage().
153 ::WinPostMsg(GetHwnd(), WM_NULL
, 0, 0);
157 // We didn't process this event.
161 // ----------------------------------------------------------------------------
162 // showing the dialogs
163 // ----------------------------------------------------------------------------
165 bool wxDialog::IsModal() const
167 return (GetWindowStyleFlag() & wxDIALOG_MODAL
) != 0;
168 } // end of wxDialog::IsModal
170 bool wxDialog::IsModalShowing() const
172 return wxModalDialogs
.Find((wxDialog
*)this) != NULL
; // const_cast
173 } // end of wxDialog::IsModalShowing
175 void wxDialog::DoShowModal()
177 wxWindow
* pParent
= GetParent();
178 wxWindow
* pOldFocus
= m_pOldFocus
;
179 HWND hWndOldFocus
= 0;
181 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
182 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
184 wxModalDialogs
.Append(this);
186 hWndOldFocus
= (HWND
)pOldFocus
->GetHWND();
189 // Remember where the focus was
195 hWndOldFocus
= GetHwndOf(pParent
);
199 // Disable all other app windows
201 wxASSERT_MSG(!m_pWindowDisabler
, _T("disabling windows twice?"));
204 // Disables other app windows and window proc message processing
205 // until WinDismissDlg called
207 ::WinProcessDlg((HWND
)GetHwnd());
210 // Before entering the modal loop, reset the "is in OnIdle()" flag (see
211 // comment in app.cpp)
213 extern bool gbInOnIdle
;
214 bool bWasInOnIdle
= gbInOnIdle
;
219 // Enter the modal loop
221 while ( IsModalShowing() )
224 wxMutexGuiLeaveOrEnter();
225 #endif // wxUSE_THREADS
227 while ( !wxTheApp
->Pending() && wxTheApp
->ProcessIdle() )
230 // a message came or no more idle processing to do
231 wxTheApp
->DoMessage();
233 gbInOnIdle
= bWasInOnIdle
;
237 // Note that this code MUST NOT access the dialog object's data
238 // in case the object has been deleted (which will be the case
239 // for a modal dialog that has been destroyed before calling EndModal).
241 if (pOldFocus
&& (pOldFocus
!= this) && ::WinIsWindow(vHabmain
, hWndOldFocus
))
244 // This is likely to prove that the object still exists
246 if (wxFindWinFromHandle((WXHWND
) hWndOldFocus
) == pOldFocus
)
247 pOldFocus
->SetFocus();
249 } // end of wxDialog::DoShowModal
258 // If we had disabled other app windows, reenable them back now because
259 // if they stay disabled Windows will activate another window (one
260 // which is enabled, anyhow) and we will lose activation. We really don't
261 // do this in OS/2 since PM does this for us.
263 if (m_pWindowDisabler
)
265 delete m_pWindowDisabler
;
266 m_pWindowDisabler
= NULL
;
271 // ShowModal() may be called for already shown dialog
273 if (!wxDialogBase::Show(bShow
) && !(bShow
&& IsModal()))
284 // Usually will result in TransferDataToWindow() being called
289 if (GetTitle().c_str())
290 ::WinSetWindowText((HWND
)GetHwnd(), GetTitle().c_str());
296 // Modal dialog needs a parent window, so try to find one
300 wxWindow
* pParent
= wxTheApp
->GetTopWindow();
302 if ( pParent
&& pParent
!= this && pParent
->IsShown() )
313 else // end of modal dialog
316 // This will cause IsModalShowing() return FALSE and our local
317 // message loop will terminate
319 wxModalDialogs
.DeleteObject(this);
323 } // end of wxDialog::Show
326 // Replacement for Show(TRUE) for modal dialogs - returns return code
328 int wxDialog::ShowModal()
335 return GetReturnCode();
336 } // end of wxDialog::ShowModal
338 void wxDialog::EndModal(
342 SetReturnCode(nRetCode
);
344 ::WinDismissDlg((HWND
)GetHwnd(), nRetCode
);
345 } // end of wxDialog::EndModal
347 // ----------------------------------------------------------------------------
348 // wxWin event handlers
349 // ----------------------------------------------------------------------------
351 void wxDialog::OnApply(
352 wxCommandEvent
& rEvent
356 TransferDataFromWindow();
357 } // end of wxDialog::OnApply
361 wxCommandEvent
& rEvent
364 if ( Validate() && TransferDataFromWindow() )
368 } // end of wxDialog::OnOK
370 void wxDialog::OnCancel(
371 wxCommandEvent
& rEvent
374 EndModal(wxID_CANCEL
);
375 } // end of wxDialog::OnCancel
377 void wxDialog::OnCloseWindow(
382 // We'll send a Cancel message by default,
383 // which may close the dialog.
384 // Check for looping if the Cancel event handler calls Close().
386 // Note that if a cancel button and handler aren't present in the dialog,
387 // nothing will happen when you close the dialog via the window manager, or
389 // We wouldn't want to destroy the dialog by default, since the dialog may have been
390 // created on the stack.
391 // However, this does mean that calling dialog->Close() won't delete the dialog
392 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
393 // sure to destroy the dialog.
394 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
398 // Ugh??? This is not good but until I figure out a global list it'll have to do
400 static wxList closing
;
402 if ( closing
.Member(this) )
405 closing
.Append(this);
407 wxCommandEvent
vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
);
409 vCancelEvent
.SetEventObject( this );
410 GetEventHandler()->ProcessEvent(vCancelEvent
); // This may close the dialog
412 closing
.DeleteObject(this);
413 } // end of wxDialog::OnCloseWindow
415 void wxDialog::OnSysColourChanged(
416 wxSysColourChangedEvent
& rEvent
419 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
421 } // end of wxDialog::OnSysColourChanged
423 MRESULT
wxDialog::OS2WindowProc(
430 bool bProcessed
= FALSE
;
436 // If we can't close, tell the system that we processed the
437 // message - otherwise it would close us
439 bProcessed
= !Close();
444 rc
= wxWindow::OS2WindowProc( uMessage
449 } // end of wxDialog::OS2WindowProc