/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/notebook.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/notebook.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22