1///////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/dialog.cpp 3// Purpose: wxDialog class 4// Author: David Webster 5// Modified by: 6// Created: 10/14/99 7// RCS-ID: $Id: dialog.cpp 40707 2006-08-20 13:29:42Z SN $ 8// Copyright: (c) David Webster 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#include "wx/dialog.h" 16 17#ifndef WX_PRECOMP 18 #include "wx/utils.h" 19 #include "wx/frame.h" 20 #include "wx/app.h" 21 #include "wx/settings.h" 22 #include "wx/intl.h" 23 #include "wx/log.h" 24#endif 25 26#include "wx/os2/private.h" 27#include "wx/evtloop.h" 28#include "wx/ptr_scpd.h" 29 30#define wxDIALOG_DEFAULT_X 300 31#define wxDIALOG_DEFAULT_Y 300 32 33#define wxDIALOG_DEFAULT_WIDTH 500 34#define wxDIALOG_DEFAULT_HEIGHT 500 35 36IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow) 37 38// ---------------------------------------------------------------------------- 39// wxDialogModalData 40// ---------------------------------------------------------------------------- 41 42// this is simply a container for any data we need to implement modality which 43// allows us to avoid changing wxDialog each time the implementation changes 44class wxDialogModalData 45{ 46public: 47 wxDialogModalData(wxDialog *dialog) : m_evtLoop(dialog) { } 48 49 void RunLoop() 50 { 51 m_evtLoop.Run(); 52 } 53 54 void ExitLoop() 55 { 56 m_evtLoop.Exit(); 57 } 58 59private: 60 wxModalEventLoop m_evtLoop; 61}; 62 63wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData); 64 65// ============================================================================ 66// implementation 67// ============================================================================ 68 69// ---------------------------------------------------------------------------- 70// wxDialog construction 71// ---------------------------------------------------------------------------- 72 73void wxDialog::Init() 74{ 75 m_pOldFocus = (wxWindow *)NULL; 76 m_isShown = false; 77 m_pWindowDisabler = (wxWindowDisabler *)NULL; 78 m_modalData = NULL; 79 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); 80} // end of wxDialog::Init 81 82bool wxDialog::Create( wxWindow* pParent, 83 wxWindowID vId, 84 const wxString& rsTitle, 85 const wxPoint& rPos, 86 const wxSize& rSize, 87 long lStyle, 88 const wxString& rsName ) 89{ 90 Init(); 91 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG); 92 93 // 94 // Save focus before doing anything which can potentially change it 95 // 96 m_pOldFocus = FindFocus(); 97 98 // 99 // All dialogs should really have this style 100 // 101 lStyle |= wxTAB_TRAVERSAL; 102 103 if (!wxTopLevelWindow::Create( pParent 104 ,vId 105 ,rsTitle 106 ,rPos 107 ,rSize 108 ,lStyle 109 ,rsName 110 )) 111 return false; 112 113 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); 114 115 // 116 // Must defer setting the title until after dialog is created and sized 117 // 118 if (!rsTitle.IsNull()) 119 SetTitle(rsTitle); 120 return true; 121} // end of wxDialog::Create 122 123#if WXWIN_COMPATIBILITY_2_6 124 125// deprecated ctor 126wxDialog::wxDialog(wxWindow *parent, 127 const wxString& title, 128 bool WXUNUSED(modal), 129 int x, 130 int y, 131 int w, 132 int h, 133 long style, 134 const wxString& name) 135{ 136 Init(); 137 138 Create(parent, wxID_ANY, title, wxPoint(x, y), wxSize(w, h), style, name); 139} 140 141void wxDialog::SetModal(bool WXUNUSED(bFlag)) 142{ 143 // nothing to do, obsolete method 144} // end of wxDialog::SetModal 145 146#endif // WXWIN_COMPATIBILITY_2_6 147 148wxDialog::~wxDialog() 149{ 150 m_isBeingDeleted = true; 151 152 // this will also reenable all the other windows for a modal dialog 153 Show(false); 154} // end of wxDialog::~wxDialog 155 156// ---------------------------------------------------------------------------- 157// showing the dialogs 158// ---------------------------------------------------------------------------- 159 160#if WXWIN_COMPATIBILITY_2_6 161 162bool wxDialog::IsModalShowing() const 163{ 164 return IsModal(); 165} // end of wxDialog::IsModalShowing 166 167#endif // WXWIN_COMPATIBILITY_2_6 168 169wxWindow *wxDialog::FindSuitableParent() const 170{ 171 // first try to use the currently active window 172 HWND hwndFg = ::WinQueryActiveWindow(HWND_DESKTOP); 173 wxWindow *parent = hwndFg ? wxFindWinFromHandle((WXHWND)hwndFg) 174 : NULL; 175 if ( !parent ) 176 { 177 // next try the main app window 178 parent = wxTheApp->GetTopWindow(); 179 } 180 181 // finally, check if the parent we found is really suitable 182 if ( !parent || parent == (wxWindow *)this || !parent->IsShown() ) 183 { 184 // don't use this one 185 parent = NULL; 186 } 187 188 return parent; 189} 190 191bool wxDialog::Show( bool bShow ) 192{ 193 if ( bShow == IsShown() ) 194 return false; 195 196 if (!bShow && m_modalData ) 197 { 198 // we need to do this before calling wxDialogBase version because if we 199 // had disabled other app windows, they must be reenabled right now as 200 // if they stay disabled Windows will activate another window (one 201 // which is enabled, anyhow) when we're hidden in the base class Show() 202 // and we will lose activation 203 m_modalData->ExitLoop(); 204#if 0 205 if (m_pWindowDisabler) 206 { 207 delete m_pWindowDisabler; 208 m_pWindowDisabler = NULL; 209 } 210#endif 211 } 212 213 if (bShow) 214 { 215 // this usually will result in TransferDataToWindow() being called 216 // which will change the controls values so do it before showing as 217 // otherwise we could have some flicker 218 InitDialog(); 219 } 220 221 wxDialogBase::Show(bShow); 222 223 wxString title = GetTitle(); 224 if (!title.empty()) 225 ::WinSetWindowText((HWND)GetHwnd(), (PSZ)title.c_str()); 226 227 if ( bShow ) 228 { 229 // dialogs don't get WM_SIZE message after creation unlike most (all?) 230 // other windows and so could start their life not laid out correctly 231 // if we didn't call Layout() from here 232 // 233 // NB: normally we should call it just the first time but doing it 234 // every time is simpler than keeping a flag 235 Layout(); 236 } 237 238 return true; 239} // end of wxDialog::Show 240 241// 242// Replacement for Show(true) for modal dialogs - returns return code 243// 244int wxDialog::ShowModal() 245{ 246 wxASSERT_MSG( !IsModal(), _T("wxDialog::ShowModal() reentered?") ); 247 248 m_endModalCalled = false; 249 250 Show(); 251 252 // EndModal may have been called from InitDialog handler (called from 253 // inside Show()), which would cause an infinite loop if we didn't take it 254 // into account 255 if ( !m_endModalCalled ) 256 { 257 // modal dialog needs a parent window, so try to find one 258 wxWindow *parent = GetParent(); 259 if ( !parent ) 260 { 261 parent = FindSuitableParent(); 262 } 263 264 // remember where the focus was 265 wxWindow *oldFocus = m_pOldFocus; 266 if ( !oldFocus ) 267 { 268 // VZ: do we really want to do this? 269 oldFocus = parent; 270 } 271 272 // We have to remember the HWND because we need to check 273 // the HWND still exists (oldFocus can be garbage when the dialog 274 // exits, if it has been destroyed) 275 HWND hwndOldFocus = oldFocus ? GetHwndOf(oldFocus) : NULL; 276 277 278 // 279 // Before entering the modal loop, reset the "is in OnIdle()" flag (see 280 // comment in app.cpp) 281 // 282 extern bool gbInOnIdle; 283 bool bWasInOnIdle = gbInOnIdle; 284 285 gbInOnIdle = false; 286 287 // enter and run the modal loop 288 { 289 wxDialogModalDataTiedPtr modalData(&m_modalData, 290 new wxDialogModalData(this)); 291 modalData->RunLoop(); 292 } 293 gbInOnIdle = bWasInOnIdle; 294 295 // and restore focus 296 // Note that this code MUST NOT access the dialog object's data 297 // in case the object has been deleted (which will be the case 298 // for a modal dialog that has been destroyed before calling EndModal). 299 if ( oldFocus && (oldFocus != this) && ::WinIsWindow(vHabmain, hwndOldFocus)) 300 { 301 // This is likely to prove that the object still exists 302 if (wxFindWinFromHandle((WXHWND) hwndOldFocus) == oldFocus) 303 oldFocus->SetFocus(); 304 } 305 } 306 307 return GetReturnCode(); 308} // end of wxDialog::ShowModal 309 310void wxDialog::EndModal( 311 int nRetCode 312) 313{ 314 wxASSERT_MSG( IsModal(), _T("EndModal() called for non modal dialog") ); 315 316 m_endModalCalled = true; 317 SetReturnCode(nRetCode); 318 319 Hide(); 320} // end of wxDialog::EndModal 321 322MRESULT wxDialog::OS2WindowProc( WXUINT uMessage, WXWPARAM wParam, WXLPARAM lParam ) 323{ 324 MRESULT rc = 0; 325 bool bProcessed = false; 326 327 switch (uMessage) 328 { 329 case WM_CLOSE: 330 // 331 // If we can't close, tell the system that we processed the 332 // message - otherwise it would close us 333 // 334 bProcessed = !Close(); 335 break; 336 } 337 338 if (!bProcessed) 339 rc = wxWindow::OS2WindowProc( uMessage 340 ,wParam 341 ,lParam 342 ); 343 return rc; 344} // end of wxDialog::OS2WindowProc 345