fixed remains of notebook flickering (improved patch 1181975)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@34269 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2005-05-22 18:10:34 +00:00
parent e7f28a5864
commit 014ee083ec

View File

@@ -57,12 +57,14 @@
// check that the page index is valid
#define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
// you can set USE_NOTEBOOK_ANTIFLICKER to 0 for desktop Windows versions too
// to disable code whih results in flicker-less notebook redrawing at the
// expense of some extra GDI resource consumption
#ifdef __WXWINCE__
#define USE_NOTEBOOK_ANTIFLICKER 0
// notebooks are never resized under CE anyhow
#define USE_NOTEBOOK_ANTIFLICKER 0
#else
// Set this to 1 to compile anti-flicker code, which creates a potentially
// large bitmap for every paint event
#define USE_NOTEBOOK_ANTIFLICKER 0
#define USE_NOTEBOOK_ANTIFLICKER 1
#endif
// ----------------------------------------------------------------------------
@@ -82,6 +84,17 @@
#define TCS_BOTTOM TCS_RIGHT
#endif
// ----------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------
#if USE_NOTEBOOK_ANTIFLICKER
// the pointer to standard spin button wnd proc
static WXFARPROC gs_wndprocNotebookSpinBtn = (WXFARPROC)NULL;
#endif // USE_NOTEBOOK_ANTIFLICKER
// ----------------------------------------------------------------------------
// event table
// ----------------------------------------------------------------------------
@@ -94,13 +107,14 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
BEGIN_EVENT_TABLE(wxNotebook, wxControl)
#if USE_NOTEBOOK_ANTIFLICKER
EVT_ERASE_BACKGROUND(wxNotebook::OnEraseBackground)
EVT_PAINT(wxNotebook::OnPaint)
#endif
EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange)
EVT_SIZE(wxNotebook::OnSize)
EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
#if USE_NOTEBOOK_ANTIFLICKER
EVT_ERASE_BACKGROUND(wxNotebook::OnEraseBackground)
EVT_PAINT(wxNotebook::OnPaint)
#endif // USE_NOTEBOOK_ANTIFLICKER
END_EVENT_TABLE()
#if wxUSE_EXTENDED_RTTI
@@ -185,25 +199,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxNotebookPageInfo, wxObject )
#endif
IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
// ---------------------------------------------------------------------------
// private functions
// ---------------------------------------------------------------------------
#if USE_NOTEBOOK_ANTIFLICKER
// wnd proc for the spin button
LRESULT APIENTRY _EXPORT wxNotebookSpinBtnWndProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
// ---------------------------------------------------------------------------
// global vars
// ---------------------------------------------------------------------------
// the pointer to standard spin button wnd proc
static WXFARPROC s_wndprocNotebookSpinBtn = (WXFARPROC)NULL;
#endif
// ============================================================================
// implementation
// ============================================================================
@@ -771,6 +766,53 @@ int wxNotebook::HitTest(const wxPoint& pt, long *flags) const
return item;
}
// ----------------------------------------------------------------------------
// 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);
}
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);
// if there is no special brush just use the solid background colour
HBRUSH hbr = (HBRUSH)m_hbrBackground;
if ( !hbr )
hbr = GetHbrushOf(wxBrush(GetBackgroundColour()));
::FillRect(GetHdcOf(memdc), &rc, hbr);
MSWDefWindowProc(WM_PAINT, (WPARAM)memdc.GetHDC(), 0);
dc.Blit(0, 0, rc.right, rc.bottom, &memdc, 0, 0);
}
#endif // USE_NOTEBOOK_ANTIFLICKER
// ----------------------------------------------------------------------------
// wxNotebook callbacks
@@ -809,7 +851,7 @@ void wxNotebook::OnSize(wxSizeEvent& event)
rect = wxRect(0, 0, 4, sz.y);
RefreshRect(rect);
}
#endif
#endif // !__WXWINCE__
// fit all the notebook pages to the tab control's display area
@@ -872,6 +914,32 @@ void wxNotebook::OnSize(wxSizeEvent& event)
false);
}
#if USE_NOTEBOOK_ANTIFLICKER
// subclass the spin control used by the notebook to scroll pages to
// prevent it from flickering on resize
if ( !gs_wndprocNotebookSpinBtn )
{
// iterate over all child windows to find spin button
for ( HWND child = ::GetWindow(GetHwnd(), GW_CHILD);
child;
child = ::GetWindow(child, GW_HWNDNEXT) )
{
wxWindow *childWindow = wxFindWinFromHandle((WXHWND)child);
// see if it exists, if no wxWindow found then assume it's the spin
// btn
if ( !childWindow )
{
// subclass the spin button to override WM_ERASEBKGND
gs_wndprocNotebookSpinBtn = (WXFARPROC)wxGetWindowProc(child);
wxSetWindowProc(child, wxNotebookSpinBtnWndProc);
break;
}
}
}
#endif // USE_NOTEBOOK_ANTIFLICKER
event.Skip();
}
@@ -1251,78 +1319,4 @@ bool wxNotebook::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result)
return processed;
}
#ifndef __WXWINCE__
void wxNotebook::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
{
// do nothing here
}
void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event))
{
// Better painting behaviour, at the expense of system resources
#if USE_NOTEBOOK_ANTIFLICKER
wxPaintDC dc(this);
wxMemoryDC memdc;
RECT rc;
::GetClientRect(GetHwnd(), &rc);
wxBitmap bmp(rc.right, rc.bottom);
memdc.SelectObject(bmp);
// iterate over all child windows to find spin button
for ( HWND child = ::GetWindow(GetHwnd(), GW_CHILD);
child;
child = ::GetWindow(child, GW_HWNDNEXT) )
{
wxWindow *childWindow = wxFindWinFromHandle((WXHWND)child);
// see if it exists, if no wxWindow found then assume it's the spin btn
if ( !childWindow )
{
// subclass the spin button to override WM_ERASEBKGND
if ( !s_wndprocNotebookSpinBtn )
s_wndprocNotebookSpinBtn = (WXFARPROC)wxGetWindowProc(child);
wxSetWindowProc(child, wxNotebookSpinBtnWndProc);
break;
}
}
HBRUSH hbr = (HBRUSH)m_hbrBackground;
// if there is no special brush just use the solid background colour
wxBrush brush;
if ( !hbr )
{
brush = wxBrush(GetBackgroundColour());
hbr = GetHbrushOf(brush);
}
::FillRect(GetHdcOf(memdc), &rc, hbr);
MSWDefWindowProc(WM_PAINT, (WPARAM)memdc.GetHDC(), 0);
dc.Blit(0, 0, rc.right, rc.bottom, &memdc, 0, 0);
#endif
}
#endif
// __WXWINCE__
#if USE_NOTEBOOK_ANTIFLICKER
// ---------------------------------------------------------------------------
// window proc for spin button
// ---------------------------------------------------------------------------
LRESULT APIENTRY _EXPORT wxNotebookSpinBtnWndProc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
if ( message == WM_ERASEBKGND )
return 0;
return ::CallWindowProc(CASTWNDPROC s_wndprocNotebookSpinBtn, hwnd, message, wParam, lParam);
}
#endif // USE_NOTEBOOK_ANTIFLICKER
#endif // wxUSE_NOTEBOOK