首页 » 技术分享 » 一个双缓冲原理的解释:Flash按钮

一个双缓冲原理的解释:Flash按钮

 

转载请注明来源:http://blog.csdn.net/caoshiying/article/details/52218665

解决闪屏的问题一定要使用双缓冲技术吗?不是。本文将顺便介绍在没有使用双缓冲的如何解决闪屏的问题。本示例同时介绍文安首尾连接不间断滚动的方法。首先上一个运行效果截图:

FlashButton.h代码:

#if !defined(AFX_FLASHBUTTON_H__36D25335_C9F2_476B_BCA8_6B63E02DDD19__INCLUDED_)
#define AFX_FLASHBUTTON_H__36D25335_C9F2_476B_BCA8_6B63E02DDD19__INCLUDED_
 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// FlashButton.h : header file
//
#include <afxtempl.h>
/
// CFlashButton window
 
class CFlashButton : public CButton
{
// Construction
public:
    CFlashButton();
 
// Attributes
public:
    CStringArray m_arrStr;
    CFont m_font;//字体
    int m_yBlock2;//第2块绘制起始位置。
    int m_nLineHight;
    CRect m_rcLoc;//相对父控件窗口的位置。
    BOOL bContinue;//线程是否继续执行。
    CBitmap m_bmp;//背景
// Operations
public:
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CFlashButton)
    //}}AFX_VIRTUAL
 
// Implementation
public:
    virtual ~CFlashButton();
 
    // Generated message map functions
protected:
    //{{AFX_MSG(CFlashButton)
    afx_msg void OnPaint();
    afx_msg void OnParentNotify(UINT message, LPARAM lParam);
    afx_msg void OnClose();
    afx_msg void OnDestroy();
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg UINT OnGetDlgCode();
    //}}AFX_MSG
 
    DECLARE_MESSAGE_MAP()
};
 
 
UINT DoFlashButtonThread(LPVOID lParam);
/
 
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
 
#endif // !defined(AFX_FLASHBUTTON_H__36D25335_C9F2_476B_BCA8_6B63E02DDD19__INCLUDED_)

FlashButton.cpp代码:

// FlashButton.cpp : implementation file
//
 
#include "stdafx.h"
#include "ExMain.h"
#include "FlashButton.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 
/
// CFlashButton
 
CFlashButton::CFlashButton()
{
    m_arrStr.Add("花开若相惜,花落莫相离。");
    m_arrStr.Add("弄花香满衣,拂花叶凄凄。");
    m_arrStr.Add("醉言花间意,别情花如依。");
    m_arrStr.Add("纵君解花语,霜雪下花篱。");
    CString str=m_arrStr.GetAt(0);
    m_font.CreateFont(32,0,0,0,FW_BOLD,0,0,0,DEFAULT_CHARSET,0,0,0,0,"华文仿宋");
    m_bmp.LoadBitmap(IDB_BITMAP1);
    bContinue=TRUE;
}
 
CFlashButton::~CFlashButton()
{
}
 
 
BEGIN_MESSAGE_MAP(CFlashButton, CButton)
    //{{AFX_MSG_MAP(CFlashButton)
    ON_WM_PAINT()
    ON_WM_PARENTNOTIFY()
    ON_WM_CLOSE()
    ON_WM_DESTROY()
    ON_WM_LBUTTONUP()
    ON_WM_LBUTTONDOWN()
    ON_WM_GETDLGCODE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/
// CFlashButton message handlers
 
void CFlashButton::OnPaint()
{
    CPaintDC dc(this); // device context for painting
     
    // TODO: Add your message handler code here
    CBrush br;
    br.CreatePatternBrush(&m_bmp);
    CRect rc;
    GetClientRect(rc);
    dc.FillRect(rc,&br);
    // Do not call CButton::OnPaint() for painting messages
}
 
void CFlashButton::OnParentNotify(UINT message, LPARAM lParam)
{
    CWindowDC dc(this);
    CSize sizeRow;
    if (message=WM_USER+1&&lParam==0)
    {
        dc.SelectObject(m_font);
        GetWindowRect(m_rcLoc);
        GetParent()->ScreenToClient(m_rcLoc);
        sizeRow=dc.GetOutputTextExtent(m_arrStr[0]);
        m_nLineHight=sizeRow.cy;
        sizeRow.cy*=4;
        m_yBlock2=max(sizeRow.cy,m_rcLoc.Height());
        // TODO: Add your message handler code here
        AfxBeginThread(DoFlashButtonThread,this);
         
    }
    else
    {
        CButton::OnParentNotify(message, lParam);
    }
}
 
UINT DoFlashButtonThread(LPVOID lParam)
{
    CWnd *p=NULL;//父控件窗口
    CBrush br;
    CRect rc;//父窗口控件大小。
    CFlashButton *t=(CFlashButton*)lParam;//本控件
    int yBlock1Begin=0,yBlock2Begin=0,i=0;
     
    p=t->GetParent();
    p->GetClientRect(rc);
    br.CreatePatternBrush(&t->m_bmp);
    yBlock2Begin=t->m_yBlock2;
 
    while (t->bContinue)
    {
        CWindowDC dc(t);
        //CDC *dcMem->=new CDC;//执行构造函数
        //CDC *dcMem->=(CDC *)calloc(sizeof(CDC),1);//不执行构造函数。
        //设定背景
        CDC dcMem;
        dcMem.CreateCompatibleDC(p->GetDC());
        dcMem.SelectObject(t->m_bmp);
        dcMem.FillRect(rc,&br);
 
        dcMem.SetBkMode(TRANSPARENT);
        dcMem.SetViewportOrg(t->m_rcLoc.left,t->m_rcLoc.top);
        dcMem.SelectObject(t->m_font);
 
        //计算绘画位置
        yBlock1Begin--;
        yBlock2Begin--;
        if (yBlock1Begin<-t->m_yBlock2)
        {
            yBlock1Begin=0;
            yBlock2Begin=t->m_yBlock2;
        }
        //绘制文字
        for (i=0;i<4;i++)
        {
            dcMem.TextOut(0,yBlock1Begin+i*t->m_nLineHight,t->m_arrStr[i]);
            dcMem.TextOut(0,yBlock2Begin+i*t->m_nLineHight,t->m_arrStr[i]);
        }
        //设定输出
        dc.BitBlt(0,0,t->m_rcLoc.Width(),t->m_rcLoc.Height(),&dcMem,0,0,SRCCOPY);
        Sleep(100);
    }
     
    return 0;
}
 
void CFlashButton::OnClose()
{
    // TODO: Add your message handler code here and/or call default
    bContinue=FALSE;
    CButton::OnClose();
}
 
void CFlashButton::OnDestroy()
{
    bContinue=FALSE;
    CButton::OnDestroy();
     
    // TODO: Add your message handler code here
     
}
 
void CFlashButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
     
    CButton::OnLButtonUp(nFlags, point);
    Invalidate();
}
 
void CFlashButton::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
     
    CButton::OnLButtonDown(nFlags, point);
    Invalidate();
}
 
UINT CFlashButton::OnGetDlgCode()
{
    // TODO: Add your message handler code here and/or call default
     
    int n= CButton::OnGetDlgCode();
    Invalidate();
    return n;
}

注释算是写得比较详细吧,相信诸位看了注释之后应该能明白。当然,您也可以使用相同的方法去重载一个CStatic类去实现。方法很多啦。

本示例解决闪屏的方法是首先把要显示的界面在内存里画出来。画完了之后一次输出到显存,成功避免了多次修改显存造成的闪屏的问题。

转载自原文链接, 如需删除请联系管理员。

原文链接:一个双缓冲原理的解释:Flash按钮,转载请注明来源!

0