开始学习VC++MFC程序了!了解了一些如何在窗口上面绘画的功能,突然联想到平时在使用一些绘图软件或其它涉及到画线的程序的一个小功能:需要画一条直线时,总是在鼠标左键按下时,开始画线;鼠标拖动时,始终显示鼠标左键按下时的起点与鼠标最新位置之间的连线。这样,使用者可以清楚地看到自己准备要画的线的位置,直到连线刚好是自己想要的位置时,鼠标左键释放,连线完成。
我想这个功能还是比较容易实现的,唯一的难点在于如何擦除鼠标拖动时之前绘制的连线,只保留最后的连线即可。至于如何找到之前连线的位置(起点与终点),这个非常容易:增加一个变量,在鼠标移动时用它始终保存鼠标当前位置即可。
步骤:
1、设置三个私有变量(在要绘画的窗口类中添加)
private:
CPoint m_originCPoint;//保存鼠标左键按下时的鼠标位置
CPoint m_preCPoint;//保存鼠标拖动(即鼠标左键按下并移动)时的位置并不断更新。
bool MouseDownFlag;//鼠标左键按下的标志。
2、初始化变量:
在要绘画的窗口类的构造函数中初始化变量:
m_originCPoint.x =m_originCPoint.y= 0;
m_preCPoint.x = m_preCPoint.y = 0;
MouseDownFlag = false;
3、建立鼠标左键按下消息处理函数,并添加以下代码:
void CfirstMAppView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_originCPoint =m_preCPoint= point;//把鼠标左键按下时的位置赋给两个变量
MouseDownFlag = true;//更新鼠标按下标志
CView::OnLButtonDown(nFlags, point);
}
4、添加鼠标左键释放消息处理函数,并添加如下代码:
void CfirstMAppView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
MouseDownFlag = false;//恢复标志为鼠标释放状态
CView::OnLButtonUp(nFlags, point);
}
5、添加鼠标移动消息处理函数,并添加以下代码:
void CfirstMAppView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (MouseDownFlag) {
//获取DC
CClientDC dc(this);
//设置画笔及其参数(线型,宽度,颜色)
CPen pen(PS_SOLID, 1, RGB(255, 0, 0));
CPen *oldpen=dc.SelectObject(&pen);
//改变画图模式并在该模式下把之前已经画的线重新画一遍,实现“擦除”的效果。
//此处应为R2_NOT,原文为R2_MERGEPENNOT是错误的!
int oldmode=SetROP2(dc, R2_NOT);
dc.MoveTo(m_originCPoint);
dc.LineTo(m_preCPoint);
//恢复原来的模式
SetROP2(dc,oldmode);
————————————————————————————————————————
//经检查,下面这样画线是有问题的:这是在MouseMove状态下,不应该把非屏幕颜色画线。
//因为一旦屏幕颜色与窗口背景色(不一定是窗口预定的画刷颜色)不一致的话,它的反色就
//不是屏幕背景色了,是别外一个颜色。
//解决方法:在MouseMove状态,始终用屏幕的反色画线。最终显示的线应该放在MouseUp
//状态下按照指定的画笔颜色画线就可以了。研究以下图片主明白了:
//上面图片中的画线才是正确的。把鼠标移动时的画线与最终线要分开。移动时的画线始终用屏幕颜色的反色来画线,最终线根据程序的需要自己设定。
//在正常的模式下,画出当前鼠标位置与初始点(鼠标左键按下的位置)之间的连线
dc.MoveTo(m_originCPoint);
dc.LineTo(point);
//恢复画笔
dc.SelectObject(oldpen);
//更新前一个点的位置为当前鼠标位置
m_preCPoint = point;
——————————————————————————————————————————
}
CView::OnMouseMove(nFlags, point);
}