1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/dialog.cpp
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"
15 #include "wx/dialog.h"
21 #include "wx/settings.h"
26 #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
)
45 EVT_CLOSE(wxDialog::OnCloseWindow
)
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // this is simply a container for any data we need to implement modality which
53 // allows us to avoid changing wxDialog each time the implementation changes
54 class wxDialogModalData
57 wxDialogModalData(wxDialog
*dialog
) : m_evtLoop(dialog
) { }
70 wxModalEventLoop m_evtLoop
;
73 wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData
);
75 // ============================================================================
77 // ============================================================================
79 // ----------------------------------------------------------------------------
80 // wxDialog construction
81 // ----------------------------------------------------------------------------
85 m_pOldFocus
= (wxWindow
*)NULL
;
87 m_pWindowDisabler
= (wxWindowDisabler
*)NULL
;
89 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
90 } // end of wxDialog::Init
92 bool wxDialog::Create( wxWindow
* pParent
,
94 const wxString
& rsTitle
,
98 const wxString
& rsName
)
101 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG
);
104 // Save focus before doing anything which can potentially change it
106 m_pOldFocus
= FindFocus();
109 // All dialogs should really have this style
111 lStyle
|= wxTAB_TRAVERSAL
;
113 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 #if WXWIN_COMPATIBILITY_2_6
136 wxDialog::wxDialog(wxWindow
*parent
,
137 const wxString
& title
,
138 bool WXUNUSED(modal
),
144 const wxString
& name
)
148 Create(parent
, wxID_ANY
, title
, wxPoint(x
, y
), wxSize(w
, h
), style
, name
);
151 void wxDialog::SetModal(bool WXUNUSED(bFlag
))
153 // nothing to do, obsolete method
154 } // end of wxDialog::SetModal
156 #endif // WXWIN_COMPATIBILITY_2_6
158 wxDialog::~wxDialog()
160 m_isBeingDeleted
= true;
162 // this will also reenable all the other windows for a modal dialog
164 } // end of wxDialog::~wxDialog
167 // By default, pressing escape cancels the dialog
169 void wxDialog::OnCharHook(
175 if (rEvent
.m_keyCode
== WXK_ESCAPE
)
178 // Behaviour changed in 2.0: we'll send a Cancel message
179 // to the dialog instead of Close.
181 wxCommandEvent
vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
185 vCancelEvent
.SetEventObject( this );
186 GetEventHandler()->ProcessEvent(vCancelEvent
);
189 // Ensure that there is another message for this window so the
190 // ShowModal loop will exit and won't get stuck in GetMessage().
192 ::WinPostMsg(GetHwnd(), WM_NULL
, 0, 0);
196 // We didn't process this event.
200 // ----------------------------------------------------------------------------
201 // showing the dialogs
202 // ----------------------------------------------------------------------------
204 #if WXWIN_COMPATIBILITY_2_6
206 bool wxDialog::IsModalShowing() const
209 } // end of wxDialog::IsModalShowing
211 #endif // WXWIN_COMPATIBILITY_2_6
213 wxWindow
*wxDialog::FindSuitableParent() const
215 // first try to use the currently active window
216 HWND hwndFg
= ::WinQueryActiveWindow(HWND_DESKTOP
);
217 wxWindow
*parent
= hwndFg
? wxFindWinFromHandle((WXHWND
)hwndFg
)
221 // next try the main app window
222 parent
= wxTheApp
->GetTopWindow();
225 // finally, check if the parent we found is really suitable
226 if ( !parent
|| parent
== (wxWindow
*)this || !parent
->IsShown() )
228 // don't use this one
235 bool wxDialog::Show( bool bShow
)
237 if ( bShow
== IsShown() )
240 if (!bShow
&& m_modalData
)
242 // we need to do this before calling wxDialogBase version because if we
243 // had disabled other app windows, they must be reenabled right now as
244 // if they stay disabled Windows will activate another window (one
245 // which is enabled, anyhow) when we're hidden in the base class Show()
246 // and we will lose activation
247 m_modalData
->ExitLoop();
249 if (m_pWindowDisabler
)
251 delete m_pWindowDisabler
;
252 m_pWindowDisabler
= NULL
;
259 // this usually will result in TransferDataToWindow() being called
260 // which will change the controls values so do it before showing as
261 // otherwise we could have some flicker
265 wxDialogBase::Show(bShow
);
267 wxString title
= GetTitle();
269 ::WinSetWindowText((HWND
)GetHwnd(), (PSZ
)title
.c_str());
273 // dialogs don't get WM_SIZE message after creation unlike most (all?)
274 // other windows and so could start their life not laid out correctly
275 // if we didn't call Layout() from here
277 // NB: normally we should call it just the first time but doing it
278 // every time is simpler than keeping a flag
283 } // end of wxDialog::Show
286 // Replacement for Show(true) for modal dialogs - returns return code
288 int wxDialog::ShowModal()
290 wxASSERT_MSG( !IsModal(), _T("wxDialog::ShowModal() reentered?") );
292 m_endModalCalled
= false;
296 // EndModal may have been called from InitDialog handler (called from
297 // inside Show()), which would cause an infinite loop if we didn't take it
299 if ( !m_endModalCalled
)
301 // modal dialog needs a parent window, so try to find one
302 wxWindow
*parent
= GetParent();
305 parent
= FindSuitableParent();
308 // remember where the focus was
309 wxWindow
*oldFocus
= m_pOldFocus
;
312 // VZ: do we really want to do this?
316 // We have to remember the HWND because we need to check
317 // the HWND still exists (oldFocus can be garbage when the dialog
318 // exits, if it has been destroyed)
319 HWND hwndOldFocus
= oldFocus
? GetHwndOf(oldFocus
) : NULL
;
323 // Before entering the modal loop, reset the "is in OnIdle()" flag (see
324 // comment in app.cpp)
326 extern bool gbInOnIdle
;
327 bool bWasInOnIdle
= gbInOnIdle
;
331 // enter and run the modal loop
333 wxDialogModalDataTiedPtr
modalData(&m_modalData
,
334 new wxDialogModalData(this));
335 modalData
->RunLoop();
337 gbInOnIdle
= bWasInOnIdle
;
340 // Note that this code MUST NOT access the dialog object's data
341 // in case the object has been deleted (which will be the case
342 // for a modal dialog that has been destroyed before calling EndModal).
343 if ( oldFocus
&& (oldFocus
!= this) && ::WinIsWindow(vHabmain
, hwndOldFocus
))
345 // This is likely to prove that the object still exists
346 if (wxFindWinFromHandle((WXHWND
) hwndOldFocus
) == oldFocus
)
347 oldFocus
->SetFocus();
351 return GetReturnCode();
352 } // end of wxDialog::ShowModal
354 void wxDialog::EndModal(
358 wxASSERT_MSG( IsModal(), _T("EndModal() called for non modal dialog") );
360 m_endModalCalled
= true;
361 SetReturnCode(nRetCode
);
364 } // end of wxDialog::EndModal
366 void wxDialog::EndDialog(int rc
)
374 // ----------------------------------------------------------------------------
375 // wxWin event handlers
376 // ----------------------------------------------------------------------------
378 void wxDialog::OnApply( wxCommandEvent
& WXUNUSED(rEvent
) )
381 TransferDataFromWindow();
382 } // end of wxDialog::OnApply
385 void wxDialog::OnOK( wxCommandEvent
& WXUNUSED(rEvent
) )
387 if ( Validate() && TransferDataFromWindow() )
391 } // end of wxDialog::OnOK
393 void wxDialog::OnCancel( wxCommandEvent
& WXUNUSED(rEvent
) )
395 EndDialog(wxID_CANCEL
);
396 } // end of wxDialog::OnCancel
398 void wxDialog::OnCloseWindow( wxCloseEvent
& WXUNUSED(rEvent
) )
401 // We'll send a Cancel message by default, which may close the dialog.
402 // Check for looping if the Cancel event handler calls Close().
404 // Note that if a cancel button and handler aren't present in the dialog,
405 // nothing will happen when you close the dialog via the window manager, or
407 // We wouldn't want to destroy the dialog by default, since the dialog may have been
408 // created on the stack.
409 // However, this does mean that calling dialog->Close() won't delete the dialog
410 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
411 // sure to destroy the dialog.
412 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
416 // Ugh??? This is not good but until I figure out a global list it'll have to do
418 static wxList closing
;
420 if ( closing
.Member(this) )
423 closing
.Append(this);
425 wxCommandEvent
vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
);
427 vCancelEvent
.SetEventObject( this );
428 GetEventHandler()->ProcessEvent(vCancelEvent
); // This may close the dialog
430 closing
.DeleteObject(this);
431 } // end of wxDialog::OnCloseWindow
433 void wxDialog::OnSysColourChanged( wxSysColourChangedEvent
& WXUNUSED(rEvent
) )
435 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
));
437 } // end of wxDialog::OnSysColourChanged
439 MRESULT
wxDialog::OS2WindowProc( WXUINT uMessage
, WXWPARAM wParam
, WXLPARAM lParam
)
442 bool bProcessed
= false;
448 // If we can't close, tell the system that we processed the
449 // message - otherwise it would close us
451 bProcessed
= !Close();
456 rc
= wxWindow::OS2WindowProc( uMessage
461 } // end of wxDialog::OS2WindowProc