65.9K
CodeProject 正在变化。 阅读更多。
Home

滚动时固定背景

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.53/5 (8投票s)

2008年10月9日

CPOL

2分钟阅读

viewsIcon

35077

downloadIcon

1182

在 MFC 中滚动文本时固定背景图像

引言

本文档解释了如何在 VC++ 6.0 中在固定图像背景上滚动文本。 我在互联网上搜索过,但找不到任何简单的文章来介绍这个主题。 因此,我开始尝试,最终找到了解决方案。 我只在 WinXP 上测试过这个程序。

虽然本文档的主要目的是在固定背景上显示滚动文本,但它也涵盖了如何使用位图画笔绘制背景。

创建一个 MFC 文档/视图项目

创建一个 MFC 文档/视图项目,并选择 CScrollView 作为基础视图类。 我们选择 CScrollView 作为视图类的基础,因为它处理所有的滚动操作。 现在添加一个位图资源,作为窗口背景。 现在创建一个 CBitmap 变量,在你的框架窗口类中加载你的位图资源。

class CMainFrame : public CFrameWnd
{
	protected: // create from serialization only
	CMainFrame();
	DECLARE_DYNCREATE(CMainFrame)

	.
	.
	.
	CBitmap m_bmBG;

PreCreateWindow() 虚拟函数中,更改扩展样式如下

cs.dwExStyle |= WS_EX_COMPOSITED;

WS_EX_COMPOSITED 是一个 Windows 扩展样式,MSDN 称该样式使用双缓冲以自底向上绘制顺序绘制窗口及其所有后代窗口。 它将满足我们的目的。 在 OnCreate() 处理程序函数中,加载我们的位图。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	.
	.	
	m_bmBG.LoadBitmap(IDB_BITMAP1);
	return 0;
}

添加 WM_ERASEBKGND Windows 消息处理程序。 在这里,我们将从我们的位图创建模式画笔,并将其选择到设备上下文中,然后填充客户端区域。 代码如下所示

BOOL CMainFrame::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	CBrush hbr,*phbrOld;
	CRect rect;

	hbr.CreatePatternBrush(&m_bmBG);
	phbrOld= pDC->SelectObject(&hbr);
	GetClientRect(&rect);
	pDC->FillRect(&rect,&hbr);
	
	pDC->SelectObject(phbrOld);
	hbr.DeleteObject();
	
	return TRUE;	
}

不要忘记在 Mainfrm.h 中添加以下行

#define WS_EX_COMPOSITED 0x02000000L

在视图类中处理 WM_CREATE 消息,并在处理程序中添加以下代码

int CTransscrollView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CScrollView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	CClientDC dc(this);
	m_ftTimes.CreatePointFont(500,"Times New Roman",&dc);
	
	CFont *pOldFont;
	pOldFont = dc.SelectObject(&m_ftTimes);

	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);
	m_nLineHt = tm.tmHeight + tm.tmExternalLeading;

	dc.SelectObject(pOldFont);
	return 0;
}

我们创建了 50 点 Times New Roman 字体,并将其选择到我们的客户端 dc 中。 计算行高并存储它。 不要忘记创建 CFont m_ftTimesint m_nLineHt 类变量。 现在处理 WM_ERASEBKGND 消息。 只是在消息处理程序中返回 TRUE。 更改 OnInitialUpdate() 函数,更改代码。

void CTransscrollView::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();

	CSize sizeTotal;
	// TODO: calculate the total size of this view
	sizeTotal.cx = 500;
	sizeTotal.cy = 25 * m_nLineHt;
	SetScrollSizes(MM_TEXT, sizeTotal);	
}

我们将显示 25 行。 我们正在创建一个足够大的视图来显示这些行。

OnDraw() 中,我们将只绘制在滚动时可见的那些行。 最初,所有行都将被绘制出来。

void CTransscrollView::OnDraw(CDC* pDC)
{
	CTransscrollDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	CFont *pOldFont;
	
	int ct;

	pDC->SetBkMode(TRANSPARENT);
	
	int start = GetDeviceScrollPosition().y /m_nLineHt -1;
	if (start < 0) start =0;

	CRect rcClient;

	GetClientRect(&rcClient);

	ct = start + rcClient.Height()/m_nLineHt + 3;

	if( ct > 25) ct=25;
	
	pOldFont = pDC->SelectObject(&m_ftTimes);
	
	pDC->SetTextColor(RGB(255,12,146));
	
	for(int i=start;i<ct;i++)
	{
		CString s;
		s.Format("I am line %d on a fixed background",i+1);
		pDC->TextOut(0,i * m_nLineHt,s);
	}
	
	pDC->SelectObject(pOldFont);
}

正如我们所知,在滚动时,ScrollWindow() 会滚动窗口内容,我们需要绘制只有那些变得可见的行。 因此,我们计算了起始行号和将要可见的结束行。 我们只绘制了那些行。 请注意,最初所有行都将被绘制出来。

享受。

历史

  • 2008年10月9日:初始发布
© . All rights reserved.