添加左键按下鼠标消息处理的步骤:
1、Ctrl+W打开MFC ClassWizard对话框
2、在Message Maps选项卡中,在Class Name下拉列表中选择CMy2DCADView视图类,在Object Ids列表框中选择第一个列表项CMy2DCADView,双击WM_LBUTTONDOWN消息,就为树突类添加上了鼠标左键按下的消息处理函数OnLButtonDown了
3、单击MFC ClassWizard对话框中的Edit Code按钮,编辑OnLButtonDown函数如下:
void CMy2DCADView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
//在视图区中输出文本“鼠标左键按下”
dc.TextOut(100, 100, "鼠标左键按下");
CView::OnLButtonDown(nFlags, point);
}
注意:若想知道在按下鼠标左键的同时某个按钮是否被按下,可以用对应的常量标志与nFlags参数作按位逻辑“与”运算,所得结果若为非零值,则表示按钮被按下。如对于Shift按钮,可以在OnLButtonDown函数中添加下面的代码:
if(nFlags & MK_SHIFT)
{//检查在按下鼠标左键的同时,Shift键是否被按下
dc.TextOut(100, 50, "Shift键被按下");
}
用鼠标画点和画线以简单总结为以下4步:
1、分析交互过程
2、添加成员变量。注意成员变量需要初始化
3、使用ClassWizard向视图类中添加相应的鼠标消息处理函数
4、在函数中添加代码
画点:
画点是一步交互工程,只需要处理鼠标左键按下的消息WM_LBUTTONDOWN,并在消息处理函数里面添加相应的代码就可以了。需要注意的是,需要有一个变量来标志程序是否出于画点状态,前面已经添加了一个BOOL变量m_bIsPoint,因此无须重新添加,直接使用就可以了。
修改视图类的OnLButtonDown函数如下:
void CMy2DCADView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);//获取设备环境
////////////////////////////////////////////
//以下的代码在视图区中画点//
////////////////////////////////////////////
if(m_bIsPoint)//如果程序处于画点状态
{
//调用CDC::Ellipse函数以点为中心,画一个小的圆圈
dc.Ellipse(point.x-2, point.y-2, point.x+2, point.y+2);
}
CView::OnLButtonDown(nFlags, point);
}
注意:由于使用CDC::SetPixel函数画的点太小,只有一个象素大,不利于观察,因此使用CDC::Ellipse函数画一个小圆圈代替。若使用CDC::SetPixel函数,只需把dc.Ellipse(point.x-2, point.y-2, point.x+2, point.y+2);代码替换为dc.SetPixel(point, RGB(0,0,255));
画线:(两次单击鼠标左键的方式)
同画点类似,除了需要有一个标志画线状态的BOOL变量m_bIsLine以外,还需要一个操作步数变量来标志鼠标左键按下时定义的是线段的起点还是终点,如果是起点,则将该点坐标值记录下来,供后续操作中画线段用;如果是终点,就将线段画出。因此,还需要有两个变量来记录线段的起点X和Y坐标值。
具体步骤如下:
1、在Class View窗口中的CMy2DCADView上单击鼠标右键,选择Add Member Variable...项,添加两个记录线段起点坐标值的整型公有成员变量m_nStartX和m_nStartY,然后再添加一个记录画线段操作步数的整型公有成员变量m_nStep(第一步为起点,第二步为终点)。此时CMy2DCADView类的定义头文件中应该有如下的代码:
public:
int m_nStep;
int m_nStartY;
int m_nStartX;
2、在视图类的构造函数中为新增加的成员变量赋初始值,添加如下代码:
m_nStep = 0;//操作步数初始为0
m_nStartX = m_nStartY = 0;//坐标值初始也为0
3、在视图类的OnLButtonDown函数中添加具体的画线段代码。将下面的代码添加到画点代码后边:
////////////////////////////////////////////
//以下的代码在视图区中画线//
////////////////////////////////////////////
if(m_bIsLine)//如果程序处于画线状态
{
if(m_nStep == 0)//如果是线段起点,则记录起点坐标
{
m_nStartX = point.x;
m_nStartY = point.y;
m_nStep ++;//操作步数加1
}
else//如果是线段终点,则在视图区中画出线段
{
dc.MoveTo(m_nStartX, m_nStartY);
dc.LineTo(point.x, point.y);//使用MoveTo、LineTo函数画线
m_nStep = 0;//完成一次画线段后,将操作步数归零
m_nStartX = m_nStartY = 0;//将记录起点坐标归零
}
}
可以使用上鼠标捕捉,方法是,只需调用CWnd的成员函数SetCapture就可以捕捉鼠标。而调用全局函数ReleaseCapture函数来释放捕捉。
添加光标资源的步骤:
1、在ResourceView选项卡中的任何一个资源项上单击鼠标右键,选择Insert...菜单项,选择Cursor项中的第二项IDC_POINTER,然后单击对话框右边的New按钮
2、使用画图工具可以随意绘制修改光标形状
3、在光标的属性对话框中将资源语言类型选择为中文
4、可以通过Set Hotspot(设置热点)按钮来设置热点,即光标指针的实际位置
显示光标的步骤:
当光标在未被捕捉时从一个窗口移到另一个窗口,Windows向窗口发送WM_SETCURSOR消息。可以在该消息的处理函数OnSetCursor中加装并显示新的光标,改变光标的形状。
1、处理WM_SETCURSOR消息
使用ClassWizard为视图类CMy2DCADView添加WM_SETCURSOR消息的处理函数OnSetCursor
2、加载光标资源
在OnSetCursor函数中,(1)可以使用CWinApp::LoadCursor函数加装一个自定义光标,(2)或者使用CWinApp::LoadStandardCursor函数来加载一个系统预定义光标
3、设置光标
使用全局函数SetCursor可以为窗口设置一个新的光标
下面是OnSetCursor函数的代码:
BOOL CMy2DCADView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TODO: Add your message handler code here and/or call default
if(m_bIsPoint)
{//如果处于画点状态,就使用自定义的IDC_POINTER光标
HCURSOR hCursor;
hCursor = AfxGetApp()->LoadCursor(IDC_POINTER);//加载自定义光标
SetCursor(hCursor);
return TRUE;//直接返回,不再调用CView::OnSetCursor
}
if(m_bIsLine)
{//如果处于画线状态,就使用Windows系统的IDC_CROSS十字光标
HCURSOR hCursor;
hCursor = AfxGetApp()->LoadStandardCursor(IDC_CROSS);//加载系统预定义光标
SetCursor(hCursor);//设置光标
return TRUE;
}
//其他情况下,由基类的OnSetCursor函数来设置默认光标形状
return CView::OnSetCursor(pWnd, nHitTest, message);
}
键盘消息的应用实例:
为程序添加上Esc键的处理,并添加相应的代码来取消绘图功能,具体步骤如下:
1、使用ClassWizard为视图类CMy2DCADView添加WM_KEYDOWN消息的处理函数OnKeyDown
2、在编辑窗口中修改OnKeyDown函数如下:
void CMy2DCADView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
//如果按下Esc键,则终止所有的绘图工作
if(nChar == VK_ESCAPE)
{
//清除掉画点和画线状态
m_bIsPoint = FALSE;
m_bIsLine = FALSE;
//将一些成员变量恢复初始值
m_nStep = 0;//操作步数归零
m_nStartX = m_nStartY = 0;//记录起点坐标归零
::ReleaseCapture();//释放鼠标捕捉
}
//将消息交给基类的OnKeyDown函数处理
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}