]> git.saurik.com Git - wxWidgets.git/blob - src/msw/notebook.cpp
xti extensions
[wxWidgets.git] / src / msw / notebook.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/notebook.cpp
3 // Purpose: implementation of wxNotebook
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 11.06.98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "notebook.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_NOTEBOOK
24
25 // wxWindows
26 #ifndef WX_PRECOMP
27 #include "wx/string.h"
28 #endif // WX_PRECOMP
29
30 #include "wx/log.h"
31 #include "wx/imaglist.h"
32 #include "wx/event.h"
33 #include "wx/control.h"
34 #include "wx/notebook.h"
35 #include "wx/app.h"
36
37 #include "wx/msw/private.h"
38
39 // Windows standard headers
40 #ifndef __WIN95__
41 #error "wxNotebook is only supported Windows 95 and above"
42 #endif //Win95
43
44 #include <windowsx.h> // for SetWindowFont
45
46 #ifdef __GNUWIN32_OLD__
47 #include "wx/msw/gnuwin32/extra.h"
48 #endif
49
50 #if defined(__WIN95__) && !(defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__))
51 #include <commctrl.h>
52 #endif
53
54 #include "wx/msw/winundef.h"
55
56 #if wxUSE_UXTHEME
57 #include "wx/msw/uxtheme.h"
58
59 #include "wx/radiobut.h"
60 #include "wx/radiobox.h"
61 #include "wx/checkbox.h"
62 #include "wx/bmpbuttn.h"
63 #include "wx/statline.h"
64 #include "wx/statbox.h"
65 #include "wx/stattext.h"
66 #include "wx/slider.h"
67 #include "wx/scrolwin.h"
68 #include "wx/panel.h"
69 #endif
70
71 /*
72 notebookpage
73 object
74 object_ref
75 label
76 selected
77 style
78 usenotebooksizer
79 */
80
81 // ----------------------------------------------------------------------------
82 // macros
83 // ----------------------------------------------------------------------------
84
85 // check that the page index is valid
86 #define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount()))
87
88 // hide the ugly cast
89 #define m_hwnd (HWND)GetHWND()
90
91 // ----------------------------------------------------------------------------
92 // constants
93 // ----------------------------------------------------------------------------
94
95 // This is a work-around for missing defines in gcc-2.95 headers
96 #ifndef TCS_RIGHT
97 #define TCS_RIGHT 0x0002
98 #endif
99
100 #ifndef TCS_VERTICAL
101 #define TCS_VERTICAL 0x0080
102 #endif
103
104 #ifndef TCS_BOTTOM
105 #define TCS_BOTTOM TCS_RIGHT
106 #endif
107
108 // ----------------------------------------------------------------------------
109 // event table
110 // ----------------------------------------------------------------------------
111
112 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
113 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
114
115 BEGIN_EVENT_TABLE(wxNotebook, wxControl)
116 EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange)
117
118 EVT_SIZE(wxNotebook::OnSize)
119
120 EVT_SET_FOCUS(wxNotebook::OnSetFocus)
121
122 EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
123 END_EVENT_TABLE()
124
125 #if wxUSE_EXTENDED_RTTI
126 IMPLEMENT_DYNAMIC_CLASS_XTI(wxNotebook, wxControl,"wx/notebook.h")
127
128 WX_BEGIN_PROPERTIES_TABLE(wxNotebook)
129 WX_END_PROPERTIES_TABLE()
130
131 WX_BEGIN_HANDLERS_TABLE(wxNotebook)
132 WX_END_HANDLERS_TABLE()
133
134 WX_CONSTRUCTOR_4( wxNotebook , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size )
135
136 #else
137 IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
138 #endif
139 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
140
141 // ============================================================================
142 // implementation
143 // ============================================================================
144
145 // ----------------------------------------------------------------------------
146 // wxNotebook construction
147 // ----------------------------------------------------------------------------
148
149 // common part of all ctors
150 void wxNotebook::Init()
151 {
152 m_imageList = NULL;
153 m_nSelection = -1;
154 }
155
156 // default for dynamic class
157 wxNotebook::wxNotebook()
158 {
159 Init();
160 }
161
162 // the same arguments as for wxControl
163 wxNotebook::wxNotebook(wxWindow *parent,
164 wxWindowID id,
165 const wxPoint& pos,
166 const wxSize& size,
167 long style,
168 const wxString& name)
169 {
170 Init();
171
172 Create(parent, id, pos, size, style, name);
173 }
174
175 // Create() function
176 bool wxNotebook::Create(wxWindow *parent,
177 wxWindowID id,
178 const wxPoint& pos,
179 const wxSize& size,
180 long style,
181 const wxString& name)
182 {
183 // Does ComCtl32 support non-top tabs?
184 int verComCtl32 = wxApp::GetComCtl32Version();
185 if ( verComCtl32 < 470 || verComCtl32 >= 600 )
186 {
187 if (style & wxNB_BOTTOM)
188 style &= ~wxNB_BOTTOM;
189
190 if (style & wxNB_LEFT)
191 style &= ~wxNB_LEFT;
192
193 if (style & wxNB_RIGHT)
194 style &= ~wxNB_RIGHT;
195 }
196
197 if ( !CreateControl(parent, id, pos, size, style | wxTAB_TRAVERSAL,
198 wxDefaultValidator, name) )
199 return FALSE;
200
201 if ( !MSWCreateControl(WC_TABCONTROL, wxEmptyString, pos, size) )
202 return FALSE;
203
204 SetBackgroundColour(wxColour(::GetSysColor(COLOR_BTNFACE)));
205
206 return TRUE;
207 }
208
209 WXDWORD wxNotebook::MSWGetStyle(long style, WXDWORD *exstyle) const
210 {
211 WXDWORD tabStyle = wxControl::MSWGetStyle(style, exstyle);
212
213 tabStyle |= WS_TABSTOP | TCS_TABS;
214
215 if ( style & wxNB_MULTILINE )
216 tabStyle |= TCS_MULTILINE;
217 if ( style & wxNB_FIXEDWIDTH )
218 tabStyle |= TCS_FIXEDWIDTH;
219
220 if ( style & wxNB_BOTTOM )
221 tabStyle |= TCS_RIGHT;
222 else if ( style & wxNB_LEFT )
223 tabStyle |= TCS_VERTICAL;
224 else if ( style & wxNB_RIGHT )
225 tabStyle |= TCS_VERTICAL | TCS_RIGHT;
226
227 // ex style
228 if ( exstyle )
229 {
230 // note that we never want to have the default WS_EX_CLIENTEDGE style
231 // as it looks too ugly for the notebooks
232 *exstyle = 0;
233 }
234
235 return tabStyle;
236 }
237
238 // ----------------------------------------------------------------------------
239 // wxNotebook accessors
240 // ----------------------------------------------------------------------------
241
242 int wxNotebook::GetPageCount() const
243 {
244 // consistency check
245 wxASSERT( (int)m_pages.Count() == TabCtrl_GetItemCount(m_hwnd) );
246
247 return m_pages.Count();
248 }
249
250 int wxNotebook::GetRowCount() const
251 {
252 return TabCtrl_GetRowCount(m_hwnd);
253 }
254
255 int wxNotebook::SetSelection(int nPage)
256 {
257 wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, wxT("notebook page out of range") );
258
259 if ( nPage != m_nSelection )
260 {
261 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId);
262 event.SetSelection(nPage);
263 event.SetOldSelection(m_nSelection);
264 event.SetEventObject(this);
265 if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
266 {
267 // program allows the page change
268 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
269 (void)GetEventHandler()->ProcessEvent(event);
270
271 TabCtrl_SetCurSel(m_hwnd, nPage);
272 }
273 }
274
275 return m_nSelection;
276 }
277
278 bool wxNotebook::SetPageText(int nPage, const wxString& strText)
279 {
280 wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, wxT("notebook page out of range") );
281
282 TC_ITEM tcItem;
283 tcItem.mask = TCIF_TEXT;
284 tcItem.pszText = (wxChar *)strText.c_str();
285
286 return TabCtrl_SetItem(m_hwnd, nPage, &tcItem) != 0;
287 }
288
289 wxString wxNotebook::GetPageText(int nPage) const
290 {
291 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxEmptyString, wxT("notebook page out of range") );
292
293 wxChar buf[256];
294 TC_ITEM tcItem;
295 tcItem.mask = TCIF_TEXT;
296 tcItem.pszText = buf;
297 tcItem.cchTextMax = WXSIZEOF(buf);
298
299 wxString str;
300 if ( TabCtrl_GetItem(m_hwnd, nPage, &tcItem) )
301 str = tcItem.pszText;
302
303 return str;
304 }
305
306 int wxNotebook::GetPageImage(int nPage) const
307 {
308 wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, wxT("notebook page out of range") );
309
310 TC_ITEM tcItem;
311 tcItem.mask = TCIF_IMAGE;
312
313 return TabCtrl_GetItem(m_hwnd, nPage, &tcItem) ? tcItem.iImage : -1;
314 }
315
316 bool wxNotebook::SetPageImage(int nPage, int nImage)
317 {
318 wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, wxT("notebook page out of range") );
319
320 TC_ITEM tcItem;
321 tcItem.mask = TCIF_IMAGE;
322 tcItem.iImage = nImage;
323
324 return TabCtrl_SetItem(m_hwnd, nPage, &tcItem) != 0;
325 }
326
327 void wxNotebook::SetImageList(wxImageList* imageList)
328 {
329 wxNotebookBase::SetImageList(imageList);
330
331 if ( imageList )
332 {
333 TabCtrl_SetImageList(m_hwnd, (HIMAGELIST)imageList->GetHIMAGELIST());
334 }
335 }
336
337 // ----------------------------------------------------------------------------
338 // wxNotebook size settings
339 // ----------------------------------------------------------------------------
340
341 void wxNotebook::SetPageSize(const wxSize& size)
342 {
343 // transform the page size into the notebook size
344 RECT rc;
345 rc.left =
346 rc.top = 0;
347 rc.right = size.x;
348 rc.bottom = size.y;
349
350 TabCtrl_AdjustRect(GetHwnd(), TRUE, &rc);
351
352 // and now set it
353 SetSize(rc.right - rc.left, rc.bottom - rc.top);
354 }
355
356 void wxNotebook::SetPadding(const wxSize& padding)
357 {
358 TabCtrl_SetPadding(GetHwnd(), padding.x, padding.y);
359 }
360
361 // Windows-only at present. Also, you must use the wxNB_FIXEDWIDTH
362 // style.
363 void wxNotebook::SetTabSize(const wxSize& sz)
364 {
365 ::SendMessage(GetHwnd(), TCM_SETITEMSIZE, 0, MAKELPARAM(sz.x, sz.y));
366 }
367
368 wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
369 {
370 wxSize sizeTotal = sizePage;
371
372 // We need to make getting tab size part of the wxWindows API.
373 wxSize tabSize(0, 0);
374 if (GetPageCount() > 0)
375 {
376 RECT rect;
377 TabCtrl_GetItemRect((HWND) GetHWND(), 0, & rect);
378 tabSize.x = rect.right - rect.left;
379 tabSize.y = rect.bottom - rect.top;
380 }
381 if ( HasFlag(wxNB_LEFT) || HasFlag(wxNB_RIGHT) )
382 {
383 sizeTotal.x += tabSize.x + 7;
384 sizeTotal.y += 7;
385 }
386 else
387 {
388 sizeTotal.x += 7;
389 sizeTotal.y += tabSize.y + 7;
390 }
391
392 return sizeTotal;
393 }
394
395 void wxNotebook::AdjustPageSize(wxNotebookPage *page)
396 {
397 wxCHECK_RET( page, _T("NULL page in wxNotebook::AdjustPageSize") );
398
399 RECT rc;
400 rc.left =
401 rc.top = 0;
402
403 // get the page size from the notebook size
404 GetSize((int *)&rc.right, (int *)&rc.bottom);
405 TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
406
407 page->SetSize(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
408 }
409
410 // ----------------------------------------------------------------------------
411 // wxNotebook operations
412 // ----------------------------------------------------------------------------
413
414 // remove one page from the notebook, without deleting
415 wxNotebookPage *wxNotebook::DoRemovePage(int nPage)
416 {
417 wxNotebookPage *pageRemoved = wxNotebookBase::DoRemovePage(nPage);
418 if ( !pageRemoved )
419 return NULL;
420
421 TabCtrl_DeleteItem(m_hwnd, nPage);
422
423 if ( m_pages.IsEmpty() )
424 {
425 // no selection any more, the notebook becamse empty
426 m_nSelection = -1;
427 }
428 else // notebook still not empty
429 {
430 // change the selected page if it was deleted or became invalid
431 int selNew;
432 if ( m_nSelection == GetPageCount() )
433 {
434 // last page deleted, make the new last page the new selection
435 selNew = m_nSelection - 1;
436 }
437 else if ( nPage <= m_nSelection )
438 {
439 // we must show another page, even if it has the same index
440 selNew = m_nSelection;
441 }
442 else // nothing changes for the currently selected page
443 {
444 selNew = -1;
445
446 // we still must refresh the current page: this needs to be done
447 // for some unknown reason if the tab control shows the up-down
448 // control (i.e. when there are too many pages) -- otherwise after
449 // deleting a page nothing at all is shown
450 if (m_nSelection >= 0)
451 m_pages[m_nSelection]->Refresh();
452 }
453
454 if ( selNew != -1 )
455 {
456 // m_nSelection must be always valid so reset it before calling
457 // SetSelection()
458 m_nSelection = -1;
459 SetSelection(selNew);
460 }
461 }
462
463 return pageRemoved;
464 }
465
466 // remove all pages
467 bool wxNotebook::DeleteAllPages()
468 {
469 int nPageCount = GetPageCount();
470 int nPage;
471 for ( nPage = 0; nPage < nPageCount; nPage++ )
472 delete m_pages[nPage];
473
474 m_pages.Clear();
475
476 TabCtrl_DeleteAllItems(m_hwnd);
477
478 m_nSelection = -1;
479
480 return TRUE;
481 }
482
483 // same as AddPage() but does it at given position
484 bool wxNotebook::InsertPage(int nPage,
485 wxNotebookPage *pPage,
486 const wxString& strText,
487 bool bSelect,
488 int imageId)
489 {
490 wxCHECK_MSG( pPage != NULL, FALSE, _T("NULL page in wxNotebook::InsertPage") );
491 wxCHECK_MSG( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), FALSE,
492 _T("invalid index in wxNotebook::InsertPage") );
493
494 wxASSERT_MSG( pPage->GetParent() == this,
495 _T("notebook pages must have notebook as parent") );
496
497 #if wxUSE_UXTHEME && wxUSE_UXTHEME_AUTO
498 static bool g_TestedForTheme = FALSE;
499 static bool g_UseTheme = FALSE;
500 if (!g_TestedForTheme)
501 {
502 int commCtrlVersion = wxTheApp->GetComCtl32Version() ;
503
504 g_UseTheme = (commCtrlVersion >= 600);
505 g_TestedForTheme = TRUE;
506 }
507
508 // Automatically apply the theme background,
509 // changing the colour of the panel to match the
510 // tab page colour. This won't work well with all
511 // themes but it's a start.
512 if (g_UseTheme && wxUxThemeEngine::Get() && pPage->IsKindOf(CLASSINFO(wxPanel)))
513 {
514 ApplyThemeBackground(pPage, GetThemeBackgroundColour());
515 }
516 #endif
517
518 // add a new tab to the control
519 // ----------------------------
520
521 // init all fields to 0
522 TC_ITEM tcItem;
523 wxZeroMemory(tcItem);
524
525 // set the image, if any
526 if ( imageId != -1 )
527 {
528 tcItem.mask |= TCIF_IMAGE;
529 tcItem.iImage = imageId;
530 }
531
532 // and the text
533 if ( !strText.IsEmpty() )
534 {
535 tcItem.mask |= TCIF_TEXT;
536 tcItem.pszText = (wxChar *)strText.c_str(); // const_cast
537 }
538
539 // fit the notebook page to the tab control's display area: this should be
540 // done before adding it to the notebook or TabCtrl_InsertItem() will
541 // change the notebooks size itself!
542 AdjustPageSize(pPage);
543
544 // finally do insert it
545 if ( TabCtrl_InsertItem(m_hwnd, nPage, &tcItem) == -1 )
546 {
547 wxLogError(wxT("Can't create the notebook page '%s'."), strText.c_str());
548
549 return FALSE;
550 }
551
552 // succeeded: save the pointer to the page
553 m_pages.Insert(pPage, nPage);
554
555 // for the first page (only) we need to adjust the size again because the
556 // notebook size changed: the tabs which hadn't been there before are now
557 // shown
558 if ( m_pages.GetCount() == 1 )
559 {
560 AdjustPageSize(pPage);
561 }
562
563 // hide the page: unless it is selected, it shouldn't be shown (and if it
564 // is selected it will be shown later)
565 HWND hwnd = GetWinHwnd(pPage);
566 SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_VISIBLE);
567
568 // this updates internal flag too -- otherwise it would get out of sync
569 // with the real state
570 pPage->Show(FALSE);
571
572
573 // now deal with the selection
574 // ---------------------------
575
576 // if the inserted page is before the selected one, we must update the
577 // index of the selected page
578 if ( nPage <= m_nSelection )
579 {
580 // one extra page added
581 m_nSelection++;
582 }
583
584 // some page should be selected: either this one or the first one if there
585 // is still no selection
586 int selNew = -1;
587 if ( bSelect )
588 selNew = nPage;
589 else if ( m_nSelection == -1 )
590 selNew = 0;
591
592 if ( selNew != -1 )
593 SetSelection(selNew);
594
595 return TRUE;
596 }
597
598 int wxNotebook::HitTest(const wxPoint& pt, long *flags) const
599 {
600 TC_HITTESTINFO hitTestInfo;
601 hitTestInfo.pt.x = pt.x;
602 hitTestInfo.pt.y = pt.y;
603 int item = TabCtrl_HitTest(GetHwnd(), &hitTestInfo);
604
605 if ( flags )
606 {
607 *flags = 0;
608
609 if ((hitTestInfo.flags & TCHT_NOWHERE) == TCHT_NOWHERE)
610 *flags |= wxNB_HITTEST_NOWHERE;
611 if ((hitTestInfo.flags & TCHT_ONITEM) == TCHT_ONITEM)
612 *flags |= wxNB_HITTEST_ONITEM;
613 if ((hitTestInfo.flags & TCHT_ONITEMICON) == TCHT_ONITEMICON)
614 *flags |= wxNB_HITTEST_ONICON;
615 if ((hitTestInfo.flags & TCHT_ONITEMLABEL) == TCHT_ONITEMLABEL)
616 *flags |= wxNB_HITTEST_ONLABEL;
617 }
618
619 return item;
620 }
621
622
623 // ----------------------------------------------------------------------------
624 // wxNotebook callbacks
625 // ----------------------------------------------------------------------------
626
627 void wxNotebook::OnSize(wxSizeEvent& event)
628 {
629 // fit the notebook page to the tab control's display area
630 RECT rc;
631 rc.left = rc.top = 0;
632 GetSize((int *)&rc.right, (int *)&rc.bottom);
633
634 TabCtrl_AdjustRect(m_hwnd, FALSE, &rc);
635
636 int width = rc.right - rc.left,
637 height = rc.bottom - rc.top;
638 size_t nCount = m_pages.Count();
639 for ( size_t nPage = 0; nPage < nCount; nPage++ ) {
640 wxNotebookPage *pPage = m_pages[nPage];
641 pPage->SetSize(rc.left, rc.top, width, height);
642 }
643
644 event.Skip();
645 }
646
647 void wxNotebook::OnSelChange(wxNotebookEvent& event)
648 {
649 // is it our tab control?
650 if ( event.GetEventObject() == this )
651 {
652 int sel = event.GetOldSelection();
653 if ( sel != -1 )
654 m_pages[sel]->Show(FALSE);
655
656 sel = event.GetSelection();
657 if ( sel != -1 )
658 {
659 wxNotebookPage *pPage = m_pages[sel];
660 pPage->Show(TRUE);
661 pPage->SetFocus();
662 }
663
664 m_nSelection = sel;
665 }
666
667 // we want to give others a chance to process this message as well
668 event.Skip();
669 }
670
671 void wxNotebook::OnSetFocus(wxFocusEvent& event)
672 {
673 // this function is only called when the focus is explicitly set (i.e. from
674 // the program) to the notebook - in this case we don't need the
675 // complicated OnNavigationKey() logic because the programmer knows better
676 // what [s]he wants
677
678 // set focus to the currently selected page if any
679 if ( m_nSelection != -1 )
680 m_pages[m_nSelection]->SetFocus();
681
682 event.Skip();
683 }
684
685 void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
686 {
687 if ( event.IsWindowChange() ) {
688 // change pages
689 AdvanceSelection(event.GetDirection());
690 }
691 else {
692 // we get this event in 2 cases
693 //
694 // a) one of our pages might have generated it because the user TABbed
695 // out from it in which case we should propagate the event upwards and
696 // our parent will take care of setting the focus to prev/next sibling
697 //
698 // or
699 //
700 // b) the parent panel wants to give the focus to us so that we
701 // forward it to our selected page. We can't deal with this in
702 // OnSetFocus() because we don't know which direction the focus came
703 // from in this case and so can't choose between setting the focus to
704 // first or last panel child
705 wxWindow *parent = GetParent();
706 // the cast is here to fic a GCC ICE
707 if ( ((wxWindow*)event.GetEventObject()) == parent )
708 {
709 // no, it doesn't come from child, case (b): forward to a page
710 if ( m_nSelection != -1 )
711 {
712 // so that the page knows that the event comes from it's parent
713 // and is being propagated downwards
714 event.SetEventObject(this);
715
716 wxWindow *page = m_pages[m_nSelection];
717 if ( !page->GetEventHandler()->ProcessEvent(event) )
718 {
719 page->SetFocus();
720 }
721 //else: page manages focus inside it itself
722 }
723 else
724 {
725 // we have no pages - still have to give focus to _something_
726 SetFocus();
727 }
728 }
729 else
730 {
731 // it comes from our child, case (a), pass to the parent
732 if ( parent ) {
733 event.SetCurrentFocus(this);
734 parent->GetEventHandler()->ProcessEvent(event);
735 }
736 }
737 }
738 }
739
740 // ----------------------------------------------------------------------------
741 // wxNotebook base class virtuals
742 // ----------------------------------------------------------------------------
743
744 #if wxUSE_CONSTRAINTS
745
746 // override these 2 functions to do nothing: everything is done in OnSize
747
748 void wxNotebook::SetConstraintSizes(bool WXUNUSED(recurse))
749 {
750 // don't set the sizes of the pages - their correct size is not yet known
751 wxControl::SetConstraintSizes(FALSE);
752 }
753
754 bool wxNotebook::DoPhase(int WXUNUSED(nPhase))
755 {
756 return TRUE;
757 }
758
759 #endif // wxUSE_CONSTRAINTS
760
761 // ----------------------------------------------------------------------------
762 // wxNotebook Windows message handlers
763 // ----------------------------------------------------------------------------
764
765 bool wxNotebook::MSWOnScroll(int orientation, WXWORD nSBCode,
766 WXWORD pos, WXHWND control)
767 {
768 // don't generate EVT_SCROLLWIN events for the WM_SCROLLs coming from the
769 // up-down control
770 if ( control )
771 return FALSE;
772
773 return wxNotebookBase::MSWOnScroll(orientation, nSBCode, pos, control);
774 }
775
776 bool wxNotebook::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result)
777 {
778 wxNotebookEvent event(wxEVT_NULL, m_windowId);
779
780 NMHDR* hdr = (NMHDR *)lParam;
781 switch ( hdr->code ) {
782 case TCN_SELCHANGE:
783 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
784 break;
785
786 case TCN_SELCHANGING:
787 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING);
788 break;
789
790 default:
791 return wxControl::MSWOnNotify(idCtrl, lParam, result);
792 }
793
794 event.SetSelection(TabCtrl_GetCurSel(m_hwnd));
795 event.SetOldSelection(m_nSelection);
796 event.SetEventObject(this);
797 event.SetInt(idCtrl);
798
799 bool processed = GetEventHandler()->ProcessEvent(event);
800 *result = !event.IsAllowed();
801 return processed;
802 }
803
804 // Windows only: attempts to get colour for UX theme page background
805 wxColour wxNotebook::GetThemeBackgroundColour()
806 {
807 #if wxUSE_UXTHEME
808 if (wxUxThemeEngine::Get())
809 {
810 wxUxThemeHandle hTheme(this, L"TAB");
811 if (hTheme)
812 {
813 // This is total guesswork.
814 // See PlatformSDK\Include\Tmschema.h for values
815 COLORREF themeColor;
816 wxUxThemeEngine::Get()->GetThemeColor
817 (
818 hTheme,
819 10 /* TABP_BODY */,
820 1 /* NORMAL */,
821 3821, /* FILLCOLORHINT */
822 & themeColor
823 );
824
825 wxColour colour(GetRValue(themeColor), GetGValue(themeColor), GetBValue(themeColor));
826 return colour;
827 }
828 }
829 #endif // wxUSE_UXTHEME
830
831 return GetBackgroundColour();
832 }
833
834 // Windows only: attempts to apply the UX theme page background to this page
835 #if wxUSE_UXTHEME
836 void wxNotebook::ApplyThemeBackground(wxWindow* window, const wxColour& colour)
837 #else
838 void wxNotebook::ApplyThemeBackground(wxWindow*, const wxColour&)
839 #endif
840 {
841 #if wxUSE_UXTHEME
842 // Don't set the background for buttons since this will
843 // switch it into ownerdraw mode
844 if (window->IsKindOf(CLASSINFO(wxButton)) && !window->IsKindOf(CLASSINFO(wxBitmapButton)))
845 // This is essential, otherwise you'll see dark grey
846 // corners in the buttons.
847 ((wxButton*)window)->wxControl::SetBackgroundColour(colour);
848 else if (window->IsKindOf(CLASSINFO(wxStaticText)) ||
849 window->IsKindOf(CLASSINFO(wxStaticBox)) ||
850 window->IsKindOf(CLASSINFO(wxStaticLine)) ||
851 window->IsKindOf(CLASSINFO(wxRadioButton)) ||
852 window->IsKindOf(CLASSINFO(wxRadioBox)) ||
853 window->IsKindOf(CLASSINFO(wxCheckBox)) ||
854 window->IsKindOf(CLASSINFO(wxBitmapButton)) ||
855 window->IsKindOf(CLASSINFO(wxSlider)) ||
856 window->IsKindOf(CLASSINFO(wxPanel)) ||
857 (window->IsKindOf(CLASSINFO(wxNotebook)) && (window != this)) ||
858 window->IsKindOf(CLASSINFO(wxScrolledWindow))
859 )
860 {
861 window->SetBackgroundColour(colour);
862 }
863
864 for ( wxWindowList::compatibility_iterator node = window->GetChildren().GetFirst(); node; node = node->GetNext() )
865 {
866 wxWindow *child = node->GetData();
867 ApplyThemeBackground(child, colour);
868 }
869 #endif
870 }
871
872 long wxNotebook::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
873 {
874 static bool g_TestedForTheme = FALSE;
875 static bool g_UseTheme = FALSE;
876 switch ( nMsg )
877 {
878 case WM_ERASEBKGND:
879 {
880 if (!g_TestedForTheme)
881 {
882 int commCtrlVersion = wxTheApp->GetComCtl32Version() ;
883
884 g_UseTheme = (commCtrlVersion >= 600);
885 g_TestedForTheme = TRUE;
886 }
887
888 // If using XP themes, it seems we can get away
889 // with not drawing a background, which reduces flicker.
890 if (g_UseTheme)
891 return TRUE;
892 }
893 }
894
895 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
896 }
897
898
899 #endif // wxUSE_NOTEBOOK