]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dialog.cpp
fixed 2 year old bug in wxBaseArray::operator=() (who the hell is/was RO who introduc...
[wxWidgets.git] / src / msw / dialog.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
b6c588e1 2// Name: src/msw/dialog.cpp
2bda0e17
KB
3// Purpose: wxDialog class
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
dc1c4b62 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
b6c588e1
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
b6c588e1 21 #pragma implementation "dialog.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
b6c588e1 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
b6c588e1
VZ
32 #include "wx/dialog.h"
33 #include "wx/utils.h"
34 #include "wx/frame.h"
35 #include "wx/app.h"
36 #include "wx/settings.h"
37 #include "wx/intl.h"
38 #include "wx/log.h"
2bda0e17
KB
39#endif
40
41#include "wx/msw/private.h"
dbda9e86 42#include "wx/log.h"
2bda0e17 43
47d67540 44#if wxUSE_COMMON_DIALOGS
b6c588e1 45 #include <commdlg.h>
2bda0e17
KB
46#endif
47
b6c588e1
VZ
48// ----------------------------------------------------------------------------
49// constants
50// ----------------------------------------------------------------------------
51
52// default dialog pos and size
53
2bda0e17
KB
54#define wxDIALOG_DEFAULT_X 300
55#define wxDIALOG_DEFAULT_Y 300
56
b6c588e1
VZ
57#define wxDIALOG_DEFAULT_WIDTH 500
58#define wxDIALOG_DEFAULT_HEIGHT 500
59
60// ----------------------------------------------------------------------------
61// globals
62// ----------------------------------------------------------------------------
63
64// all objects to be deleted during next idle processing - from window.cpp
cde9f08e 65extern wxList WXDLLEXPORT wxPendingDelete;
2bda0e17 66
b6c588e1
VZ
67// all frames and modeless dialogs - not static, used in frame.cpp, mdi.cpp &c
68wxWindowList wxModelessWindows;
69
70// all modal dialogs currently shown
71static wxWindowList wxModalDialogs;
72
73// ----------------------------------------------------------------------------
74// wxWin macros
75// ----------------------------------------------------------------------------
76
1b6452df
VZ
77IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxPanel)
78
79BEGIN_EVENT_TABLE(wxDialog, wxPanel)
1b6452df
VZ
80 EVT_BUTTON(wxID_OK, wxDialog::OnOK)
81 EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
82 EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
b6c588e1 83
1b6452df 84 EVT_CHAR_HOOK(wxDialog::OnCharHook)
b6c588e1 85
1b6452df 86 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
b6c588e1 87
1b6452df
VZ
88 EVT_CLOSE(wxDialog::OnCloseWindow)
89END_EVENT_TABLE()
2bda0e17 90
b6c588e1
VZ
91// ============================================================================
92// implementation
93// ============================================================================
94
95// ----------------------------------------------------------------------------
96// wxDialog construction
97// ----------------------------------------------------------------------------
98
b0a6bb75 99void wxDialog::Init()
2bda0e17 100{
52a07708 101 m_oldFocus = (wxWindow *)NULL;
b0a6bb75 102
b6c588e1 103 m_isShown = FALSE;
2bda0e17 104
b0a6bb75
VZ
105 m_windowDisabler = (wxWindowDisabler *)NULL;
106
b6c588e1 107 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
2bda0e17
KB
108}
109
b3daa5a3
VZ
110bool wxDialog::Create(wxWindow *parent,
111 wxWindowID id,
462e2437
VZ
112 const wxString& title,
113 const wxPoint& pos,
114 const wxSize& size,
115 long style,
116 const wxString& name)
2bda0e17 117{
b0a6bb75
VZ
118 Init();
119
abceee76
VZ
120 m_oldFocus = FindFocus();
121
462e2437 122 SetName(name);
bd9d76cb 123
f6bcfd97 124 wxTopLevelWindows.Append(this);
2bda0e17 125
b3daa5a3
VZ
126 if ( parent )
127 parent->AddChild(this);
2bda0e17 128
462e2437
VZ
129 if ( id == -1 )
130 m_windowId = (int)NewControlId();
131 else
132 m_windowId = id;
133
134 int x = pos.x;
135 int y = pos.y;
136 int width = size.x;
137 int height = size.y;
138
b6c588e1
VZ
139 if (x < 0)
140 x = wxDIALOG_DEFAULT_X;
141 if (y < 0)
142 y = wxDIALOG_DEFAULT_Y;
462e2437
VZ
143
144 m_windowStyle = style;
145
462e2437 146 if (width < 0)
b6c588e1 147 width = wxDIALOG_DEFAULT_WIDTH;
462e2437 148 if (height < 0)
b6c588e1 149 height = wxDIALOG_DEFAULT_HEIGHT;
462e2437 150
706bb5f9
JS
151 // All dialogs should really have this style
152 m_windowStyle |= wxTAB_TRAVERSAL;
153
462e2437
VZ
154 WXDWORD extendedStyle = MakeExtendedStyle(m_windowStyle);
155 if (m_windowStyle & wxSTAY_ON_TOP)
156 extendedStyle |= WS_EX_TOPMOST;
157
4204da65
JS
158#ifndef __WIN16__
159 if (m_exStyle & wxDIALOG_EX_CONTEXTHELP)
160 extendedStyle |= WS_EX_CONTEXTHELP;
161#endif
b3daa5a3 162
462e2437
VZ
163 // Allows creation of dialogs with & without captions under MSWindows,
164 // resizeable or not (but a resizeable dialog always has caption -
165 // otherwise it would look too strange)
837e5743 166 const wxChar *dlg;
257bf510 167 if ( style & wxRESIZE_BORDER )
223d09f6 168 dlg = wxT("wxResizeableDialog");
462e2437 169 else if ( style & wxCAPTION )
223d09f6 170 dlg = wxT("wxCaptionDialog");
462e2437 171 else
223d09f6 172 dlg = wxT("wxNoCaptionDialog");
462e2437
VZ
173 MSWCreate(m_windowId, parent, NULL, this, NULL,
174 x, y, width, height,
175 0, // style is not used if we have dlg template
176 dlg,
177 extendedStyle);
2bda0e17 178
462e2437 179 HWND hwnd = (HWND)GetHWND();
2bda0e17 180
462e2437
VZ
181 if ( !hwnd )
182 {
f6bcfd97 183 wxFAIL_MSG(_("Failed to create dialog. You probably forgot to include wx/msw/wx.rc in your resources."));
2bda0e17 184
462e2437
VZ
185 return FALSE;
186 }
2bda0e17 187
462e2437 188 SubclassWin(GetHWND());
bd9d76cb 189
462e2437 190 SetWindowText(hwnd, title);
2bda0e17 191
462e2437 192 return TRUE;
2bda0e17
KB
193}
194
c4d305b7
VZ
195bool wxDialog::EnableCloseButton(bool enable)
196{
197 // get system (a.k.a. window) menu
198 HMENU hmenu = ::GetSystemMenu(GetHwnd(), FALSE /* get it */);
199 if ( !hmenu )
200 {
201 wxLogLastError(_T("GetSystemMenu"));
202
203 return FALSE;
204 }
205
206 // enabling/disabling the close item from it also automatically
207 // disables/enabling the close title bar button
208 if ( !::EnableMenuItem(hmenu, SC_CLOSE,
209 MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED)) )
210 {
211 wxLogLastError(_T("DeleteMenu(SC_CLOSE)"));
212
213 return FALSE;
214 }
215
216 // update appearance immediately
217 if ( !::DrawMenuBar(GetHwnd()) )
218 {
219 wxLogLastError(_T("DrawMenuBar"));
220 }
221
222 return TRUE;
223}
224
debe6624 225void wxDialog::SetModal(bool flag)
2bda0e17 226{
b6c588e1
VZ
227 if ( flag )
228 {
229 m_windowStyle |= wxDIALOG_MODAL;
230
231 wxModelessWindows.DeleteObject(this);
232 }
233 else
234 {
235 m_windowStyle &= ~wxDIALOG_MODAL;
236
237 wxModelessWindows.Append(this);
238 }
2bda0e17
KB
239}
240
241wxDialog::~wxDialog()
242{
b6c588e1 243 m_isBeingDeleted = TRUE;
2bda0e17 244
b6c588e1 245 wxTopLevelWindows.DeleteObject(this);
2bda0e17 246
b0a6bb75 247 // this will also reenable all the other windows for a modal dialog
b6c588e1 248 Show(FALSE);
edccf428 249
b6c588e1
VZ
250 if ( !IsModal() )
251 wxModelessWindows.DeleteObject(this);
2bda0e17 252
b6c588e1
VZ
253 // If this is the last top-level window, exit.
254 if ( wxTheApp && (wxTopLevelWindows.Number() == 0) )
2bda0e17 255 {
b6c588e1
VZ
256 wxTheApp->SetTopWindow(NULL);
257
258 if ( wxTheApp->GetExitOnFrameDelete() )
259 {
260 ::PostQuitMessage(0);
261 }
2bda0e17 262 }
2bda0e17
KB
263}
264
b6c588e1
VZ
265// ----------------------------------------------------------------------------
266// kbd handling
267// ----------------------------------------------------------------------------
268
2bda0e17
KB
269// By default, pressing escape cancels the dialog
270void wxDialog::OnCharHook(wxKeyEvent& event)
271{
cbc66a27 272 if (GetHWND())
2bda0e17 273 {
cbc66a27
VZ
274 // "Esc" works as an accelerator for the "Cancel" button, but it
275 // shouldn't close the dialog which doesn't have any cancel button
276 if ( (event.m_keyCode == WXK_ESCAPE) && FindWindow(wxID_CANCEL) )
277 {
278 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
279 cancelEvent.SetEventObject( this );
280 GetEventHandler()->ProcessEvent(cancelEvent);
281
282 // ensure that there is another message for this window so the
283 // ShowModal loop will exit and won't get stuck in GetMessage().
284 ::PostMessage(GetHwnd(), WM_NULL, 0, 0);
285
286 return;
287 }
2bda0e17 288 }
cbc66a27
VZ
289
290 // We didn't process this event.
291 event.Skip();
2bda0e17
KB
292}
293
b6c588e1
VZ
294// ----------------------------------------------------------------------------
295// Windows dialog boxes can't be iconized
296// ----------------------------------------------------------------------------
2bda0e17 297
debe6624 298void wxDialog::Iconize(bool WXUNUSED(iconize))
2bda0e17 299{
2bda0e17
KB
300}
301
a23fd0e1 302bool wxDialog::IsIconized() const
2bda0e17 303{
b6c588e1 304 return FALSE;
2bda0e17
KB
305}
306
b6c588e1
VZ
307// ----------------------------------------------------------------------------
308// size/position handling
309// ----------------------------------------------------------------------------
310
721b32e0 311void wxDialog::DoSetClientSize(int width, int height)
2bda0e17 312{
b6c588e1
VZ
313 HWND hWnd = (HWND) GetHWND();
314 RECT rect;
315 ::GetClientRect(hWnd, &rect);
2bda0e17 316
b6c588e1
VZ
317 RECT rect2;
318 GetWindowRect(hWnd, &rect2);
2bda0e17 319
b6c588e1
VZ
320 // Find the difference between the entire window (title bar and all)
321 // and the client area; add this to the new client size to move the
322 // window
323 int actual_width = rect2.right - rect2.left - rect.right + width;
324 int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
2bda0e17 325
b6c588e1 326 MoveWindow(hWnd, rect2.left, rect2.top, actual_width, actual_height, TRUE);
debe6624 327
b6c588e1
VZ
328 wxSizeEvent event(wxSize(actual_width, actual_height), m_windowId);
329 event.SetEventObject( this );
330 GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
331}
332
b6c588e1 333void wxDialog::DoGetPosition(int *x, int *y) const
2bda0e17 334{
b6c588e1
VZ
335 RECT rect;
336 GetWindowRect(GetHwnd(), &rect);
2bda0e17 337
b6c588e1
VZ
338 if ( x )
339 *x = rect.left;
340 if ( y )
341 *y = rect.top;
2bda0e17
KB
342}
343
b6c588e1
VZ
344// ----------------------------------------------------------------------------
345// showing the dialogs
346// ----------------------------------------------------------------------------
22cf5fec
VZ
347
348bool wxDialog::IsModal() const
349{
b6c588e1 350 return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0;
2bda0e17
KB
351}
352
b6c588e1 353bool wxDialog::IsModalShowing() const
2bda0e17 354{
b6c588e1 355 return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
2bda0e17
KB
356}
357
b6c588e1 358void wxDialog::DoShowModal()
2bda0e17 359{
b6c588e1 360 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
f6bcfd97 361 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
b6c588e1
VZ
362
363 wxModalDialogs.Append(this);
364
365 wxWindow *parent = GetParent();
366
f6bcfd97 367 wxWindow* oldFocus = m_oldFocus;
b6c588e1 368
f6bcfd97
BP
369 // We have to remember the HWND because we need to check
370 // the HWND still exists (oldFocus can be garbage when the dialog
371 // exits, if it has been destroyed)
372 HWND hwndOldFocus = 0;
373 if (oldFocus)
374 hwndOldFocus = (HWND) oldFocus->GetHWND();
b6c588e1 375
b0a6bb75
VZ
376 // remember where the focus was
377 if ( !oldFocus )
b6c588e1 378 {
b0a6bb75
VZ
379 oldFocus = parent;
380 if ( parent )
381 hwndOldFocus = GetHwndOf(parent);
382 }
f6bcfd97 383
b0a6bb75
VZ
384 // disable all other app windows
385 wxASSERT_MSG( !m_windowDisabler, _T("disabling windows twice?") );
f6bcfd97 386
b0a6bb75
VZ
387 m_windowDisabler = new wxWindowDisabler(this);
388
389 // enter the modal loop
390 while ( IsModalShowing() )
391 {
b6c588e1 392#if wxUSE_THREADS
b0a6bb75 393 wxMutexGuiLeaveOrEnter();
b6c588e1
VZ
394#endif // wxUSE_THREADS
395
b0a6bb75
VZ
396 while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() )
397 ;
b6c588e1 398
b0a6bb75
VZ
399 // a message came or no more idle processing to do
400 wxTheApp->DoMessage();
b6c588e1
VZ
401 }
402
b6c588e1 403 // and restore focus
f6bcfd97
BP
404 // Note that this code MUST NOT access the dialog object's data
405 // in case the object has been deleted (which will be the case
406 // for a modal dialog that has been destroyed before calling EndModal).
407 if ( oldFocus && (oldFocus != this) && ::IsWindow(hwndOldFocus))
b6c588e1 408 {
f6bcfd97
BP
409 // This is likely to prove that the object still exists
410 if (wxFindWinFromHandle((WXHWND) hwndOldFocus) == oldFocus)
411 oldFocus->SetFocus();
b6c588e1 412 }
2bda0e17
KB
413}
414
b6c588e1 415bool wxDialog::Show(bool show)
2bda0e17 416{
abceee76 417 if ( !show )
86ad564e 418 {
b0a6bb75
VZ
419 // if we had disabled other app windows, reenable them back now because
420 // if they stay disabled Windows will activate another window (one
421 // which is enabled, anyhow) and we will lose activation
422 if ( m_windowDisabler )
86ad564e 423 {
b0a6bb75
VZ
424 delete m_windowDisabler;
425 m_windowDisabler = NULL;
86ad564e
JS
426 }
427 }
428
abceee76
VZ
429 // ShowModal() may be called for already shown dialog
430 if ( !wxDialogBase::Show(show) && !(show && IsModal()) )
b6c588e1
VZ
431 {
432 // nothing to do
433 return FALSE;
434 }
2bda0e17 435
b6c588e1
VZ
436 if ( show )
437 {
438 // usually will result in TransferDataToWindow() being called
439 InitDialog();
440 }
2bda0e17 441
b6c588e1
VZ
442 if ( IsModal() )
443 {
444 if ( show )
445 {
f6bcfd97
BP
446 // modal dialog needs a parent window, so try to find one
447 if ( !GetParent() )
448 {
449 wxWindow *parent = wxTheApp->GetTopWindow();
450 if ( parent && parent != this && parent->IsShown() )
451 {
452 // use it
453 m_parent = parent;
e5f741e5
VZ
454
455 // VZ: to make dialog behave properly we should reparent
456 // the dialog for Windows as well - unfortunately,
457 // following the docs for SetParent() results in this
458 // code which plainly doesn't work
459#if 0
460 long dwStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE);
461 dwStyle &= ~WS_POPUP;
462 dwStyle |= WS_CHILD;
463 ::SetWindowLong(GetHwnd(), GWL_STYLE, dwStyle);
464 ::SetParent(GetHwnd(), GetHwndOf(parent));
465#endif // 0
f6bcfd97
BP
466 }
467 }
468
b6c588e1
VZ
469 DoShowModal();
470 }
471 else // end of modal dialog
472 {
473 // this will cause IsModalShowing() return FALSE and our local
474 // message loop will terminate
475 wxModalDialogs.DeleteObject(this);
476 }
477 }
2bda0e17 478
b6c588e1 479 return TRUE;
2bda0e17
KB
480}
481
f6bcfd97 482// a special version for Show(TRUE) for modal dialogs which returns return code
a23fd0e1 483int wxDialog::ShowModal()
2bda0e17 484{
f6bcfd97 485 if ( !IsModal() )
5e1febfa 486 {
f6bcfd97 487 SetModal(TRUE);
5e1febfa
VZ
488 }
489
b6c588e1 490 Show(TRUE);
5e1febfa 491
b6c588e1 492 return GetReturnCode();
2bda0e17
KB
493}
494
b6c588e1
VZ
495// NB: this function (surprizingly) may be called for both modal and modeless
496// dialogs and should work for both of them
2bda0e17
KB
497void wxDialog::EndModal(int retCode)
498{
b6c588e1 499 SetReturnCode(retCode);
6a088435 500
b6c588e1 501 Show(FALSE);
2bda0e17
KB
502}
503
b6c588e1
VZ
504// ----------------------------------------------------------------------------
505// wxWin event handlers
506// ----------------------------------------------------------------------------
2bda0e17
KB
507
508// Standard buttons
33ac7e6f 509void wxDialog::OnOK(wxCommandEvent& WXUNUSED(event))
2bda0e17 510{
dc1c4b62
VZ
511 if ( Validate() && TransferDataFromWindow() )
512 {
b6c588e1 513 EndModal(wxID_OK);
dc1c4b62 514 }
2bda0e17
KB
515}
516
33ac7e6f 517void wxDialog::OnApply(wxCommandEvent& WXUNUSED(event))
2bda0e17 518{
b6c588e1
VZ
519 if ( Validate() )
520 TransferDataFromWindow();
521
522 // TODO probably need to disable the Apply button until things change again
2bda0e17
KB
523}
524
33ac7e6f 525void wxDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
2bda0e17 526{
b6c588e1 527 EndModal(wxID_CANCEL);
2bda0e17
KB
528}
529
33ac7e6f 530void wxDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
2bda0e17 531{
b6c588e1 532 // We'll send a Cancel message by default, which may close the dialog.
e3065973
JS
533 // Check for looping if the Cancel event handler calls Close().
534
535 // Note that if a cancel button and handler aren't present in the dialog,
536 // nothing will happen when you close the dialog via the window manager, or
b6c588e1
VZ
537 // via Close(). We wouldn't want to destroy the dialog by default, since
538 // the dialog may have been created on the stack. However, this does mean
539 // that calling dialog->Close() won't delete the dialog unless the handler
540 // for wxID_CANCEL does so. So use Destroy() if you want to be sure to
541 // destroy the dialog. The default OnCancel (above) simply ends a modal
542 // dialog, and hides a modeless dialog.
543
544 // VZ: this is horrible and MT-unsafe. Can't we reuse some of these global
545 // lists here? don't dare to change it now, but should be done later!
2bda0e17 546 static wxList closing;
bd9d76cb 547
2bda0e17 548 if ( closing.Member(this) )
e3065973 549 return;
bd9d76cb 550
2bda0e17 551 closing.Append(this);
bd9d76cb 552
387a3b02
JS
553 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
554 cancelEvent.SetEventObject( this );
e3065973 555 GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
2bda0e17
KB
556
557 closing.DeleteObject(this);
e3065973 558}
2bda0e17 559
e3065973 560// Destroy the window (delayed, if a managed window)
a23fd0e1 561bool wxDialog::Destroy()
e3065973 562{
b6c588e1
VZ
563 wxCHECK_MSG( !wxPendingDelete.Member(this), FALSE,
564 _T("wxDialog destroyed twice") );
565
e3065973 566 wxPendingDelete.Append(this);
2bda0e17 567
b6c588e1 568 return TRUE;
94b49b93
JS
569}
570
33ac7e6f 571void wxDialog::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
2bda0e17 572{
1f112209 573#if wxUSE_CTL3D
b6c588e1 574 Ctl3dColorChange();
2bda0e17 575#else
b6c588e1
VZ
576 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
577 Refresh();
2bda0e17 578#endif
68ad65f8 579}
42e69d6b
VZ
580
581// ---------------------------------------------------------------------------
582// dialog window proc
583// ---------------------------------------------------------------------------
584
585long wxDialog::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
586{
587 long rc = 0;
588 bool processed = FALSE;
589
590 switch ( message )
591 {
b0a6bb75 592#if 0 // now that we got owner window right it doesn't seem to be needed
5e1febfa
VZ
593 case WM_ACTIVATE:
594 switch ( LOWORD(wParam) )
595 {
596 case WA_ACTIVE:
597 case WA_CLICKACTIVE:
598 if ( IsModalShowing() && GetParent() )
599 {
600 // bring the owner window to top as the standard dialog
601 // boxes do
602 if ( !::SetWindowPos
603 (
604 GetHwndOf(GetParent()),
605 GetHwnd(),
606 0, 0,
607 0, 0,
608 SWP_NOACTIVATE |
609 SWP_NOMOVE |
610 SWP_NOSIZE
611 ) )
612 {
f6bcfd97 613 wxLogLastError(wxT("SetWindowPos(SWP_NOACTIVATE)"));
5e1febfa
VZ
614 }
615 }
616 // fall through to process it normally as well
617 }
618 break;
b0a6bb75 619#endif // 0
5e1febfa 620
42e69d6b
VZ
621 case WM_CLOSE:
622 // if we can't close, tell the system that we processed the
623 // message - otherwise it would close us
624 processed = !Close();
625 break;
abceee76
VZ
626
627 case WM_SETCURSOR:
628 // we want to override the busy cursor for modal dialogs:
629 // typically, wxBeginBusyCursor() is called and then a modal dialog
bfbd6dc1 630 // is shown, but the modal dialog shouldn't have hourglass cursor
d1477745 631 if ( IsModalShowing() && wxIsBusy() )
abceee76 632 {
bfbd6dc1
VZ
633 // set our cursor for all windows (but see below)
634 wxCursor cursor = m_cursor;
635 if ( !cursor.Ok() )
636 cursor = wxCURSOR_ARROW;
abceee76 637
bfbd6dc1
VZ
638 ::SetCursor(GetHcursorOf(cursor));
639
640 // in any case, stop here and don't let wxWindow process this
641 // message (it would set the busy cursor)
abceee76 642 processed = TRUE;
bfbd6dc1
VZ
643
644 // but return FALSE to tell the child window (if the event
645 // comes from one of them and not from ourselves) that it can
646 // set its own cursor if it has one: thus, standard controls
647 // (e.g. text ctrl) still have correct cursors in a dialog
648 // invoked while wxIsBusy()
649 rc = FALSE;
abceee76 650 }
bfbd6dc1 651 break;
42e69d6b
VZ
652 }
653
654 if ( !processed )
655 rc = wxWindow::MSWWindowProc(message, wParam, lParam);
656
657 return rc;
658}
b6c588e1
VZ
659
660#if wxUSE_CTL3D
661
662// Define for each class of dialog and control
663WXHBRUSH wxDialog::OnCtlColor(WXHDC WXUNUSED(pDC),
664 WXHWND WXUNUSED(pWnd),
665 WXUINT WXUNUSED(nCtlColor),
666 WXUINT message,
667 WXWPARAM wParam,
668 WXLPARAM lParam)
669{
670 return (WXHBRUSH)Ctl3dCtlColorEx(message, wParam, lParam);
671}
672
673#endif // wxUSE_CTL3D
674