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 // Lists to keep track of windows, so we can disable/enable them
36 wxWindowList wxModalDialogs
;
37 wxWindowList wxModelessWindows
; // Frames and modeless dialogs
38 extern wxList WXDLLEXPORT wxPendingDelete
;
40 IMPLEMENT_DYNAMIC_CLASS(wxDialog
, wxPanel
)
42 BEGIN_EVENT_TABLE(wxDialog
, wxPanel
)
43 EVT_SIZE(wxDialog::OnSize
)
44 EVT_BUTTON(wxID_OK
, wxDialog::OnOK
)
45 EVT_BUTTON(wxID_APPLY
, wxDialog::OnApply
)
46 EVT_BUTTON(wxID_CANCEL
, wxDialog::OnCancel
)
47 EVT_CHAR_HOOK(wxDialog::OnCharHook
)
48 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged
)
49 EVT_CLOSE(wxDialog::OnCloseWindow
)
54 m_pOldFocus
= (wxWindow
*)NULL
;
56 m_pWindowDisabler
= (wxWindowDisabler
*)NULL
;
57 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
));
58 } // end of wxDialog::Init
60 bool wxDialog::Create(
63 , const wxString
& rsTitle
67 , const wxString
& rsName
72 long lWidth
= rSize
.x
;
73 long lHeight
= rSize
.y
;
75 WXDWORD dwExtendedStyle
= 0L;
79 m_pOldFocus
= (wxWindow
*)FindFocus();
81 wxTopLevelWindows
.Append(this);
83 pParent
->AddChild(this);
85 m_windowId
= NewControlId();
89 lX
= wxDIALOG_DEFAULT_X
;
91 lY
= wxDIALOG_DEFAULT_Y
;
92 m_windowStyle
= lStyle
;
94 lWidth
= wxDIALOG_DEFAULT_WIDTH
;
96 lHeight
= wxDIALOG_DEFAULT_HEIGHT
;
99 // All dialogs should really have this style
101 m_windowStyle
|= wxTAB_TRAVERSAL
;
104 // Allows creation of dialogs with & without captions under MSWindows,
105 // resizeable or not (but a resizeable dialog always has caption -
106 // otherwise it would look too strange)
108 if (lStyle
& wxRESIZE_BORDER
)
109 zDlg
= "wxResizeableDialog";
110 else if (lStyle
& wxCAPTION
)
111 zDlg
= "wxCaptionDialog";
113 zDlg
= "wxNoCaptionDialog";
114 OS2Create( GetWinHwnd(pParent
)
128 hWnd
= (HWND
)GetHWND();
133 SubclassWin(GetHWND());
134 ::WinSetWindowText( hWnd
135 ,(PSZ
)rsTitle
.c_str()
137 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
));
139 } // end of wxDialog::Create
141 void wxDialog::SetModal(
146 m_windowStyle
|= wxDIALOG_MODAL
;
147 else if ( m_windowStyle
& wxDIALOG_MODAL
)
148 m_windowStyle
-= wxDIALOG_MODAL
;
150 wxModelessWindows
.DeleteObject(this);
152 wxModelessWindows
.Append(this);
153 } // end of wxDialog::SetModal
155 wxDialog::~wxDialog()
157 m_isBeingDeleted
= TRUE
;
158 wxTopLevelWindows
.DeleteObject(this);
161 wxModelessWindows
.DeleteObject(this);
164 // If this is the last top-level window, exit.
166 if (wxTheApp
&& (wxTopLevelWindows
.Number() == 0))
168 wxTheApp
->SetTopWindow(NULL
);
170 if (wxTheApp
->GetExitOnFrameDelete())
172 ::WinPostMsg(GetHwnd(), WM_QUIT
, 0, 0);
175 } // end of wxDialog::~wxDialog
178 // By default, pressing escape cancels the dialog
180 void wxDialog::OnCharHook(
186 if (rEvent
.m_keyCode
== WXK_ESCAPE
)
189 // Behaviour changed in 2.0: we'll send a Cancel message
190 // to the dialog instead of Close.
192 wxCommandEvent
vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
196 vCancelEvent
.SetEventObject( this );
197 GetEventHandler()->ProcessEvent(vCancelEvent
);
200 // Ensure that there is another message for this window so the
201 // ShowModal loop will exit and won't get stuck in GetMessage().
203 ::WinPostMsg(GetHwnd(), WM_NULL
, 0, 0);
207 // We didn't process this event.
211 void wxDialog::Iconize(
212 bool WXUNUSED(bIconize
)
215 } // end of wxDialog::Iconize
217 bool wxDialog::IsIconized() const
220 } // end of wxDialog::IsIconized
222 void wxDialog::DoSetClientSize(
227 HWND hWnd
= (HWND
) GetHWND();
231 ::WinQueryWindowRect(hWnd
, &vRect
);
232 ::WinQueryWindowRect(hWnd
, &vRect2
);
234 LONG lActualWidth
= vRect2
.xRight
- vRect2
.xLeft
- vRect
.xRight
+ nWidth
;
235 LONG lActualHeight
= vRect2
.yTop
+ vRect2
.yTop
- vRect
.yTop
+ nHeight
;
237 ::WinSetWindowPos( GetHwnd()
246 wxSizeEvent
vEvent( wxSize( lActualWidth
252 vEvent
.SetEventObject( this );
253 GetEventHandler()->ProcessEvent(vEvent
);
254 } // end of wxDialog::DoSetClientSize
256 void wxDialog::DoGetPosition(
263 ::WinQueryWindowRect(GetHwnd(), &vRect
);
267 *pnY
= vRect
.yBottom
; // OS/2's bottom is windows' top???
268 } // end of wxDialog::DoGetPosition
270 bool wxDialog::IsModal() const
272 return (GetWindowStyleFlag() & wxDIALOG_MODAL
) != 0;
273 } // end of wxDialog::IsModal
275 bool wxDialog::IsModalShowing() const
277 return wxModalDialogs
.Find((wxDialog
*)this) != NULL
; // const_cast
278 } // end of wxDialog::IsModalShowing
280 void wxDialog::DoShowModal()
282 wxWindow
* pParent
= GetParent();
283 wxWindow
* pOldFocus
= m_pOldFocus
;
284 HWND hWndOldFocus
= 0;
286 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
287 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
289 wxModalDialogs
.Append(this);
291 hWndOldFocus
= (HWND
)pOldFocus
->GetHWND();
294 // Remember where the focus was
300 hWndOldFocus
= GetHwndOf(pParent
);
304 // Disable all other app windows
306 wxASSERT_MSG(!m_pWindowDisabler
, _T("disabling windows twice?"));
308 m_pWindowDisabler
= new wxWindowDisabler(this);
311 // Enter the modal loop
313 while ( IsModalShowing() )
316 wxMutexGuiLeaveOrEnter();
317 #endif // wxUSE_THREADS
319 while ( !wxTheApp
->Pending() && wxTheApp
->ProcessIdle() )
322 // a message came or no more idle processing to do
323 wxTheApp
->DoMessage();
328 // Note that this code MUST NOT access the dialog object's data
329 // in case the object has been deleted (which will be the case
330 // for a modal dialog that has been destroyed before calling EndModal).
332 if (pOldFocus
&& (pOldFocus
!= this) && ::WinIsWindow(vHabmain
, hWndOldFocus
))
335 // This is likely to prove that the object still exists
337 if (wxFindWinFromHandle((WXHWND
) hWndOldFocus
) == pOldFocus
)
338 pOldFocus
->SetFocus();
340 } // end of wxDialog::DoShowModal
349 // If we had disabled other app windows, reenable them back now because
350 // if they stay disabled Windows will activate another window (one
351 // which is enabled, anyhow) and we will lose activation
353 if (m_pWindowDisabler
)
355 delete m_pWindowDisabler
;
356 m_pWindowDisabler
= NULL
;
361 // ShowModal() may be called for already shown dialog
363 if (!wxDialogBase::Show(bShow
) && !(bShow
&& IsModal()))
374 // Usually will result in TransferDataToWindow() being called
384 // Modal dialog needs a parent window, so try to find one
388 wxWindow
* pParent
= wxTheApp
->GetTopWindow();
390 if ( pParent
&& pParent
!= this && pParent
->IsShown() )
401 else // end of modal dialog
404 // This will cause IsModalShowing() return FALSE and our local
405 // message loop will terminate
407 wxModalDialogs
.DeleteObject(this);
411 } // end of wxDialog::Show
414 // Replacement for Show(TRUE) for modal dialogs - returns return code
416 int wxDialog::ShowModal()
423 return GetReturnCode();
424 } // end of wxDialog::ShowModal
426 void wxDialog::EndModal(
430 SetReturnCode(nRetCode
);
432 } // end of wxDialog::EndModal
434 void wxDialog::OnApply(
435 wxCommandEvent
& rEvent
439 TransferDataFromWindow();
440 } // end of wxDialog::OnApply
444 wxCommandEvent
& rEvent
447 if ( Validate() && TransferDataFromWindow() )
451 } // end of wxDialog::OnOK
453 void wxDialog::OnCancel(
454 wxCommandEvent
& rEvent
457 EndModal(wxID_CANCEL
);
458 } // end of wxDialog::OnCancel
460 void wxDialog::OnCloseWindow(
465 // We'll send a Cancel message by default,
466 // which may close the dialog.
467 // Check for looping if the Cancel event handler calls Close().
469 // Note that if a cancel button and handler aren't present in the dialog,
470 // nothing will happen when you close the dialog via the window manager, or
472 // We wouldn't want to destroy the dialog by default, since the dialog may have been
473 // created on the stack.
474 // However, this does mean that calling dialog->Close() won't delete the dialog
475 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
476 // sure to destroy the dialog.
477 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
481 // Ugh??? This is not good but until I figure out a global list it'll have to do
483 static wxList closing
;
485 if ( closing
.Member(this) )
488 closing
.Append(this);
490 wxCommandEvent
vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
);
492 vCancelEvent
.SetEventObject( this );
493 GetEventHandler()->ProcessEvent(vCancelEvent
); // This may close the dialog
495 closing
.DeleteObject(this);
496 } // end of wxDialog::OnCloseWindow
499 // Destroy the window (delayed, if a managed window)
501 bool wxDialog::Destroy()
503 wxCHECK_MSG( !wxPendingDelete
.Member(this), FALSE
,
504 _T("wxDialog destroyed twice") );
505 wxPendingDelete
.Append(this);
507 } // end of wxDialog::Destroy
509 void wxDialog::OnSysColourChanged(
510 wxSysColourChangedEvent
& rEvent
513 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
));
515 } // end of wxDialog::OnSysColourChanged
517 MRESULT
wxDialog::OS2WindowProc(
524 bool bProcessed
= FALSE
;
530 // If we can't close, tell the system that we processed the
531 // message - otherwise it would close us
533 bProcessed
= !Close();
538 rc
= wxWindow::OS2WindowProc( uMessage
543 } // end of wxDialog::OS2WindowProc