孙鑫VC++深入详解:Lesson5 Part4 屏幕字符串滚动输出,DrawText,SetTimer,WM_Timer消息


滚动字母,修改输出字幕颜色,定时器

在onCreate中添加一个定时器,即SetTimer(1,100,NULL)
再在类CDrawView中添加消息WM_TIMER的响应函数OnTimer
每间隔100毫秒调用OnTime()
在OnTime()中用DrawText输出字符串,DrawText的输出矩形宽度每次按照5像素宽度增加,
随着矩形宽度增加,那么显示出来的字符串就逐步增加,效果看起来就是滚动输出.

dc.DrawText(cs,rect,DT_LEFT); 

//文本左对齐,就是字符串cs的左边的字符是对齐的,字符串右边的字符不断滚动出来,左边固定不动,字幕向右边扩展,逐步显示出字符串右边的字符.

dc.DrawText(cs,rect,DT_RIGHT); 
//文本右对齐,就是字符串cs的右边的字符是对齐的,整体字符是从左向右边整体移动,字符串左边的字符不断滚动出来,



GetTextMetrics:这是获得设备环境Device Context中当前的字体信息

GetTextExtent:这是获得显示在屏幕中的字符串的宽度和高度



1. DrawText用法:
CDC::DrawText   2个重载函数

即使字符串的宽度大于设定的矩形宽度,只输出矩形中的字符串,

virtual int DrawText( LPCTSTR lpszString, int nCount, LPRECT lpRect, UINT nFormat );
int DrawText( const CString& str, LPRECT lpRect, UINT nFormat );


2. SetTime用法:
CWnd::SetTimer
UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );

Return Value
The timer identifier of the new timer if the function is successful. An application passes this value to the KillTimer member function to kill the timer. Nonzero if successful; otherwise 0.

Parameters

nIDEvent: Specifies a nonzero timer identifier.设定定时器ID,这个ID会作为返回值

nElapse: Specifies the time-out value, in milliseconds.间隔时间,毫秒
lpfnTimer:
     指定一个处理WM_TIME消息的回调函数的名称,用自己编写回调函数处理TIMER消息
     填NULL则是交给Cwnd处理WM_TIMER消息,CWnd对象会把消息放入到应用程序的消息列队中

Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application’s message queue and handled by the CWnd object.


//


// TextView.cpp : implementation of the CTextView class
//

#include "stdafx.h"
#include "Text.h"

#include "TextDoc.h"
#include "TextView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTextView

IMPLEMENT_DYNCREATE(CTextView, CView)

BEGIN_MESSAGE_MAP(CTextView, CView)
	//{{AFX_MSG_MAP(CTextView)
	ON_WM_CREATE()   //在 Message map tables for Windows messages消息映射表中定义的宏,调用OnCreate函数
	ON_WM_CHAR()
	ON_WM_LBUTTONDOWN()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTextView construction/destruction

CTextView::CTextView()
{
	// TODO: add construction code here
	m_strLine ="";
	m_ptOrigin =0;
	m_nTimerID = 0;
	m_nWidth =0;

}

CTextView::~CTextView()
{
}

BOOL CTextView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CTextView drawing

void CTextView::OnDraw(CDC* pDC) // 这个函数传入了一个device context指针,因为在客户区画图不用在定义一个DC了.
{
	CTextDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	//------窗口重绘,在窗口输出一句话,直接用pDC对象的成员函数  
    CString cstr("这是一个CString类对象,对象名是cstr");  
    pDC->TextOut(0,0,cstr); 

  
//------CString类的成员函数LoadString(UINT nID), 用来加载字符串类资源(Insert-->Resource-->String table)  
       cstr.LoadString(IDS_STRING61446);  
       pDC->TextOut(0,50,cstr);  
	
//------路径层 CDC::BeginPath, EndPath
	 // CString cstr;
	   cstr="路径层";
	   pDC->TextOut(150,150,cstr);	 //把cstr输出在(150,150)这个点是将要创建的路径层的中心	  
	   pDC->BeginPath();
	   pDC->Rectangle(100,100,200,200);//在路径层上绘制一个矩形:就是字符串cstr的所占的区域
	   pDC->EndPath();  // 如果不取消则下面画的横竖线就看不见,因为还是在路径层上
	   pDC->SelectClipPath(RGN_DIFF);//把路径层的绘图与Device Context中的绘图区域进行 OR,XOR,COPY,AND,DIFF运算,产生了新的绘图区

	   //下面的横竖线就是在新的绘图区上绘制,	  
	   for(int i=0;i<300;i+=10)
	   {
		   //画横线
		   pDC->MoveTo(0,i);
		   pDC->LineTo(300,i);
		   //画竖线
		   pDC->MoveTo(i,0);
		   pDC->LineTo(i,300);	   
	   }  
}

/////////////////////////////////////////////////////////////////////////////
// CTextView printing

BOOL CTextView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CTextView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CTextView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CTextView diagnostics

#ifdef _DEBUG
void CTextView::AssertValid() const
{
	CView::AssertValid();
}

void CTextView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CTextDoc* CTextView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTextDoc)));
	return (CTextDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTextView message handlers

int CTextView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	// GetSystemMetrics 


//------创建文本插入符
	/*
	CClientDC dc(this);
	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);
	CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
	ShowCaret();
	*/



//------创建图形插入符
	/*
	  1. 创建一个位图对象CBitmap bitmap,且应作为全局的成员存在,因此把这个对象作为CTextView类的一个私有成员.
	  2. CreateCare()函数来创建一个插入符
	  3. 发现运行后闪烁的位图背景色和前景色均不是我设计的那个颜色,奇怪了...
	 */

//	CBitmap bitmap; 放在这里没有用,OnCreate消息处理完函数返回(return 0)后,这个临时bitmap资源类对象发生了析构,内存中没有了.
    /*
	bitmap.LoadBitmap(IDB_BITMAP1);
	CClientDC dc(this);
	CreateCaret(&bitmap);
	ShowCaret();
	*/

//------ 放置一个Timer,设ID为1,也就是返回值是1,即m_nTimerID =1 
	m_nTimerID = SetTimer(1,100,NULL);

	

//---
	return 0;
}

void CTextView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	
	CClientDC dc(this);
	CFont font;
	font.CreatePointFont(300,"华文行楷",NULL); //初始化字体
	CFont *poldfont =  dc.SelectObject(&font); //把字体选入设备环境中,并保存就的字体以备恢复.

    TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);

	if(0x0d==nChar) //如果是回车键
	{
		m_strLine.Empty(); //回车换行了,清空字符串
		m_ptOrigin.x = 0;  //回车换行,回到客户区左边
		m_ptOrigin.y +=tm.tmHeight;		
	}
	else if(0x08==nChar) //如果是退格键
	{
		COLORREF clr = dc.SetTextColor(GetBkColor(dc));//把文本颜色设置为背景色,返回原来文本颜色保存起来
		dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);//原地把文本重新输出,同为背景色,我们看不见文本了.
		m_strLine = m_strLine.Left(m_strLine.GetLength()-1);
        dc.SetTextColor(clr); // 改回原来文本的颜色
		//dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);		
	}
	else
	{
			m_strLine +=nChar;
	}
      
		dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine); //输出整个字符串

        
		// 横向输出字符时,插入符要跟着变化,依照字符串的宽度来变化
		// 获取字符串宽度
		CSize sz = dc.GetTextExtent(m_strLine);
		CPoint pt;
		pt.x = m_ptOrigin.x + sz.cx;
		pt.y = m_ptOrigin.y;
		SetCaretPos(pt); //重置插入符的位置为字符串的末尾
		
		
		dc.SelectObject(poldfont); //回复旧的字体

	CView::OnChar(nChar, nRepCnt, nFlags);
}

void CTextView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	SetCaretPos(point);
	m_strLine.Empty();
	m_ptOrigin =point;
	
	CView::OnLButtonDown(nFlags, point);
}

void CTextView::OnTimer(UINT nIDEvent) //nIDEvent就是定时器ID
{
	// TODO: Add your message handler code here and/or call default

   if(nIDEvent!=m_nTimerID) return;

	m_nWidth += 5; //  矩形宽度按照5个像素递增
	CClientDC dc(this);
	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm); //获得设备环境的文本信息,如字体信息

	CRect rect; 
	rect.left =0;
	rect.top =250;
	rect.right = m_nWidth;
	rect.bottom =rect.top + tm.tmHeight;
	
	
    CString cs;

	  cs = "字母变色,滚动字幕,Timer用法示范";

	dc.SetTextColor(RGB(255,0,0));
	dc.DrawText(cs,rect,DT_LEFT); //文本左对齐

    dc.SetTextColor(RGB(0,0,255));
	rect.top =220;
	dc.DrawText(cs,rect,DT_RIGHT); //文本右对齐

    CSize sz =dc.GetTextExtent(cs);//字符串在屏幕上显示的宽度和高度

	if(m_nWidth>sz.cx) //当矩形宽度大于字符串宽度时,字符串已经完整的输出了.
	{
		m_nWidth =0;  // 这样右对齐的情况下,左边又开始从零增长
		dc.SetTextColor(RGB(0,255,0));//用绿色输出
		dc.TextOut(0,250,cs); //注意是TextOut直接在点(0,250)处输出字符串cs
	}


//---	
	CView::OnTimer(nIDEvent);
}

---//

---//孙鑫VC++深入详解:Lesson5 Part4 屏幕字符串滚动输出,DrawText,SetTimer,WM_Timer消息_第1张图片

你可能感兴趣的:(孙鑫VC++深入详解:Lesson5 Part4 屏幕字符串滚动输出,DrawText,SetTimer,WM_Timer消息)