您的位置:首页 > 其它

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

2016-08-16 11:35 176 查看
转载请注明来源: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 按钮 双缓冲 GDI MFC