- To produce the flicker effect, create an MFC Application named FlickerFree
- Create it as a Single Document type
- Using the Resource Symbols dialog box, create an ID named IDT_OCCUR
- In the view header file, declare the following variables:
// FlickerFreeView.h : interface of the CFlickerFreeView class
//
#pragma once
class CFlickerFreeView : public CView
{
protected: // create from serialization only
CFlickerFreeView();
DECLARE_DYNCREATE(CFlickerFreeView)
// Attributes
public:
CFlickerFreeDoc* GetDocument() const;
// Operations
public:
// Overrides
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// Implementation
public:
virtual ~CFlickerFreeView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
private:
int x;
int y;
int w;
int h;
BOOL MovingRight;
};
#ifndef _DEBUG // debug version in FlickerFreeView.cpp
inline CFlickerFreeDoc* CFlickerFreeView::GetDocument() const
{ return reinterpret_cast<CFlickerFreeDoc*>(m_pDocument); }
#endif
|
- In the constructor of the view class, initialize the variables as follows:
CFlickerFreeView::CFlickerFreeView()
{
// TODO: add construction code here
x = 0;
y = 100;
w = 100;
h = 150;
MovingRight = TRUE;
}
|
- Generate the OnInitialUpdate event for the view class and use it to
initialize the timer as follows:
void CFlickerFreeView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
SetTimer(IDT_OCCUR, 10, NULL);
}
|
- Change the OnDraw event as follows:
void CFlickerFreeView::OnDraw(CDC* pDC)
{
CFlickerFreeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
CRect rect;
CBrush brsBlack, *brsOld;
GetClientRect(&rect);
brsBlack.CreateSolidBrush(RGB(0, 0, 0));
brsOld = pDC->SelectObject(&brsBlack);
pDC->Rectangle(rect.left, rect.top, rect.Width(), rect.Height());
CPen penRed, *penOld;
penRed.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
penOld = pDC->SelectObject(&penRed);
pDC->Rectangle(x, y, x + 100, h);
pDC->SelectObject(penOld);
pDC->SelectObject(brsOld);
}
|
- Generate the event of the WM_TIMER message for the view class and
implement it as follows:
void CFlickerFreeView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CRect rect;
GetClientRect(&rect);
if( x < 0 )
{
x = 0;
MovingRight = TRUE;
}
if( x > (rect.Width() - 100) )
{
x = rect.Width() - 100;
MovingRight = FALSE;
}
Invalidate();
if( MovingRight == TRUE )
x++;
else
x--;
CView::OnTimer(nIDEvent);
}
|
- Execute the application to see the result and notice the flickering effect
- Close the application
Fortunately, in most cases, getting rid of, or reducing, the
flickering effect can be easy. To take care of it, override the OnEraseBkgnd
event and simply return TRUE from it.
Practical Learning: Taking Care of Flickering
|
|
- Generate the event of the WM_ERASEBKGND message of the view class and
change its return value as follows:
BOOL CFlickerFreeView::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;// CView::OnEraseBkgnd(pDC);
}
|
- Execute the application again to see the result
|
|