- 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
|