+// ----------------------------------------------------------------------------
+// flicker-less notebook redraw
+// ----------------------------------------------------------------------------
+
+#if USE_NOTEBOOK_ANTIFLICKER
+
+// wnd proc for the spin button
+LRESULT APIENTRY _EXPORT wxNotebookSpinBtnWndProc(HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ if ( message == WM_ERASEBKGND )
+ return 0;
+
+ return ::CallWindowProc(CASTWNDPROC gs_wndprocNotebookSpinBtn,
+ hwnd, message, wParam, lParam);
+}
+
+LRESULT APIENTRY _EXPORT wxNotebookWndProc(HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ return ::CallWindowProc(CASTWNDPROC gs_wndprocNotebook,
+ hwnd, message, wParam, lParam);
+}
+
+void wxNotebook::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
+{
+ // do nothing here
+}
+
+void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event))
+{
+ wxPaintDC dc(this);
+ wxMemoryDC memdc;
+ RECT rc;
+ ::GetClientRect(GetHwnd(), &rc);
+ wxBitmap bmp(rc.right, rc.bottom);
+ memdc.SelectObject(bmp);
+
+ const wxLayoutDirection dir = dc.GetLayoutDirection();
+ memdc.SetLayoutDirection(dir);
+
+ const HDC hdc = GetHdcOf(memdc);
+
+ // The drawing logic of the native tab control is absolutely impenetrable
+ // but observation shows that in the current Windows versions (XP and 7),
+ // the tab control always erases its entire background in its window proc
+ // when the tabs are top-aligned but does not do it when the tabs are in
+ // any other position.
+ //
+ // This means that we can't rely on our background colour being used for
+ // the blank area in the tab row because this doesn't work in the default
+ // top-aligned case, hence the hack with ExtFloodFill() below. But it also
+ // means that we still do need to erase the DC to account for the other
+ // cases.
+ //
+ // Moreover, just in case some very old or very new (or even future,
+ // although it seems unlikely that this is ever going to change by now)
+ // version of Windows didn't do it like this, do both things in all cases
+ // instead of optimizing away the one of them which doesn't do anything for
+ // the effectively used tab orientation -- better safe than fast.
+
+ // Notice that we use our own background here, not the background used for
+ // the pages, because the tab row background must blend with the parent and
+ // so the background colour inherited from it (if any) must be used.
+ AutoHBRUSH hbr(wxColourToRGB(GetBackgroundColour()));
+
+ ::FillRect(hdc, &rc, hbr);
+
+ MSWDefWindowProc(WM_PAINT, (WPARAM)hdc, 0);
+
+ // At least for the top-aligned tabs, our background colour was overwritten
+ // and so we now replace the default background with our colour. This is
+ // horribly inefficient, of course, but seems to be the only way to do it.
+ if ( UseBgCol() )
+ {
+ SelectInHDC selectBrush(hdc, hbr);
+
+ // Find the point which must contain the default background colour:
+ // this is a hack, of course, but using this point "close" to the
+ // corner seems to work fine in practice.
+ int x = 0,
+ y = 0;
+
+ switch ( GetWindowStyle() & wxBK_ALIGN_MASK )
+ {
+ case wxBK_TOP:
+ x = rc.right - 2;
+ y = 2;
+ break;
+
+ case wxBK_BOTTOM:
+ x = rc.right - 2;
+ y = rc.bottom - 2;
+ break;
+
+ case wxBK_LEFT:
+ x = 2;
+ y = rc.bottom - 2;
+ break;
+
+ case wxBK_RIGHT:
+ x = 2;
+ y = rc.bottom - 2;
+ break;
+ }
+
+ ::ExtFloodFill(hdc, x, y, ::GetSysColor(COLOR_BTNFACE), FLOODFILLSURFACE);
+ }
+
+ // For some reason in RTL mode, source offset has to be -1, otherwise the
+ // right border (physical) remains unpainted.
+ const wxCoord ofs = dir == wxLayout_RightToLeft ? -1 : 0;
+ dc.Blit(ofs, 0, rc.right, rc.bottom, &memdc, ofs, 0);
+}
+
+#endif // USE_NOTEBOOK_ANTIFLICKER