Applied patch [ 1181975 ] [wxMSW] Removes all flicker from wxNotebook

with modifications. Disabled until you set USE_NOTEBOOK_ANTIFLICKER
to 1. Also added code to refresh edges of the notebook to eliminate
droppings.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33743 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2005-04-19 08:47:36 +00:00
parent 4930046b96
commit 254fbd140e
2 changed files with 137 additions and 0 deletions

View File

@@ -232,6 +232,11 @@ protected:
WXHBRUSH m_hbrBackground;
#endif // wxUSE_UXTHEME
// No need to optimize for WinCE
#ifndef __WXWINCE__
void OnEraseBackground(wxEraseEvent& event);
void OnPaint(wxPaintEvent& event);
#endif
DECLARE_DYNAMIC_CLASS_NO_COPY(wxNotebook)
DECLARE_EVENT_TABLE()

View File

@@ -35,6 +35,8 @@
#include "wx/notebook.h"
#include "wx/app.h"
#include "wx/sysopt.h"
#include "wx/dcclient.h"
#include "wx/dcmemory.h"
#include "wx/msw/private.h"
@@ -64,6 +66,14 @@
// hide the ugly cast
#define m_hwnd (HWND)GetHWND()
#ifdef __WXWINCE__
#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
#endif
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
@@ -93,6 +103,10 @@ 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)
@@ -180,6 +194,25 @@ 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
// ============================================================================
@@ -762,6 +795,30 @@ void wxNotebook::OnSize(wxSizeEvent& event)
event.Skip();
return;
}
#ifndef __WXWINCE__
else
{
// Without this, we can sometimes get droppings at the edges
// of a notebook, for example a notebook in a splitter window.
// This needs to be reconciled with the RefreshRect calls
// at the end of this function, which weren't enough to prevent
// the droppings.
wxSize sz = GetClientSize();
// Refresh right side
wxRect rect(sz.x-4, 0, 4, sz.y);
RefreshRect(rect);
// Refresh bottom side
rect = wxRect(0, sz.y-4, sz.x, 4);
RefreshRect(rect);
// Refresh left side
rect = wxRect(0, 0, 4, sz.y);
RefreshRect(rect);
}
#endif
// fit all the notebook pages to the tab control's display area
@@ -1179,4 +1236,79 @@ 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