EDN Admin
Well-known member
Hi,
I would like to owner draw a button using GDI+ because I needantialiased functionnality.
I did overload the DrawItem function and I try using the double buffering technic to avoid flickering. But I noticed that when Im not using it I get no flickering.
When using double buffering I get a kind of flickering. I said "kind" because it seem to be theDrawImage that is causing the problem. I see a small rectangle in the bottom of the result DC (button DC) that is not the same color as the rest of the background color.
I made a small program to demonstrate the problem.
MyButton.hclass CMyButton : public CButton
{
DECLARE_DYNAMIC(CMyButton)
public:
CMyButton();
virtual ~CMyButton();
protected:
void CMyButton:rawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
DECLARE_MESSAGE_MAP()
virtual void PreSubclassWindow();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};
MyButton.cpp
#include "stdafx.h"
#include "MFCWin32_TestDivers.h"
#include "MyButton.h"
#define MY_BUTTON_DOUBLE_BUFFERING 1
// CMyButton
IMPLEMENT_DYNAMIC(CMyButton, CButton)
CMyButton::CMyButton()
{
}
CMyButton::~CMyButton()
{
}
BEGIN_MESSAGE_MAP(CMyButton, CButton)
ON_WM_ERASEBKGND()
ON_WM_DESTROY()
ON_WM_SIZE()
END_MESSAGE_MAP()
void CMyButton:reSubclassWindow()
{
ModifyStyle(0, BS_OWNERDRAW, SWP_FRAMECHANGED);
CButton:reSubclassWindow();
}
BOOL CMyButton:reTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_LBUTTONDBLCLK)
{
pMsg->message = WM_LBUTTONDOWN;
}
return CButton:reTranslateMessage(pMsg);
}
void CMyButton:rawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CRect rc;
GetClientRect (&rc);
#if (MY_BUTTON_DOUBLE_BUFFERING == 1)
Bitmap bmp(rc.Width(), rc.Height());
Graphics graphics(&bmp);
#else
Graphics graphics(this->m_hWnd);
#endif
Rect r(rc.left, rc.top, rc.Width() -1, rc.Height() -1);
Pen pn(Color::Black, 1.0f);
if ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0)
{
SolidBrush br(Color(255, 0, 0));
graphics.FillRectangle(&br, r);
graphics.DrawRectangle(&pn, r);
}
else
{
SolidBrush br(Color(0, 0, 0));
graphics.FillRectangle(&br, r);
graphics.DrawRectangle(&pn, r);
}
#if (MY_BUTTON_DOUBLE_BUFFERING == 1)
Graphics graphi(this->m_hWnd);
graphi.DrawImage(&bmp, 0, 0);
#endif
}
BOOL CMyButton::OnEraseBkgnd(CDC* pDC)
{
#if (MY_BUTTON_DOUBLE_BUFFERING == 1)
return TRUE;
#else
return CButton::OnEraseBkgnd(pDC);
#endif
}
I create a preprocessor MY_BUTTON_DOUBLE_BUFFERING that allow to toggle between DoubleBuffering and No DoubleBuffering. Simply set it to 1 for double buffering and 0 to no double buffering.
Try to click repeatedly and quickly on the button and you will notice that when using the Double buffering, you will see the small rectangle at the bottom of the button that seem to be poorly refreshed :-(
I also tried to move the double buffering object as a class member and pre-created it only when the button changed its size.But I get the same result.
In the past, Ive already subclassed CButton for doing something similar (without having need of GDI+) using all the drawing stuff of the regular GDI and double buffering technic and I never get this kind of problem before.
Does anyone have an idea ? I do not know what to do at all...
Best regards,
Martin
View the full article
I would like to owner draw a button using GDI+ because I needantialiased functionnality.
I did overload the DrawItem function and I try using the double buffering technic to avoid flickering. But I noticed that when Im not using it I get no flickering.
When using double buffering I get a kind of flickering. I said "kind" because it seem to be theDrawImage that is causing the problem. I see a small rectangle in the bottom of the result DC (button DC) that is not the same color as the rest of the background color.
I made a small program to demonstrate the problem.
MyButton.hclass CMyButton : public CButton
{
DECLARE_DYNAMIC(CMyButton)
public:
CMyButton();
virtual ~CMyButton();
protected:
void CMyButton:rawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
DECLARE_MESSAGE_MAP()
virtual void PreSubclassWindow();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};
MyButton.cpp
#include "stdafx.h"
#include "MFCWin32_TestDivers.h"
#include "MyButton.h"
#define MY_BUTTON_DOUBLE_BUFFERING 1
// CMyButton
IMPLEMENT_DYNAMIC(CMyButton, CButton)
CMyButton::CMyButton()
{
}
CMyButton::~CMyButton()
{
}
BEGIN_MESSAGE_MAP(CMyButton, CButton)
ON_WM_ERASEBKGND()
ON_WM_DESTROY()
ON_WM_SIZE()
END_MESSAGE_MAP()
void CMyButton:reSubclassWindow()
{
ModifyStyle(0, BS_OWNERDRAW, SWP_FRAMECHANGED);
CButton:reSubclassWindow();
}
BOOL CMyButton:reTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_LBUTTONDBLCLK)
{
pMsg->message = WM_LBUTTONDOWN;
}
return CButton:reTranslateMessage(pMsg);
}
void CMyButton:rawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CRect rc;
GetClientRect (&rc);
#if (MY_BUTTON_DOUBLE_BUFFERING == 1)
Bitmap bmp(rc.Width(), rc.Height());
Graphics graphics(&bmp);
#else
Graphics graphics(this->m_hWnd);
#endif
Rect r(rc.left, rc.top, rc.Width() -1, rc.Height() -1);
Pen pn(Color::Black, 1.0f);
if ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0)
{
SolidBrush br(Color(255, 0, 0));
graphics.FillRectangle(&br, r);
graphics.DrawRectangle(&pn, r);
}
else
{
SolidBrush br(Color(0, 0, 0));
graphics.FillRectangle(&br, r);
graphics.DrawRectangle(&pn, r);
}
#if (MY_BUTTON_DOUBLE_BUFFERING == 1)
Graphics graphi(this->m_hWnd);
graphi.DrawImage(&bmp, 0, 0);
#endif
}
BOOL CMyButton::OnEraseBkgnd(CDC* pDC)
{
#if (MY_BUTTON_DOUBLE_BUFFERING == 1)
return TRUE;
#else
return CButton::OnEraseBkgnd(pDC);
#endif
}
I create a preprocessor MY_BUTTON_DOUBLE_BUFFERING that allow to toggle between DoubleBuffering and No DoubleBuffering. Simply set it to 1 for double buffering and 0 to no double buffering.
Try to click repeatedly and quickly on the button and you will notice that when using the Double buffering, you will see the small rectangle at the bottom of the button that seem to be poorly refreshed :-(
I also tried to move the double buffering object as a class member and pre-created it only when the button changed its size.But I get the same result.
In the past, Ive already subclassed CButton for doing something similar (without having need of GDI+) using all the drawing stuff of the regular GDI and double buffering technic and I never get this kind of problem before.
Does anyone have an idea ? I do not know what to do at all...
Best regards,
Martin
View the full article