]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dialog.cpp
1. added wxHelpProvider and (unfinished) wxSimpleHelpProvider
[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
a23fd0e1 99wxDialog::wxDialog()
2bda0e17 100{
52a07708 101 m_oldFocus = (wxWindow *)NULL;
b6c588e1 102 m_isShown = FALSE;
2bda0e17 103
b6c588e1 104 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
2bda0e17
KB
105}
106
debe6624 107bool wxDialog::Create(wxWindow *parent, wxWindowID id,
462e2437
VZ
108 const wxString& title,
109 const wxPoint& pos,
110 const wxSize& size,
111 long style,
112 const wxString& name)
2bda0e17 113{
abceee76
VZ
114 m_oldFocus = FindFocus();
115
462e2437
VZ
116 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
117 SetName(name);
bd9d76cb 118
f6bcfd97 119 wxTopLevelWindows.Append(this);
2bda0e17 120
462e2437 121 // windowFont = wxTheFontList->FindOrCreateFont(11, wxSWISS, wxNORMAL, wxNORMAL);
2bda0e17 122
462e2437 123 if (parent) parent->AddChild(this);
2bda0e17 124
462e2437
VZ
125 if ( id == -1 )
126 m_windowId = (int)NewControlId();
127 else
128 m_windowId = id;
129
130 int x = pos.x;
131 int y = pos.y;
132 int width = size.x;
133 int height = size.y;
134
b6c588e1
VZ
135 if (x < 0)
136 x = wxDIALOG_DEFAULT_X;
137 if (y < 0)
138 y = wxDIALOG_DEFAULT_Y;
462e2437
VZ
139
140 m_windowStyle = style;
141
142 m_isShown = FALSE;
462e2437
VZ
143
144 if (width < 0)
b6c588e1 145 width = wxDIALOG_DEFAULT_WIDTH;
462e2437 146 if (height < 0)
b6c588e1 147 height = wxDIALOG_DEFAULT_HEIGHT;
462e2437 148
706bb5f9
JS
149 // All dialogs should really have this style
150 m_windowStyle |= wxTAB_TRAVERSAL;
151
462e2437
VZ
152 WXDWORD extendedStyle = MakeExtendedStyle(m_windowStyle);
153 if (m_windowStyle & wxSTAY_ON_TOP)
154 extendedStyle |= WS_EX_TOPMOST;
b96340e6
JS
155 if (m_exStyle & wxFRAME_EX_CONTEXTHELP)
156 extendedStyle |= WS_EX_CONTEXTHELP;
462e2437
VZ
157
158 // Allows creation of dialogs with & without captions under MSWindows,
159 // resizeable or not (but a resizeable dialog always has caption -
160 // otherwise it would look too strange)
837e5743 161 const wxChar *dlg;
257bf510 162 if ( style & wxRESIZE_BORDER )
223d09f6 163 dlg = wxT("wxResizeableDialog");
462e2437 164 else if ( style & wxCAPTION )
223d09f6 165 dlg = wxT("wxCaptionDialog");
462e2437 166 else
223d09f6 167 dlg = wxT("wxNoCaptionDialog");
462e2437
VZ
168 MSWCreate(m_windowId, parent, NULL, this, NULL,
169 x, y, width, height,
170 0, // style is not used if we have dlg template
171 dlg,
172 extendedStyle);
2bda0e17 173
462e2437 174 HWND hwnd = (HWND)GetHWND();
2bda0e17 175
462e2437
VZ
176 if ( !hwnd )
177 {
f6bcfd97 178 wxFAIL_MSG(_("Failed to create dialog. You probably forgot to include wx/msw/wx.rc in your resources."));
2bda0e17 179
462e2437
VZ
180 return FALSE;
181 }
2bda0e17 182
462e2437 183 SubclassWin(GetHWND());
bd9d76cb 184
462e2437
VZ
185 SetWindowText(hwnd, title);
186 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
2bda0e17 187
462e2437 188 return TRUE;
2bda0e17
KB
189}
190
debe6624 191void wxDialog::SetModal(bool flag)
2bda0e17 192{
b6c588e1
VZ
193 if ( flag )
194 {
195 m_windowStyle |= wxDIALOG_MODAL;
196
197 wxModelessWindows.DeleteObject(this);
198 }
199 else
200 {
201 m_windowStyle &= ~wxDIALOG_MODAL;
202
203 wxModelessWindows.Append(this);
204 }
2bda0e17
KB
205}
206
207wxDialog::~wxDialog()
208{
b6c588e1 209 m_isBeingDeleted = TRUE;
2bda0e17 210
b6c588e1 211 wxTopLevelWindows.DeleteObject(this);
2bda0e17 212
abceee76
VZ
213 // this will call BringWindowToTop() if necessary to bring back our parent
214 // window to top
b6c588e1 215 Show(FALSE);
edccf428 216
b6c588e1
VZ
217 if ( !IsModal() )
218 wxModelessWindows.DeleteObject(this);
2bda0e17 219
b6c588e1
VZ
220 // If this is the last top-level window, exit.
221 if ( wxTheApp && (wxTopLevelWindows.Number() == 0) )
2bda0e17 222 {
b6c588e1
VZ
223 wxTheApp->SetTopWindow(NULL);
224
225 if ( wxTheApp->GetExitOnFrameDelete() )
226 {
227 ::PostQuitMessage(0);
228 }
2bda0e17 229 }
2bda0e17
KB
230}
231
b6c588e1
VZ
232// ----------------------------------------------------------------------------
233// kbd handling
234// ----------------------------------------------------------------------------
235
2bda0e17
KB
236// By default, pressing escape cancels the dialog
237void wxDialog::OnCharHook(wxKeyEvent& event)
238{
cbc66a27 239 if (GetHWND())
2bda0e17 240 {
cbc66a27
VZ
241 // "Esc" works as an accelerator for the "Cancel" button, but it
242 // shouldn't close the dialog which doesn't have any cancel button
243 if ( (event.m_keyCode == WXK_ESCAPE) && FindWindow(wxID_CANCEL) )
244 {
245 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
246 cancelEvent.SetEventObject( this );
247 GetEventHandler()->ProcessEvent(cancelEvent);
248
249 // ensure that there is another message for this window so the
250 // ShowModal loop will exit and won't get stuck in GetMessage().
251 ::PostMessage(GetHwnd(), WM_NULL, 0, 0);
252
253 return;
254 }
2bda0e17 255 }
cbc66a27
VZ
256
257 // We didn't process this event.
258 event.Skip();
2bda0e17
KB
259}
260
b6c588e1
VZ
261// ----------------------------------------------------------------------------
262// Windows dialog boxes can't be iconized
263// ----------------------------------------------------------------------------
2bda0e17 264
debe6624 265void wxDialog::Iconize(bool WXUNUSED(iconize))
2bda0e17 266{
2bda0e17
KB
267}
268
a23fd0e1 269bool wxDialog::IsIconized() const
2bda0e17 270{
b6c588e1 271 return FALSE;
2bda0e17
KB
272}
273
b6c588e1
VZ
274// ----------------------------------------------------------------------------
275// size/position handling
276// ----------------------------------------------------------------------------
277
721b32e0 278void wxDialog::DoSetClientSize(int width, int height)
2bda0e17 279{
b6c588e1
VZ
280 HWND hWnd = (HWND) GetHWND();
281 RECT rect;
282 ::GetClientRect(hWnd, &rect);
2bda0e17 283
b6c588e1
VZ
284 RECT rect2;
285 GetWindowRect(hWnd, &rect2);
2bda0e17 286
b6c588e1
VZ
287 // Find the difference between the entire window (title bar and all)
288 // and the client area; add this to the new client size to move the
289 // window
290 int actual_width = rect2.right - rect2.left - rect.right + width;
291 int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
2bda0e17 292
b6c588e1 293 MoveWindow(hWnd, rect2.left, rect2.top, actual_width, actual_height, TRUE);
debe6624 294
b6c588e1
VZ
295 wxSizeEvent event(wxSize(actual_width, actual_height), m_windowId);
296 event.SetEventObject( this );
297 GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
298}
299
b6c588e1 300void wxDialog::DoGetPosition(int *x, int *y) const
2bda0e17 301{
b6c588e1
VZ
302 RECT rect;
303 GetWindowRect(GetHwnd(), &rect);
2bda0e17 304
b6c588e1
VZ
305 if ( x )
306 *x = rect.left;
307 if ( y )
308 *y = rect.top;
2bda0e17
KB
309}
310
b6c588e1
VZ
311// ----------------------------------------------------------------------------
312// showing the dialogs
313// ----------------------------------------------------------------------------
22cf5fec
VZ
314
315bool wxDialog::IsModal() const
316{
b6c588e1 317 return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0;
2bda0e17
KB
318}
319
b6c588e1 320bool wxDialog::IsModalShowing() const
2bda0e17 321{
b6c588e1 322 return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
2bda0e17
KB
323}
324
b6c588e1 325void wxDialog::DoShowModal()
2bda0e17 326{
b6c588e1 327 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
f6bcfd97 328 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
b6c588e1
VZ
329
330 wxModalDialogs.Append(this);
331
332 wxWindow *parent = GetParent();
333
f6bcfd97 334 wxWindow* oldFocus = m_oldFocus;
b6c588e1 335
f6bcfd97
BP
336 // We have to remember the HWND because we need to check
337 // the HWND still exists (oldFocus can be garbage when the dialog
338 // exits, if it has been destroyed)
339 HWND hwndOldFocus = 0;
340 if (oldFocus)
341 hwndOldFocus = (HWND) oldFocus->GetHWND();
b6c588e1 342
f6bcfd97 343 // inside this block, all app windows are disabled
b6c588e1 344 {
f6bcfd97
BP
345 wxWindowDisabler wd(this);
346
347 // remember where the focus was
348 if ( !oldFocus )
349 {
350 oldFocus = parent;
351 if (parent)
352 hwndOldFocus = (HWND) parent->GetHWND();
353 }
354
355 // enter the modal loop
356 while ( IsModalShowing() )
357 {
b6c588e1 358#if wxUSE_THREADS
f6bcfd97 359 wxMutexGuiLeaveOrEnter();
b6c588e1
VZ
360#endif // wxUSE_THREADS
361
f6bcfd97
BP
362 while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() )
363 ;
b6c588e1 364
f6bcfd97
BP
365 // a message came or no more idle processing to do
366 wxTheApp->DoMessage();
367 }
b6c588e1
VZ
368 }
369
f6bcfd97
BP
370#ifdef __WIN32__
371 if ( parent )
372 ::SetActiveWindow(GetHwndOf(parent));
373#endif // __WIN32__
b6c588e1
VZ
374
375 // and restore focus
f6bcfd97
BP
376 // Note that this code MUST NOT access the dialog object's data
377 // in case the object has been deleted (which will be the case
378 // for a modal dialog that has been destroyed before calling EndModal).
379 if ( oldFocus && (oldFocus != this) && ::IsWindow(hwndOldFocus))
b6c588e1 380 {
f6bcfd97
BP
381 // This is likely to prove that the object still exists
382 if (wxFindWinFromHandle((WXHWND) hwndOldFocus) == oldFocus)
383 oldFocus->SetFocus();
b6c588e1 384 }
2bda0e17
KB
385}
386
b6c588e1 387bool wxDialog::Show(bool show)
2bda0e17 388{
abceee76
VZ
389 // The following is required when the parent has been disabled, (modal
390 // dialogs, or modeless dialogs with disabling such as wxProgressDialog).
391 // Otherwise the parent disappears behind other windows when the dialog is
392 // hidden.
393 if ( !show )
86ad564e 394 {
abceee76
VZ
395 wxWindow *parent = GetParent();
396 if ( parent )
86ad564e 397 {
abceee76 398 ::BringWindowToTop(GetHwndOf(parent));
86ad564e
JS
399 }
400 }
401
abceee76
VZ
402 // ShowModal() may be called for already shown dialog
403 if ( !wxDialogBase::Show(show) && !(show && IsModal()) )
b6c588e1
VZ
404 {
405 // nothing to do
406 return FALSE;
407 }
2bda0e17 408
b6c588e1
VZ
409 if ( show )
410 {
411 // usually will result in TransferDataToWindow() being called
412 InitDialog();
413 }
2bda0e17 414
b6c588e1
VZ
415 if ( IsModal() )
416 {
417 if ( show )
418 {
f6bcfd97
BP
419 // modal dialog needs a parent window, so try to find one
420 if ( !GetParent() )
421 {
422 wxWindow *parent = wxTheApp->GetTopWindow();
423 if ( parent && parent != this && parent->IsShown() )
424 {
425 // use it
426 m_parent = parent;
427 }
428 }
429
b6c588e1
VZ
430 DoShowModal();
431 }
432 else // end of modal dialog
433 {
434 // this will cause IsModalShowing() return FALSE and our local
435 // message loop will terminate
436 wxModalDialogs.DeleteObject(this);
437 }
438 }
2bda0e17 439
b6c588e1 440 return TRUE;
2bda0e17
KB
441}
442
f6bcfd97 443// a special version for Show(TRUE) for modal dialogs which returns return code
a23fd0e1 444int wxDialog::ShowModal()
2bda0e17 445{
f6bcfd97 446 if ( !IsModal() )
5e1febfa 447 {
f6bcfd97 448 SetModal(TRUE);
5e1febfa
VZ
449 }
450
b6c588e1 451 Show(TRUE);
5e1febfa 452
b6c588e1 453 return GetReturnCode();
2bda0e17
KB
454}
455
b6c588e1
VZ
456// NB: this function (surprizingly) may be called for both modal and modeless
457// dialogs and should work for both of them
2bda0e17
KB
458void wxDialog::EndModal(int retCode)
459{
b6c588e1 460 SetReturnCode(retCode);
6a088435 461
b6c588e1 462 Show(FALSE);
2bda0e17
KB
463}
464
b6c588e1
VZ
465// ----------------------------------------------------------------------------
466// wxWin event handlers
467// ----------------------------------------------------------------------------
2bda0e17
KB
468
469// Standard buttons
470void wxDialog::OnOK(wxCommandEvent& event)
471{
dc1c4b62
VZ
472 if ( Validate() && TransferDataFromWindow() )
473 {
b6c588e1 474 EndModal(wxID_OK);
dc1c4b62 475 }
2bda0e17
KB
476}
477
478void wxDialog::OnApply(wxCommandEvent& event)
479{
b6c588e1
VZ
480 if ( Validate() )
481 TransferDataFromWindow();
482
483 // TODO probably need to disable the Apply button until things change again
2bda0e17
KB
484}
485
486void wxDialog::OnCancel(wxCommandEvent& event)
487{
b6c588e1 488 EndModal(wxID_CANCEL);
2bda0e17
KB
489}
490
e3065973 491void wxDialog::OnCloseWindow(wxCloseEvent& event)
2bda0e17 492{
b6c588e1 493 // We'll send a Cancel message by default, which may close the dialog.
e3065973
JS
494 // Check for looping if the Cancel event handler calls Close().
495
496 // Note that if a cancel button and handler aren't present in the dialog,
497 // nothing will happen when you close the dialog via the window manager, or
b6c588e1
VZ
498 // via Close(). We wouldn't want to destroy the dialog by default, since
499 // the dialog may have been created on the stack. However, this does mean
500 // that calling dialog->Close() won't delete the dialog unless the handler
501 // for wxID_CANCEL does so. So use Destroy() if you want to be sure to
502 // destroy the dialog. The default OnCancel (above) simply ends a modal
503 // dialog, and hides a modeless dialog.
504
505 // VZ: this is horrible and MT-unsafe. Can't we reuse some of these global
506 // lists here? don't dare to change it now, but should be done later!
2bda0e17 507 static wxList closing;
bd9d76cb 508
2bda0e17 509 if ( closing.Member(this) )
e3065973 510 return;
bd9d76cb 511
2bda0e17 512 closing.Append(this);
bd9d76cb 513
387a3b02
JS
514 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
515 cancelEvent.SetEventObject( this );
e3065973 516 GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
2bda0e17
KB
517
518 closing.DeleteObject(this);
e3065973 519}
2bda0e17 520
e3065973 521// Destroy the window (delayed, if a managed window)
a23fd0e1 522bool wxDialog::Destroy()
e3065973 523{
b6c588e1
VZ
524 wxCHECK_MSG( !wxPendingDelete.Member(this), FALSE,
525 _T("wxDialog destroyed twice") );
526
e3065973 527 wxPendingDelete.Append(this);
2bda0e17 528
b6c588e1 529 return TRUE;
94b49b93
JS
530}
531
2bda0e17
KB
532void wxDialog::OnSysColourChanged(wxSysColourChangedEvent& event)
533{
1f112209 534#if wxUSE_CTL3D
b6c588e1 535 Ctl3dColorChange();
2bda0e17 536#else
b6c588e1
VZ
537 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
538 Refresh();
2bda0e17 539#endif
68ad65f8 540}
42e69d6b
VZ
541
542// ---------------------------------------------------------------------------
543// dialog window proc
544// ---------------------------------------------------------------------------
545
546long wxDialog::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
547{
548 long rc = 0;
549 bool processed = FALSE;
550
551 switch ( message )
552 {
5e1febfa
VZ
553 case WM_ACTIVATE:
554 switch ( LOWORD(wParam) )
555 {
556 case WA_ACTIVE:
557 case WA_CLICKACTIVE:
558 if ( IsModalShowing() && GetParent() )
559 {
560 // bring the owner window to top as the standard dialog
561 // boxes do
562 if ( !::SetWindowPos
563 (
564 GetHwndOf(GetParent()),
565 GetHwnd(),
566 0, 0,
567 0, 0,
568 SWP_NOACTIVATE |
569 SWP_NOMOVE |
570 SWP_NOSIZE
571 ) )
572 {
f6bcfd97 573 wxLogLastError(wxT("SetWindowPos(SWP_NOACTIVATE)"));
5e1febfa
VZ
574 }
575 }
576 // fall through to process it normally as well
577 }
578 break;
579
42e69d6b
VZ
580 case WM_CLOSE:
581 // if we can't close, tell the system that we processed the
582 // message - otherwise it would close us
583 processed = !Close();
584 break;
abceee76
VZ
585
586 case WM_SETCURSOR:
587 // we want to override the busy cursor for modal dialogs:
588 // typically, wxBeginBusyCursor() is called and then a modal dialog
bfbd6dc1 589 // is shown, but the modal dialog shouldn't have hourglass cursor
d1477745 590 if ( IsModalShowing() && wxIsBusy() )
abceee76 591 {
bfbd6dc1
VZ
592 // set our cursor for all windows (but see below)
593 wxCursor cursor = m_cursor;
594 if ( !cursor.Ok() )
595 cursor = wxCURSOR_ARROW;
abceee76 596
bfbd6dc1
VZ
597 ::SetCursor(GetHcursorOf(cursor));
598
599 // in any case, stop here and don't let wxWindow process this
600 // message (it would set the busy cursor)
abceee76 601 processed = TRUE;
bfbd6dc1
VZ
602
603 // but return FALSE to tell the child window (if the event
604 // comes from one of them and not from ourselves) that it can
605 // set its own cursor if it has one: thus, standard controls
606 // (e.g. text ctrl) still have correct cursors in a dialog
607 // invoked while wxIsBusy()
608 rc = FALSE;
abceee76 609 }
bfbd6dc1 610 break;
42e69d6b
VZ
611 }
612
613 if ( !processed )
614 rc = wxWindow::MSWWindowProc(message, wParam, lParam);
615
616 return rc;
617}
b6c588e1
VZ
618
619#if wxUSE_CTL3D
620
621// Define for each class of dialog and control
622WXHBRUSH wxDialog::OnCtlColor(WXHDC WXUNUSED(pDC),
623 WXHWND WXUNUSED(pWnd),
624 WXUINT WXUNUSED(nCtlColor),
625 WXUINT message,
626 WXWPARAM wParam,
627 WXLPARAM lParam)
628{
629 return (WXHBRUSH)Ctl3dCtlColorEx(message, wParam, lParam);
630}
631
632#endif // wxUSE_CTL3D
633