]> git.saurik.com Git - wxWidgets.git/blob - src/msw/notebook.cpp
need to include wx/imaglist.h even when using PCH
[wxWidgets.git] / src / msw / notebook.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/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 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_NOTEBOOK
20
21 #include "wx/notebook.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
25 #include "wx/string.h"
26 #include "wx/dc.h"
27 #include "wx/log.h"
28 #include "wx/event.h"
29 #include "wx/app.h"
30 #include "wx/dcclient.h"
31 #include "wx/dcmemory.h"
32 #include "wx/control.h"
33 #endif // WX_PRECOMP
34
35 #include "wx/imaglist.h"
36 #include "wx/sysopt.h"
37
38 #include "wx/msw/private.h"
39
40 #include <windowsx.h>
41 #include "wx/msw/winundef.h"
42
43 #if wxUSE_UXTHEME
44 #include "wx/msw/uxtheme.h"
45 #endif
46
47 // ----------------------------------------------------------------------------
48 // macros
49 // ----------------------------------------------------------------------------
50
51 // check that the page index is valid
52 #define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
53
54 // you can set USE_NOTEBOOK_ANTIFLICKER to 0 for desktop Windows versions too
55 // to disable code whih results in flicker-less notebook redrawing at the
56 // expense of some extra GDI resource consumption
57 #ifdef __WXWINCE__
58 // notebooks are never resized under CE anyhow
59 #define USE_NOTEBOOK_ANTIFLICKER 0
60 #else
61 #define USE_NOTEBOOK_ANTIFLICKER 1
62 #endif
63
64 // ----------------------------------------------------------------------------
65 // constants
66 // ----------------------------------------------------------------------------
67
68 // This is a work-around for missing defines in gcc-2.95 headers
69 #ifndef TCS_RIGHT
70 #define TCS_RIGHT 0x0002
71 #endif
72
73 #ifndef TCS_VERTICAL
74 #define TCS_VERTICAL 0x0080
75 #endif
76
77 #ifndef TCS_BOTTOM
78 #define TCS_BOTTOM TCS_RIGHT
79 #endif
80
81 // ----------------------------------------------------------------------------
82 // global variables
83 // ----------------------------------------------------------------------------
84
85 #if USE_NOTEBOOK_ANTIFLICKER
86
87 // the pointer to standard spin button wnd proc
88 static WXFARPROC gs_wndprocNotebookSpinBtn = (WXFARPROC)NULL;
89
90 // the pointer to standard tab control wnd proc
91 static WXFARPROC gs_wndprocNotebook = (WXFARPROC)NULL;
92
93 LRESULT APIENTRY _EXPORT wxNotebookWndProc(HWND hwnd,
94 UINT message,
95 WPARAM wParam,
96 LPARAM lParam);
97
98 #endif // USE_NOTEBOOK_ANTIFLICKER
99
100 // ----------------------------------------------------------------------------
101 // event table
102 // ----------------------------------------------------------------------------
103
104 #include "wx/listimpl.cpp"
105
106 WX_DEFINE_LIST( wxNotebookPageInfoList )
107
108 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
109 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
110
111 BEGIN_EVENT_TABLE(wxNotebook, wxControl)
112 EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, wxNotebook::OnSelChange)
113 EVT_SIZE(wxNotebook::OnSize)
114 EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
115
116 #if USE_NOTEBOOK_ANTIFLICKER
117 EVT_ERASE_BACKGROUND(wxNotebook::OnEraseBackground)
118 EVT_PAINT(wxNotebook::OnPaint)
119 #endif // USE_NOTEBOOK_ANTIFLICKER
120 END_EVENT_TABLE()
121
122 #if wxUSE_EXTENDED_RTTI
123 WX_DEFINE_FLAGS( wxNotebookStyle )
124
125 wxBEGIN_FLAGS( wxNotebookStyle )
126 // new style border flags, we put them first to
127 // use them for streaming out
128 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
129 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
130 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
131 wxFLAGS_MEMBER(wxBORDER_RAISED)
132 wxFLAGS_MEMBER(wxBORDER_STATIC)
133 wxFLAGS_MEMBER(wxBORDER_NONE)
134
135 // old style border flags
136 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
137 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
138 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
139 wxFLAGS_MEMBER(wxRAISED_BORDER)
140 wxFLAGS_MEMBER(wxSTATIC_BORDER)
141 wxFLAGS_MEMBER(wxBORDER)
142
143 // standard window styles
144 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
145 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
146 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
147 wxFLAGS_MEMBER(wxWANTS_CHARS)
148 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
149 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
150 wxFLAGS_MEMBER(wxVSCROLL)
151 wxFLAGS_MEMBER(wxHSCROLL)
152
153 wxFLAGS_MEMBER(wxNB_FIXEDWIDTH)
154 wxFLAGS_MEMBER(wxBK_DEFAULT)
155 wxFLAGS_MEMBER(wxBK_TOP)
156 wxFLAGS_MEMBER(wxBK_LEFT)
157 wxFLAGS_MEMBER(wxBK_RIGHT)
158 wxFLAGS_MEMBER(wxBK_BOTTOM)
159 wxFLAGS_MEMBER(wxNB_NOPAGETHEME)
160 wxFLAGS_MEMBER(wxNB_FLAT)
161
162 wxEND_FLAGS( wxNotebookStyle )
163
164 IMPLEMENT_DYNAMIC_CLASS_XTI(wxNotebook, wxControl,"wx/notebook.h")
165 IMPLEMENT_DYNAMIC_CLASS_XTI(wxNotebookPageInfo, wxObject , "wx/notebook.h" )
166
167 wxCOLLECTION_TYPE_INFO( wxNotebookPageInfo * , wxNotebookPageInfoList ) ;
168
169 template<> void wxCollectionToVariantArray( wxNotebookPageInfoList const &theList, wxxVariantArray &value)
170 {
171 wxListCollectionToVariantArray<wxNotebookPageInfoList::compatibility_iterator>( theList , value ) ;
172 }
173
174 wxBEGIN_PROPERTIES_TABLE(wxNotebook)
175 wxEVENT_PROPERTY( PageChanging , wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING , wxNotebookEvent )
176 wxEVENT_PROPERTY( PageChanged , wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED , wxNotebookEvent )
177
178 wxPROPERTY_COLLECTION( PageInfos , wxNotebookPageInfoList , wxNotebookPageInfo* , AddPageInfo , GetPageInfos , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
179 wxPROPERTY_FLAGS( WindowStyle , wxNotebookStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
180 wxEND_PROPERTIES_TABLE()
181
182 wxBEGIN_HANDLERS_TABLE(wxNotebook)
183 wxEND_HANDLERS_TABLE()
184
185 wxCONSTRUCTOR_5( wxNotebook , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle)
186
187
188 wxBEGIN_PROPERTIES_TABLE(wxNotebookPageInfo)
189 wxREADONLY_PROPERTY( Page , wxNotebookPage* , GetPage , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
190 wxREADONLY_PROPERTY( Text , wxString , GetText , wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
191 wxREADONLY_PROPERTY( Selected , bool , GetSelected , false, 0 /*flags*/ , wxT("Helpstring") , wxT("group") )
192 wxREADONLY_PROPERTY( ImageId , int , GetImageId , -1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
193 wxEND_PROPERTIES_TABLE()
194
195 wxBEGIN_HANDLERS_TABLE(wxNotebookPageInfo)
196 wxEND_HANDLERS_TABLE()
197
198 wxCONSTRUCTOR_4( wxNotebookPageInfo , wxNotebookPage* , Page , wxString , Text , bool , Selected , int , ImageId )
199
200 #else
201 IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
202 IMPLEMENT_DYNAMIC_CLASS(wxNotebookPageInfo, wxObject )
203 #endif
204 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
205
206 // ============================================================================
207 // implementation
208 // ============================================================================
209
210 // ----------------------------------------------------------------------------
211 // wxNotebook construction
212 // ----------------------------------------------------------------------------
213
214 const wxNotebookPageInfoList& wxNotebook::GetPageInfos() const
215 {
216 wxNotebookPageInfoList* list = const_cast< wxNotebookPageInfoList* >( &m_pageInfos ) ;
217 WX_CLEAR_LIST( wxNotebookPageInfoList , *list ) ;
218 for( size_t i = 0 ; i < GetPageCount() ; ++i )
219 {
220 wxNotebookPageInfo *info = new wxNotebookPageInfo() ;
221 info->Create( const_cast<wxNotebook*>(this)->GetPage(i) , GetPageText(i) , GetSelection() == int(i) , GetPageImage(i) ) ;
222 list->Append( info ) ;
223 }
224 return m_pageInfos ;
225 }
226
227 // common part of all ctors
228 void wxNotebook::Init()
229 {
230 m_imageList = NULL;
231 m_nSelection = -1;
232
233 #if wxUSE_UXTHEME
234 m_hbrBackground = NULL;
235 #endif // wxUSE_UXTHEME
236
237 #if USE_NOTEBOOK_ANTIFLICKER
238 m_hasSubclassedUpdown = false;
239 #endif // USE_NOTEBOOK_ANTIFLICKER
240 }
241
242 // default for dynamic class
243 wxNotebook::wxNotebook()
244 {
245 Init();
246 }
247
248 // the same arguments as for wxControl
249 wxNotebook::wxNotebook(wxWindow *parent,
250 wxWindowID id,
251 const wxPoint& pos,
252 const wxSize& size,
253 long style,
254 const wxString& name)
255 {
256 Init();
257
258 Create(parent, id, pos, size, style, name);
259 }
260
261 // Create() function
262 bool wxNotebook::Create(wxWindow *parent,
263 wxWindowID id,
264 const wxPoint& pos,
265 const wxSize& size,
266 long style,
267 const wxString& name)
268 {
269 if ( (style & wxBK_ALIGN_MASK) == wxBK_DEFAULT )
270 {
271 #if defined(__POCKETPC__)
272 style |= wxBK_BOTTOM | wxNB_FLAT;
273 #else
274 style |= wxBK_TOP;
275 #endif
276 }
277
278 #ifdef __WXWINCE__
279 // Not sure why, but without this style, there is no border
280 // around the notebook tabs.
281 if (style & wxNB_FLAT)
282 style |= wxBORDER_SUNKEN;
283 #endif
284
285 #if !wxUSE_UXTHEME
286 // ComCtl32 notebook tabs simply don't work unless they're on top if we have uxtheme, we can
287 // work around it later (after control creation), but if we don't have uxtheme, we have to clear
288 // those styles
289 const int verComCtl32 = wxApp::GetComCtl32Version();
290 if ( verComCtl32 == 600 )
291 {
292 style &= ~(wxBK_BOTTOM | wxBK_LEFT | wxBK_RIGHT);
293 }
294 #endif //wxUSE_UXTHEME
295
296 LPCTSTR className = WC_TABCONTROL;
297
298 #if USE_NOTEBOOK_ANTIFLICKER
299 // SysTabCtl32 class has natively CS_HREDRAW and CS_VREDRAW enabled and it
300 // causes horrible flicker when resizing notebook, so get rid of it by
301 // using a class without these styles (but otherwise identical to it)
302 if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
303 {
304 static ClassRegistrar s_clsNotebook;
305 if ( !s_clsNotebook.IsInitialized() )
306 {
307 // get a copy of standard class and modify it
308 WNDCLASS wc;
309
310 if ( ::GetClassInfo(NULL, WC_TABCONTROL, &wc) )
311 {
312 gs_wndprocNotebook =
313 wx_reinterpret_cast(WXFARPROC, wc.lpfnWndProc);
314 wc.lpszClassName = wxT("_wx_SysTabCtl32");
315 wc.style &= ~(CS_HREDRAW | CS_VREDRAW);
316 wc.hInstance = wxGetInstance();
317 wc.lpfnWndProc = wxNotebookWndProc;
318 s_clsNotebook.Register(wc);
319 }
320 else
321 {
322 wxLogLastError(_T("GetClassInfoEx(SysTabCtl32)"));
323 }
324 }
325
326 // use our custom class if available but fall back to the standard
327 // notebook if we failed to register it
328 if ( s_clsNotebook.IsRegistered() )
329 {
330 // it's ok to use c_str() here as the static s_clsNotebook object
331 // has sufficiently long lifetime
332 className = s_clsNotebook.GetName().c_str();
333 }
334 }
335 #endif // USE_NOTEBOOK_ANTIFLICKER
336
337 if ( !CreateControl(parent, id, pos, size, style | wxTAB_TRAVERSAL,
338 wxDefaultValidator, name) )
339 return false;
340
341 if ( !MSWCreateControl(className, wxEmptyString, pos, size) )
342 return false;
343
344 #if wxUSE_UXTHEME
345 if ( HasFlag(wxNB_NOPAGETHEME) ||
346 wxSystemOptions::IsFalse(wxT("msw.notebook.themed-background")) )
347 {
348 SetBackgroundColour(GetThemeBackgroundColour());
349 }
350 else // use themed background by default
351 {
352 // create backing store
353 UpdateBgBrush();
354 }
355
356 // comctl32.dll 6.0 doesn't support non-top tabs with visual styles (the
357 // control is simply not rendered correctly), so we disable themes
358 // if possible, otherwise we simply clear the styles.
359 // It's probably not possible to have UXTHEME without ComCtl32 6 or better, but lets
360 // check it anyway.
361 const int verComCtl32 = wxApp::GetComCtl32Version();
362 if ( verComCtl32 == 600 )
363 {
364 // check if we use themes at all -- if we don't, we're still okay
365 if ( wxUxThemeEngine::GetIfActive() && (style & (wxBK_BOTTOM|wxBK_LEFT|wxBK_RIGHT)))
366 {
367 wxUxThemeEngine::GetIfActive()->SetWindowTheme((HWND)this->GetHandle(), L"", L"");
368 SetBackgroundColour(GetThemeBackgroundColour()); //correct the background color for the new non-themed control
369 }
370 }
371 #endif // wxUSE_UXTHEME
372
373 // Undocumented hack to get flat notebook style
374 // In fact, we should probably only do this in some
375 // curcumstances, i.e. if we know we will have a border
376 // at the bottom (the tab control doesn't draw it itself)
377 #if defined(__POCKETPC__) || defined(__SMARTPHONE__)
378 if (HasFlag(wxNB_FLAT))
379 {
380 SendMessage(GetHwnd(), CCM_SETVERSION, COMCTL32_VERSION, 0);
381 if (!m_hasBgCol)
382 SetBackgroundColour(*wxWHITE);
383 }
384 #endif
385 return true;
386 }
387
388 WXDWORD wxNotebook::MSWGetStyle(long style, WXDWORD *exstyle) const
389 {
390 WXDWORD tabStyle = wxControl::MSWGetStyle(style, exstyle);
391
392 tabStyle |= WS_TABSTOP | TCS_TABS;
393
394 if ( style & wxNB_MULTILINE )
395 tabStyle |= TCS_MULTILINE;
396 if ( style & wxNB_FIXEDWIDTH )
397 tabStyle |= TCS_FIXEDWIDTH;
398
399 if ( style & wxBK_BOTTOM )
400 tabStyle |= TCS_RIGHT;
401 else if ( style & wxBK_LEFT )
402 tabStyle |= TCS_VERTICAL;
403 else if ( style & wxBK_RIGHT )
404 tabStyle |= TCS_VERTICAL | TCS_RIGHT;
405
406 // ex style
407 if ( exstyle )
408 {
409 // note that we never want to have the default WS_EX_CLIENTEDGE style
410 // as it looks too ugly for the notebooks
411 *exstyle = 0;
412 }
413
414 return tabStyle;
415 }
416
417 wxNotebook::~wxNotebook()
418 {
419 #if wxUSE_UXTHEME
420 if ( m_hbrBackground )
421 ::DeleteObject((HBRUSH)m_hbrBackground);
422 #endif // wxUSE_UXTHEME
423 }
424
425 // ----------------------------------------------------------------------------
426 // wxNotebook accessors
427 // ----------------------------------------------------------------------------
428
429 size_t wxNotebook::GetPageCount() const
430 {
431 // consistency check
432 wxASSERT( (int)m_pages.Count() == TabCtrl_GetItemCount(GetHwnd()) );
433
434 return m_pages.Count();
435 }
436
437 int wxNotebook::GetRowCount() const
438 {
439 return TabCtrl_GetRowCount(GetHwnd());
440 }
441
442 int wxNotebook::SetSelection(size_t nPage)
443 {
444 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
445
446 if ( int(nPage) != m_nSelection )
447 {
448 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId);
449 event.SetSelection(nPage);
450 event.SetOldSelection(m_nSelection);
451 event.SetEventObject(this);
452 if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
453 {
454 // program allows the page change
455 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
456 (void)GetEventHandler()->ProcessEvent(event);
457
458 TabCtrl_SetCurSel(GetHwnd(), nPage);
459 }
460 }
461
462 return m_nSelection;
463 }
464
465 void wxNotebook::UpdateSelection(size_t newsel)
466 {
467 if ( m_nSelection != -1 )
468 m_pages[m_nSelection]->Show(false);
469
470 if ( newsel != -1 )
471 {
472 wxNotebookPage *pPage = m_pages[newsel];
473 pPage->Show(true);
474 }
475
476 // Changing the page should give the focus to it but, as per bug report
477 // http://sf.net/tracker/index.php?func=detail&aid=1150659&group_id=9863&atid=109863,
478 // we should not set the focus to it directly since it erroneously
479 // selects radio buttons and breaks keyboard handling for a notebook's
480 // scroll buttons. So give focus to the notebook and not the page.
481
482 // but don't do this is the notebook is hidden
483 if ( ::IsWindowVisible(GetHwnd()) )
484 SetFocus();
485
486 m_nSelection = newsel;
487 }
488
489 int wxNotebook::ChangeSelection(size_t nPage)
490 {
491 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
492
493 if ( int(nPage) != m_nSelection )
494 {
495 TabCtrl_SetCurSel(GetHwnd(), nPage);
496
497 UpdateSelection(nPage);
498 }
499
500 return m_nSelection;
501 }
502
503 bool wxNotebook::SetPageText(size_t nPage, const wxString& strText)
504 {
505 wxCHECK_MSG( IS_VALID_PAGE(nPage), false, wxT("notebook page out of range") );
506
507 TC_ITEM tcItem;
508 tcItem.mask = TCIF_TEXT;
509 tcItem.pszText = (wxChar *)strText.c_str();
510
511 if ( !HasFlag(wxNB_MULTILINE) )
512 return TabCtrl_SetItem(GetHwnd(), nPage, &tcItem) != 0;
513
514 // multiline - we need to set new page size if a line is added or removed
515 int rows = GetRowCount();
516 bool ret = TabCtrl_SetItem(GetHwnd(), nPage, &tcItem) != 0;
517
518 if ( ret && rows != GetRowCount() )
519 {
520 const wxRect r = GetPageSize();
521 const size_t count = m_pages.Count();
522 for ( size_t page = 0; page < count; page++ )
523 m_pages[page]->SetSize(r);
524 }
525
526 return ret;
527 }
528
529 wxString wxNotebook::GetPageText(size_t nPage) const
530 {
531 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxEmptyString, wxT("notebook page out of range") );
532
533 wxChar buf[256];
534 TC_ITEM tcItem;
535 tcItem.mask = TCIF_TEXT;
536 tcItem.pszText = buf;
537 tcItem.cchTextMax = WXSIZEOF(buf);
538
539 wxString str;
540 if ( TabCtrl_GetItem(GetHwnd(), nPage, &tcItem) )
541 str = tcItem.pszText;
542
543 return str;
544 }
545
546 int wxNotebook::GetPageImage(size_t nPage) const
547 {
548 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
549
550 TC_ITEM tcItem;
551 tcItem.mask = TCIF_IMAGE;
552
553 return TabCtrl_GetItem(GetHwnd(), nPage, &tcItem) ? tcItem.iImage : wxNOT_FOUND;
554 }
555
556 bool wxNotebook::SetPageImage(size_t nPage, int nImage)
557 {
558 wxCHECK_MSG( IS_VALID_PAGE(nPage), false, wxT("notebook page out of range") );
559
560 TC_ITEM tcItem;
561 tcItem.mask = TCIF_IMAGE;
562 tcItem.iImage = nImage;
563
564 return TabCtrl_SetItem(GetHwnd(), nPage, &tcItem) != 0;
565 }
566
567 void wxNotebook::SetImageList(wxImageList* imageList)
568 {
569 wxNotebookBase::SetImageList(imageList);
570
571 if ( imageList )
572 {
573 (void) TabCtrl_SetImageList(GetHwnd(), (HIMAGELIST)imageList->GetHIMAGELIST());
574 }
575 }
576
577 // ----------------------------------------------------------------------------
578 // wxNotebook size settings
579 // ----------------------------------------------------------------------------
580
581 wxRect wxNotebook::GetPageSize() const
582 {
583 wxRect r;
584
585 RECT rc;
586 ::GetClientRect(GetHwnd(), &rc);
587
588 // This check is to work around a bug in TabCtrl_AdjustRect which will
589 // cause a crash on win2k or on XP with themes disabled if either
590 // wxNB_MULTILINE is used or tabs are placed on a side, if the rectangle
591 // is too small.
592 //
593 // The value of 20 is chosen arbitrarily but seems to work
594 if ( rc.right > 20 && rc.bottom > 20 )
595 {
596 TabCtrl_AdjustRect(GetHwnd(), false, &rc);
597
598 wxCopyRECTToRect(rc, r);
599 }
600
601 return r;
602 }
603
604 void wxNotebook::SetPageSize(const wxSize& size)
605 {
606 // transform the page size into the notebook size
607 RECT rc;
608 rc.left =
609 rc.top = 0;
610 rc.right = size.x;
611 rc.bottom = size.y;
612
613 TabCtrl_AdjustRect(GetHwnd(), true, &rc);
614
615 // and now set it
616 SetSize(rc.right - rc.left, rc.bottom - rc.top);
617 }
618
619 void wxNotebook::SetPadding(const wxSize& padding)
620 {
621 TabCtrl_SetPadding(GetHwnd(), padding.x, padding.y);
622 }
623
624 // Windows-only at present. Also, you must use the wxNB_FIXEDWIDTH
625 // style.
626 void wxNotebook::SetTabSize(const wxSize& sz)
627 {
628 ::SendMessage(GetHwnd(), TCM_SETITEMSIZE, 0, MAKELPARAM(sz.x, sz.y));
629 }
630
631 wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
632 {
633 // we can't use TabCtrl_AdjustRect here because it only works for wxNB_TOP
634 wxSize sizeTotal = sizePage;
635
636 wxSize tabSize;
637 if ( GetPageCount() > 0 )
638 {
639 RECT rect;
640 TabCtrl_GetItemRect(GetHwnd(), 0, &rect);
641 tabSize.x = rect.right - rect.left;
642 tabSize.y = rect.bottom - rect.top;
643 }
644
645 // add an extra margin in both directions
646 const int MARGIN = 8;
647 if ( IsVertical() )
648 {
649 sizeTotal.x += MARGIN;
650 sizeTotal.y += tabSize.y + MARGIN;
651 }
652 else // horizontal layout
653 {
654 sizeTotal.x += tabSize.x + MARGIN;
655 sizeTotal.y += MARGIN;
656 }
657
658 return sizeTotal;
659 }
660
661 void wxNotebook::AdjustPageSize(wxNotebookPage *page)
662 {
663 wxCHECK_RET( page, _T("NULL page in wxNotebook::AdjustPageSize") );
664
665 const wxRect r = GetPageSize();
666 if ( !r.IsEmpty() )
667 {
668 page->SetSize(r);
669 }
670 }
671
672 // ----------------------------------------------------------------------------
673 // wxNotebook operations
674 // ----------------------------------------------------------------------------
675
676 // remove one page from the notebook, without deleting
677 wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage)
678 {
679 wxNotebookPage *pageRemoved = wxNotebookBase::DoRemovePage(nPage);
680 if ( !pageRemoved )
681 return NULL;
682
683 TabCtrl_DeleteItem(GetHwnd(), nPage);
684
685 if ( m_pages.IsEmpty() )
686 {
687 // no selection any more, the notebook becamse empty
688 m_nSelection = -1;
689 }
690 else // notebook still not empty
691 {
692 int selNew = TabCtrl_GetCurSel(GetHwnd());
693 if (selNew != -1)
694 {
695 // No selection change, just refresh the current selection.
696 // Because it could be that the slection index changed
697 // we need to update it.
698 // Note: this does not mean the selection it self changed.
699 m_nSelection = selNew;
700 m_pages[m_nSelection]->Refresh();
701 }
702 else if (int(nPage) == m_nSelection)
703 {
704 // The selection was deleted.
705
706 // Determine new selection.
707 if (m_nSelection == int(GetPageCount()))
708 selNew = m_nSelection - 1;
709 else
710 selNew = m_nSelection;
711
712 // m_nSelection must be always valid so reset it before calling
713 // SetSelection()
714 m_nSelection = -1;
715 SetSelection(selNew);
716 }
717 else
718 {
719 wxFAIL; // Windows did not behave ok.
720 }
721 }
722
723 return pageRemoved;
724 }
725
726 // remove all pages
727 bool wxNotebook::DeleteAllPages()
728 {
729 size_t nPageCount = GetPageCount();
730 size_t nPage;
731 for ( nPage = 0; nPage < nPageCount; nPage++ )
732 delete m_pages[nPage];
733
734 m_pages.Clear();
735
736 TabCtrl_DeleteAllItems(GetHwnd());
737
738 m_nSelection = -1;
739
740 InvalidateBestSize();
741 return true;
742 }
743
744 // same as AddPage() but does it at given position
745 bool wxNotebook::InsertPage(size_t nPage,
746 wxNotebookPage *pPage,
747 const wxString& strText,
748 bool bSelect,
749 int imageId)
750 {
751 wxCHECK_MSG( pPage != NULL, false, _T("NULL page in wxNotebook::InsertPage") );
752 wxCHECK_MSG( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), false,
753 _T("invalid index in wxNotebook::InsertPage") );
754
755 wxASSERT_MSG( pPage->GetParent() == this,
756 _T("notebook pages must have notebook as parent") );
757
758 // add a new tab to the control
759 // ----------------------------
760
761 // init all fields to 0
762 TC_ITEM tcItem;
763 wxZeroMemory(tcItem);
764
765 // set the image, if any
766 if ( imageId != -1 )
767 {
768 tcItem.mask |= TCIF_IMAGE;
769 tcItem.iImage = imageId;
770 }
771
772 // and the text
773 if ( !strText.empty() )
774 {
775 tcItem.mask |= TCIF_TEXT;
776 tcItem.pszText = (wxChar *)strText.c_str(); // const_cast
777 }
778
779 // hide the page: unless it is selected, it shouldn't be shown (and if it
780 // is selected it will be shown later)
781 HWND hwnd = GetWinHwnd(pPage);
782 SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_VISIBLE);
783
784 // this updates internal flag too -- otherwise it would get out of sync
785 // with the real state
786 pPage->Show(false);
787
788
789 // fit the notebook page to the tab control's display area: this should be
790 // done before adding it to the notebook or TabCtrl_InsertItem() will
791 // change the notebooks size itself!
792 AdjustPageSize(pPage);
793
794 // finally do insert it
795 if ( TabCtrl_InsertItem(GetHwnd(), nPage, &tcItem) == -1 )
796 {
797 wxLogError(wxT("Can't create the notebook page '%s'."), strText.c_str());
798
799 return false;
800 }
801
802 // need to update the bg brush when the first page is added
803 // so the first panel gets the correct themed background
804 if ( m_pages.empty() )
805 {
806 UpdateBgBrush();
807 }
808
809 // succeeded: save the pointer to the page
810 m_pages.Insert(pPage, nPage);
811
812 // we may need to adjust the size again if the notebook size changed:
813 // normally this only happens for the first page we add (the tabs which
814 // hadn't been there before are now shown) but for a multiline notebook it
815 // can happen for any page at all as a new row could have been started
816 if ( m_pages.GetCount() == 1 || HasFlag(wxNB_MULTILINE) )
817 {
818 AdjustPageSize(pPage);
819 }
820
821 // now deal with the selection
822 // ---------------------------
823
824 // if the inserted page is before the selected one, we must update the
825 // index of the selected page
826 if ( int(nPage) <= m_nSelection )
827 {
828 // one extra page added
829 m_nSelection++;
830 }
831
832 // some page should be selected: either this one or the first one if there
833 // is still no selection
834 int selNew = -1;
835 if ( bSelect )
836 selNew = nPage;
837 else if ( m_nSelection == -1 )
838 selNew = 0;
839
840 if ( selNew != -1 )
841 SetSelection(selNew);
842
843 InvalidateBestSize();
844
845 return true;
846 }
847
848 int wxNotebook::HitTest(const wxPoint& pt, long *flags) const
849 {
850 TC_HITTESTINFO hitTestInfo;
851 hitTestInfo.pt.x = pt.x;
852 hitTestInfo.pt.y = pt.y;
853 int item = TabCtrl_HitTest(GetHwnd(), &hitTestInfo);
854
855 if ( flags )
856 {
857 *flags = 0;
858
859 if ((hitTestInfo.flags & TCHT_NOWHERE) == TCHT_NOWHERE)
860 *flags |= wxBK_HITTEST_NOWHERE;
861 if ((hitTestInfo.flags & TCHT_ONITEM) == TCHT_ONITEM)
862 *flags |= wxBK_HITTEST_ONITEM;
863 if ((hitTestInfo.flags & TCHT_ONITEMICON) == TCHT_ONITEMICON)
864 *flags |= wxBK_HITTEST_ONICON;
865 if ((hitTestInfo.flags & TCHT_ONITEMLABEL) == TCHT_ONITEMLABEL)
866 *flags |= wxBK_HITTEST_ONLABEL;
867 if ( item == wxNOT_FOUND && GetPageSize().Contains(pt) )
868 *flags |= wxBK_HITTEST_ONPAGE;
869 }
870
871 return item;
872 }
873
874 // ----------------------------------------------------------------------------
875 // flicker-less notebook redraw
876 // ----------------------------------------------------------------------------
877
878 #if USE_NOTEBOOK_ANTIFLICKER
879
880 // wnd proc for the spin button
881 LRESULT APIENTRY _EXPORT wxNotebookSpinBtnWndProc(HWND hwnd,
882 UINT message,
883 WPARAM wParam,
884 LPARAM lParam)
885 {
886 if ( message == WM_ERASEBKGND )
887 return 0;
888
889 return ::CallWindowProc(CASTWNDPROC gs_wndprocNotebookSpinBtn,
890 hwnd, message, wParam, lParam);
891 }
892
893 LRESULT APIENTRY _EXPORT wxNotebookWndProc(HWND hwnd,
894 UINT message,
895 WPARAM wParam,
896 LPARAM lParam)
897 {
898 return ::CallWindowProc(CASTWNDPROC gs_wndprocNotebook,
899 hwnd, message, wParam, lParam);
900 }
901
902 void wxNotebook::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
903 {
904 // do nothing here
905 }
906
907 void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event))
908 {
909 wxPaintDC dc(this);
910 wxMemoryDC memdc;
911 RECT rc;
912 ::GetClientRect(GetHwnd(), &rc);
913 wxBitmap bmp(rc.right, rc.bottom);
914 memdc.SelectObject(bmp);
915
916 // if there is no special brush just use the solid background colour
917 #if wxUSE_UXTHEME
918 HBRUSH hbr = (HBRUSH)m_hbrBackground;
919 #else
920 HBRUSH hbr = 0;
921 #endif
922 wxBrush brush;
923 if ( !hbr )
924 {
925 brush = wxBrush(GetBackgroundColour());
926 hbr = GetHbrushOf(brush);
927 }
928
929 ::FillRect(GetHdcOf(memdc), &rc, hbr);
930
931 MSWDefWindowProc(WM_PAINT, (WPARAM)memdc.GetHDC(), 0);
932
933 dc.Blit(0, 0, rc.right, rc.bottom, &memdc, 0, 0);
934 }
935
936 #endif // USE_NOTEBOOK_ANTIFLICKER
937
938 // ----------------------------------------------------------------------------
939 // wxNotebook callbacks
940 // ----------------------------------------------------------------------------
941
942 void wxNotebook::OnSize(wxSizeEvent& event)
943 {
944 if ( GetPageCount() == 0 )
945 {
946 // Prevents droppings on resize, but does cause some flicker
947 // when there are no pages.
948 Refresh();
949 event.Skip();
950 return;
951 }
952 #ifndef __WXWINCE__
953 else
954 {
955 // Without this, we can sometimes get droppings at the edges
956 // of a notebook, for example a notebook in a splitter window.
957 // This needs to be reconciled with the RefreshRect calls
958 // at the end of this function, which weren't enough to prevent
959 // the droppings.
960
961 wxSize sz = GetClientSize();
962
963 // Refresh right side
964 wxRect rect(sz.x-4, 0, 4, sz.y);
965 RefreshRect(rect);
966
967 // Refresh bottom side
968 rect = wxRect(0, sz.y-4, sz.x, 4);
969 RefreshRect(rect);
970
971 // Refresh left side
972 rect = wxRect(0, 0, 4, sz.y);
973 RefreshRect(rect);
974 }
975 #endif // !__WXWINCE__
976
977 // fit all the notebook pages to the tab control's display area
978
979 RECT rc;
980 rc.left = rc.top = 0;
981 GetSize((int *)&rc.right, (int *)&rc.bottom);
982
983 // save the total size, we'll use it below
984 int widthNbook = rc.right - rc.left,
985 heightNbook = rc.bottom - rc.top;
986
987 // there seems to be a bug in the implementation of TabCtrl_AdjustRect(): it
988 // returns completely false values for multiline tab controls after the tabs
989 // are added but before getting the first WM_SIZE (off by ~50 pixels, see
990 //
991 // http://sf.net/tracker/index.php?func=detail&aid=645323&group_id=9863&atid=109863
992 //
993 // and the only work around I could find was this ugly hack... without it
994 // simply toggling the "multiline" checkbox in the notebook sample resulted
995 // in a noticeable page displacement
996 if ( HasFlag(wxNB_MULTILINE) )
997 {
998 // avoid an infinite recursion: we get another notification too!
999 static bool s_isInOnSize = false;
1000
1001 if ( !s_isInOnSize )
1002 {
1003 s_isInOnSize = true;
1004 SendMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED,
1005 MAKELPARAM(rc.right, rc.bottom));
1006 s_isInOnSize = false;
1007 }
1008 }
1009
1010 #if wxUSE_UXTHEME
1011 // background bitmap size has changed, update the brush using it too
1012 UpdateBgBrush();
1013 #endif // wxUSE_UXTHEME
1014
1015 TabCtrl_AdjustRect(GetHwnd(), false, &rc);
1016
1017 int width = rc.right - rc.left,
1018 height = rc.bottom - rc.top;
1019 size_t nCount = m_pages.Count();
1020 for ( size_t nPage = 0; nPage < nCount; nPage++ ) {
1021 wxNotebookPage *pPage = m_pages[nPage];
1022 pPage->SetSize(rc.left, rc.top, width, height);
1023 }
1024
1025
1026 // unless we had already repainted everything, we now need to refresh
1027 if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
1028 {
1029 // invalidate areas not covered by pages
1030 RefreshRect(wxRect(0, 0, widthNbook, rc.top), false);
1031 RefreshRect(wxRect(0, rc.top, rc.left, height), false);
1032 RefreshRect(wxRect(0, rc.bottom, widthNbook, heightNbook - rc.bottom),
1033 false);
1034 RefreshRect(wxRect(rc.right, rc.top, widthNbook - rc.right, height),
1035 false);
1036 }
1037
1038 #if USE_NOTEBOOK_ANTIFLICKER
1039 // subclass the spin control used by the notebook to scroll pages to
1040 // prevent it from flickering on resize
1041 if ( !m_hasSubclassedUpdown )
1042 {
1043 // iterate over all child windows to find spin button
1044 for ( HWND child = ::GetWindow(GetHwnd(), GW_CHILD);
1045 child;
1046 child = ::GetWindow(child, GW_HWNDNEXT) )
1047 {
1048 wxWindow *childWindow = wxFindWinFromHandle((WXHWND)child);
1049
1050 // see if it exists, if no wxWindow found then assume it's the spin
1051 // btn
1052 if ( !childWindow )
1053 {
1054 // subclass the spin button to override WM_ERASEBKGND
1055 if ( !gs_wndprocNotebookSpinBtn )
1056 gs_wndprocNotebookSpinBtn = (WXFARPROC)wxGetWindowProc(child);
1057
1058 wxSetWindowProc(child, wxNotebookSpinBtnWndProc);
1059 m_hasSubclassedUpdown = true;
1060 break;
1061 }
1062 }
1063 }
1064 #endif // USE_NOTEBOOK_ANTIFLICKER
1065
1066 event.Skip();
1067 }
1068
1069 void wxNotebook::OnSelChange(wxNotebookEvent& event)
1070 {
1071 // is it our tab control?
1072 if ( event.GetEventObject() == this )
1073 {
1074 UpdateSelection(event.GetSelection());
1075 }
1076
1077 // we want to give others a chance to process this message as well
1078 event.Skip();
1079 }
1080
1081 void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
1082 {
1083 if ( event.IsWindowChange() ) {
1084 // change pages
1085 AdvanceSelection(event.GetDirection());
1086 }
1087 else {
1088 // we get this event in 3 cases
1089 //
1090 // a) one of our pages might have generated it because the user TABbed
1091 // out from it in which case we should propagate the event upwards and
1092 // our parent will take care of setting the focus to prev/next sibling
1093 //
1094 // or
1095 //
1096 // b) the parent panel wants to give the focus to us so that we
1097 // forward it to our selected page. We can't deal with this in
1098 // OnSetFocus() because we don't know which direction the focus came
1099 // from in this case and so can't choose between setting the focus to
1100 // first or last panel child
1101 //
1102 // or
1103 //
1104 // c) we ourselves (see MSWTranslateMessage) generated the event
1105 //
1106 wxWindow * const parent = GetParent();
1107
1108 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
1109 const bool isFromParent = event.GetEventObject() == (wxObject*) parent;
1110 const bool isFromSelf = event.GetEventObject() == (wxObject*) this;
1111
1112 if ( isFromParent || isFromSelf )
1113 {
1114 // no, it doesn't come from child, case (b) or (c): forward to a
1115 // page but only if direction is backwards (TAB) or from ourselves,
1116 if ( m_nSelection != -1 &&
1117 (!event.GetDirection() || isFromSelf) )
1118 {
1119 // so that the page knows that the event comes from it's parent
1120 // and is being propagated downwards
1121 event.SetEventObject(this);
1122
1123 wxWindow *page = m_pages[m_nSelection];
1124 if ( !page->GetEventHandler()->ProcessEvent(event) )
1125 {
1126 page->SetFocus();
1127 }
1128 //else: page manages focus inside it itself
1129 }
1130 else // otherwise set the focus to the notebook itself
1131 {
1132 SetFocus();
1133 }
1134 }
1135 else
1136 {
1137 // it comes from our child, case (a), pass to the parent, but only
1138 // if the direction is forwards. Otherwise set the focus to the
1139 // notebook itself. The notebook is always the 'first' control of a
1140 // page.
1141 if ( !event.GetDirection() )
1142 {
1143 SetFocus();
1144 }
1145 else if ( parent )
1146 {
1147 event.SetCurrentFocus(this);
1148 parent->GetEventHandler()->ProcessEvent(event);
1149 }
1150 }
1151 }
1152 }
1153
1154 #if wxUSE_UXTHEME
1155
1156 bool wxNotebook::DoDrawBackground(WXHDC hDC, wxWindow *child)
1157 {
1158 wxUxThemeHandle theme(child ? child : this, L"TAB");
1159 if ( !theme )
1160 return false;
1161
1162 // get the notebook client rect (we're not interested in drawing tabs
1163 // themselves)
1164 wxRect r = GetPageSize();
1165 if ( r.IsEmpty() )
1166 return false;
1167
1168 RECT rc;
1169 wxCopyRectToRECT(r, rc);
1170
1171 // map rect to the coords of the window we're drawing in
1172 if ( child )
1173 ::MapWindowPoints(GetHwnd(), GetHwndOf(child), (POINT *)&rc, 2);
1174
1175 // we have the content area (page size), but we need to draw all of the
1176 // background for it to be aligned correctly
1177 wxUxThemeEngine::Get()->GetThemeBackgroundExtent
1178 (
1179 theme,
1180 (HDC) hDC,
1181 9 /* TABP_PANE */,
1182 0,
1183 &rc,
1184 &rc
1185 );
1186 wxUxThemeEngine::Get()->DrawThemeBackground
1187 (
1188 theme,
1189 (HDC) hDC,
1190 9 /* TABP_PANE */,
1191 0,
1192 &rc,
1193 NULL
1194 );
1195
1196 return true;
1197 }
1198
1199 WXHBRUSH wxNotebook::QueryBgBitmap()
1200 {
1201 wxRect r = GetPageSize();
1202 if ( r.IsEmpty() )
1203 return 0;
1204
1205 WindowHDC hDC(GetHwnd());
1206 MemoryHDC hDCMem(hDC);
1207 CompatibleBitmap hBmp(hDC, r.x + r.width, r.y + r.height);
1208
1209 SelectInHDC selectBmp(hDCMem, hBmp);
1210
1211 if ( !DoDrawBackground((WXHDC)(HDC)hDCMem) )
1212 return 0;
1213
1214 return (WXHBRUSH)::CreatePatternBrush(hBmp);
1215 }
1216
1217 void wxNotebook::UpdateBgBrush()
1218 {
1219 if ( m_hbrBackground )
1220 ::DeleteObject((HBRUSH)m_hbrBackground);
1221
1222 if ( !m_hasBgCol && wxUxThemeEngine::GetIfActive() )
1223 {
1224 m_hbrBackground = QueryBgBitmap();
1225 }
1226 else // no themes or we've got user-defined solid colour
1227 {
1228 m_hbrBackground = NULL;
1229 }
1230 }
1231
1232 WXHBRUSH wxNotebook::MSWGetBgBrushForChild(WXHDC hDC, WXHWND hWnd)
1233 {
1234 if ( m_hbrBackground )
1235 {
1236 // before drawing with the background brush, we need to position it
1237 // correctly
1238 RECT rc;
1239 ::GetWindowRect((HWND)hWnd, &rc);
1240
1241 ::MapWindowPoints(NULL, GetHwnd(), (POINT *)&rc, 1);
1242
1243 if ( !::SetBrushOrgEx((HDC)hDC, -rc.left, -rc.top, NULL) )
1244 {
1245 wxLogLastError(_T("SetBrushOrgEx(notebook bg brush)"));
1246 }
1247
1248 return m_hbrBackground;
1249 }
1250
1251 return wxNotebookBase::MSWGetBgBrushForChild(hDC, hWnd);
1252 }
1253
1254 bool wxNotebook::MSWPrintChild(WXHDC hDC, wxWindow *child)
1255 {
1256 // solid background colour overrides themed background drawing
1257 if ( !UseBgCol() && DoDrawBackground(hDC, child) )
1258 return true;
1259
1260 // If we're using a solid colour (for example if we've switched off
1261 // theming for this notebook), paint it
1262 if (UseBgCol())
1263 {
1264 wxRect r = GetPageSize();
1265 if ( r.IsEmpty() )
1266 return false;
1267
1268 RECT rc;
1269 wxCopyRectToRECT(r, rc);
1270
1271 // map rect to the coords of the window we're drawing in
1272 if ( child )
1273 ::MapWindowPoints(GetHwnd(), GetHwndOf(child), (POINT *)&rc, 2);
1274
1275 wxBrush brush(GetBackgroundColour());
1276 HBRUSH hbr = GetHbrushOf(brush);
1277
1278 ::FillRect((HDC) hDC, &rc, hbr);
1279
1280 return true;
1281 }
1282
1283 return wxNotebookBase::MSWPrintChild(hDC, child);
1284 }
1285
1286 #endif // wxUSE_UXTHEME
1287
1288 // Windows only: attempts to get colour for UX theme page background
1289 wxColour wxNotebook::GetThemeBackgroundColour() const
1290 {
1291 #if wxUSE_UXTHEME
1292 if (wxUxThemeEngine::Get())
1293 {
1294 wxUxThemeHandle hTheme((wxNotebook*) this, L"TAB");
1295 if (hTheme)
1296 {
1297 // This is total guesswork.
1298 // See PlatformSDK\Include\Tmschema.h for values
1299 COLORREF themeColor;
1300 wxUxThemeEngine::Get()->GetThemeColor(
1301 hTheme,
1302 10 /* TABP_BODY */,
1303 1 /* NORMAL */,
1304 3821 /* FILLCOLORHINT */,
1305 &themeColor);
1306
1307 /*
1308 [DS] Workaround for WindowBlinds:
1309 Some themes return a near black theme color using FILLCOLORHINT,
1310 this makes notebook pages have an ugly black background and makes
1311 text (usually black) unreadable. Retry again with FILLCOLOR.
1312
1313 This workaround potentially breaks appearance of some themes,
1314 but in practice it already fixes some themes.
1315 */
1316 if (themeColor == 1)
1317 {
1318 wxUxThemeEngine::Get()->GetThemeColor(
1319 hTheme,
1320 10 /* TABP_BODY */,
1321 1 /* NORMAL */,
1322 3802 /* FILLCOLOR */,
1323 &themeColor);
1324 }
1325
1326 return wxRGBToColour(themeColor);
1327 }
1328 }
1329 #endif // wxUSE_UXTHEME
1330
1331 return GetBackgroundColour();
1332 }
1333
1334 // ----------------------------------------------------------------------------
1335 // wxNotebook base class virtuals
1336 // ----------------------------------------------------------------------------
1337
1338 #if wxUSE_CONSTRAINTS
1339
1340 // override these 2 functions to do nothing: everything is done in OnSize
1341
1342 void wxNotebook::SetConstraintSizes(bool WXUNUSED(recurse))
1343 {
1344 // don't set the sizes of the pages - their correct size is not yet known
1345 wxControl::SetConstraintSizes(false);
1346 }
1347
1348 bool wxNotebook::DoPhase(int WXUNUSED(nPhase))
1349 {
1350 return true;
1351 }
1352
1353 #endif // wxUSE_CONSTRAINTS
1354
1355 // ----------------------------------------------------------------------------
1356 // wxNotebook Windows message handlers
1357 // ----------------------------------------------------------------------------
1358
1359 bool wxNotebook::MSWOnScroll(int orientation, WXWORD nSBCode,
1360 WXWORD pos, WXHWND control)
1361 {
1362 // don't generate EVT_SCROLLWIN events for the WM_SCROLLs coming from the
1363 // up-down control
1364 if ( control )
1365 return false;
1366
1367 return wxNotebookBase::MSWOnScroll(orientation, nSBCode, pos, control);
1368 }
1369
1370 bool wxNotebook::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result)
1371 {
1372 wxNotebookEvent event(wxEVT_NULL, m_windowId);
1373
1374 NMHDR* hdr = (NMHDR *)lParam;
1375 switch ( hdr->code ) {
1376 case TCN_SELCHANGE:
1377 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
1378 break;
1379
1380 case TCN_SELCHANGING:
1381 event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING);
1382 break;
1383
1384 default:
1385 return wxControl::MSWOnNotify(idCtrl, lParam, result);
1386 }
1387
1388 event.SetSelection(TabCtrl_GetCurSel(GetHwnd()));
1389 event.SetOldSelection(m_nSelection);
1390 event.SetEventObject(this);
1391 event.SetInt(idCtrl);
1392
1393 bool processed = GetEventHandler()->ProcessEvent(event);
1394 *result = !event.IsAllowed();
1395 return processed;
1396 }
1397
1398 #endif // wxUSE_NOTEBOOK