程序的主要功能:
(1)修改由向导生成的多文档窗口程序框架,使该程序能通过视类(View Class)与用户交互,也即响应鼠标输入。
(2)在文档窗口中绘制和显示线段。
(3)接收键盘字符输入并将其显示在文档窗口中。
一、在视图中响应鼠标输入与绘制线段
具体步骤如下:
1. 利用向导生成应用程序框架
2.为视类(例如CP2View)添加数据成员
(1)添加以下5个数据成员
CPoint m_ptStart;//画线的起点
CPoint m_ptOld; //画线的临时点
HCURSOR m_hCross;//十字鼠标句柄
HCURSOR m_hArrow;//标准型鼠标句柄
bool m_bMouseDown;//标识是否按下鼠标左键
(2)添加数据成员的操作
- 在Class View框中选择要添加成员的类;
- 单击鼠标右键,执行所弹出的快捷菜单中的“Add Member Varible”命令;
- 输入变量类型、名称以及访问权限(Public|Protected|Private);
- 单击“OK”按纽。
3.修改该类的构造函数(CP2View())
在构造函数中初始化所添加的数据成员。
修改后的代码如下:
CP2View::CP2View()
{
// TODO: add construction code here
m_bMouseDown=false;
m_hCross=AfxGetApp()->LoadStandardCursor(IDC_CROSS);
m_hArrow=AfxGetApp()->LoadStandardCursor(IDC_ARROW);
}
4.为视类添加鼠标动作响应函数
(1)针对以下三个鼠标消息添加对应的处理函数
OnLButtonDown():该函数与WM_LBUTTONDOWN消息有关,用来响应用户按下鼠标左键。
OnMouseMove():该函数与WM_MOUSEMOVE消息有关,用来响应用户移动鼠标。
OnLButtonUp():该函数与WM_LBUTTONUP消息有关,用来响应用户松开鼠标左键。
(2)选择“消息”和编辑成员函数代码的操作
- 打开“View”菜单,执行“ClassWizard”命令,弹出“MFC ClassWizard”对话框;
- 选择该对话框的“Message Maps”标签;
- 在“Project”框中选择要要执行添加操作的项目(本例为P2);
- 在“Class name”框中选择要执行添加操作的类(本例为CP2View);
- 在“object Ids”框中选择要要执行添加操作的类(本例为CP2View);
- 在“Messages”框中选择对应的消息(例如WM_LBUTTONDOWN);
- 单击“Add Function”按纽,为所选类添加成员函数(例如onLButtonDown(),该函数用来响应WM_LBUTTONDOWN消息)。
- 单击“Edit Code”按纽,进入对应函数的代码编辑处理。
(3)为视类所添加的三个函数的代码
void CP2View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_bMouseDown=true; //鼠标左键按下
m_ptStart=point //画线的起点
m_ptOld=point; //临时点
SetCapture();/ /将鼠标消息发送到视窗口
CRect rect; //声明客户区对象
GetClientRect(&rect); //得到客户区的大小
ClientToScreen(&rect); //将当前窗口坐标变换成屏幕坐标
ClipCursor(&rect); //将鼠标限定在其参数指定的范围内
SetCursor(m_hCross); //设置鼠标形状为十字形
CView::OnLButtonDown(nFlags, point);
}
void CP2View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (m_bMouseDown)
{
CClientDC dc(this);
dc.SetROP2(R2_NOT);
dc.MoveTo(m_ptStart);//这两行代码檫除从起点到上次
dc.LineTo(m_ptOld); //鼠标移动到的位置之间的临时线
dc.MoveTo(m_ptStart);//这两行代码从起点
dc.LineTo(point); //到鼠标当前位置画线
m_ptOld=point;//鼠标当前位置在下一次鼠标移动事件看来就是“老位置”
}
CView::OnMouseMove(nFlags, point);
}
void CP2View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (m_bMouseDown)
{
m_bMouseDown=false;
ReleaseCapture();
ClipCursor(NULL);
CClientDC dc(this);
dc.SetROP2(R2_NOT);
dc.MoveTo(m_ptStart);//这两行代码檫除从起点到上次
dc.LineTo(m_ptOld); //鼠标移动到的位置之间的临时线
dc.SetROP2(R2_COPYPEN);
dc.MoveTo(m_ptStart);//这两行代码从起点到鼠标
dc.LineTo(point);//当前位置之间画线
SetCursor(m_hArrow);//设置鼠标形状为标准箭头形
}
CView::OnLButtonUp(nFlags, point);
}
二、在视类中响应键盘输入与显示字符
1.为视类添加数据成员
添加以下2个数据成员:
CString m_strDisplay;//保存当前字符串的变量
int m_nLine;//记录已输入的字符行数
2.在构造函数:CP2View()中对数据成员初始化
仅须增加一行代码。
CP2View::CP2View()
{
// TODO: add construction code here
m_nLine=5;
m_bMouseDown=false;
m_hCross=AfxGetApp()->LoadStandardCursor(IDC_CROSS);
m_hArrow=AfxGetApp()->LoadStandardCursor(IDC_ARROW);
}
3.为视类添加键盘消息响应函数OnChar()
该函数与WM_CHAR消息有关,用来响应用户的键盘输入,当按下某个键时,该函数被调用,其第一个参数nChar是所按键的ASCII码。
(1)添加消息响应函数OnChar()的操作
参见1.4.2。
(2)OnChar()函数的代码
void CP2View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
if (nChar==VK_RETURN) //如果按下回车键
{
m_strDisplay.Empty();
m_nLine++;
}
else if(m_strDisplay.GetLength()<64) //当前字符数小于64
m_strDisplay+=nChar;
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
int nLineHeight=tm.tmHeight+tm.tmExternalLeading;
dc.TextOut(0,m_nLine *nLineHeight,m_strDisplay);
CView::OnChar(nChar, nRepCnt, nFlags);
}