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