4:
程序中画线首先要有两个点,那就是先要捕获两个点;windows是基于消息的编程,鼠标左键按下去获取一个点(WM_LBUTTONDOWN获取消息)拖动鼠标鼠标左键弹起来获取另外一个点(WM_LBUTTONUP获取消息)
在窗口类(CMainFrame中对鼠标左键按下去和弹起进行消息响应),由于View类是覆盖在CMainFrame框架类窗口之上的,就像框架类是一堵墙,它的前面还挡着一堵墙就是View类,所以对窗口空白区域任何操作都是对View类的操作,包括鼠标移动鼠标点击都是对View类的操作,只有View类能捕获的到。
afx_msg是一个宏,这个宏表示函数原型是一个消息响应函数原型的声明。
当增加一个消息响应函数,在三个地方都修改了代码,头文件在DECLARE_MESSAGE_MAP()声明消息映射之前在两个注释宏之间加入了消息响应函数原型的声明;在源文件当中在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP()之间里面的也是注释宏之间加入了一个消息响应函数的一个宏ON_WM_LBUTTONDOWN(),通过这个宏把消息和消息响应函数关联起来了,一旦有这样一个消息产生就会去调用我们的和它关联的消息响应函数进行处理。
在Mfc当中采用的是消息映射,一种是在基类当中针对每一种消息做一个虚函数,当子类如果需要对这个消息进行响应只需要重写这个虚函数就可以了,当调用这个函数的时候,根据多态性的原理,子类有的调用子类的,子类没有的调用父类的,也可以完成消息的路由最终到一个函数。
在Mfc中没有采用这种方法,消息产生之后,这个消息是和一个具体的窗口相关的,在Mfc当中维护了一个句柄和C++类指针的映射,这样的话通过这个句柄就可以找到相对应的C++类对象的指针,有了指针之后,把这个指针传递给基类,在基类当中去调用WindowProc(在SRC目录下的WINCORE.cpp中LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)这个函数)这个函数进行处理,在WindowProc当中是调用OnWndMsg这个函数进行处理,在OnWndMsg里去判断根据你的消息种类去查找你的消息映射,查找消息映射一个是通过头文件当中的消息响应函数的原型声明,另外一个是源文件当中的消息映射最终找到了我们的消息响应函数,由这个消息响应函数对我们的消息进行响应。
要画线,首先需要获取一个DC的句柄一种方式应用系统函数的GetDC函数:
HDC hdc;
hdc=::GetDC(m_hWnd); //调用系统函数获取DC句柄
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);
LineTo(hdc,point.x,point.y);
::ReleaseDC(m_hWnd,hdc); //释放DC句柄
另外一种是调用一个类叫CDC的GetDC函数,它是把这个DC句柄封装成它的一个数据成员,然后在调用的时候就不用定义DC句柄并且传递DC句柄,下面这三个函数都是它的类成员函数:
CDC *pDC=GetDC();
pDC->MoveTo(m_ptOrigin); //移动到起始点
pDC->LineTo(point); //画线到终点
ReleaseDC(pDC); //释放DC对象
还有一种是调用一个类叫CClientDC,它是继承CDC类而来的,它的构造函数就有GetDC来获取一个DC句柄,并且这个句柄是它的数据成员,并且它在析构的时候会自动调用ReleaseDC来析构这个DC句柄:
CClientDC dc(this); //它的构造函数需要一个CWnd指针传递进去
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
同样的还有一种是调用一个类叫CWindowDC,它也在构造函数中调用了GetDC在析构函数中调用了ReleaseDC,与CClientDC的区别是可以在客户区也可在非客户区进行操作(画线)。
改变画笔样式:
CPen pen(PS_SOLID,1,RGB(255,0,0)); //设计一种画笔,实线、宽度1,颜色是红色
CClientDC dc(this);
CPen *pOldPen=dc.SelectObject(&pen); //把设计好的画笔选进来,并且保存原来的画笔样式pOldPen(被替换的是返回值)
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen); //画完线把原来的画笔样式选择回去
要知后事如何,请见下回分晓