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