孙鑫《vc ++深入详解》第四章简单绘图

来源:互联网 发布:黑道圣徒捏脸数据下载 编辑:程序博客网 时间:2024/05/16 10:51

1.MFC消息映射机制的具体实现方法:

在每个能接收和处理消息的类中,定义一个消息和消息函数静态对照表,即消息映射表。在消息映射表中,消息与对应的消息处理函数指针是成对出现的。某个类能处理的所有消息及其对应的消息函数的地址都列在这个类所对应的静态表中。当有消息需要处理时,程序只要搜索该消息静态表,查看表中是否含有该消息,就能知道该类能否处理此消息,如果能处理该消息,则同样依照静态表能很容易找到并调用对应的消息处理函数。

 

消息映射机制实际实现过程:

MFC在后台维护里一个窗口句柄与对应的c++对象指针的对照表。当收到某一消息时,小姨的第一参数就指明了该消息与哪个窗口句柄相关,通过对照表,就可以找到与之相关的C++对象指针,然后把这个指针传递给应用程序框架窗口类的基类,后者会调用一个名为WindowProc的函数。该函数的定义位于WinCore.cpp文件中:

 

LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

     // OnWndMsg does most of the work, except for DefWindowProc call

     LRESULT lResult = 0;

     if (!OnWndMsg(message, wParam, lParam, &lResult))

         lResult = DefWindowProc(message, wParam, lParam);

     return lResult;

} 根据这个WindowProc函数的定义我们可发现他是个虚函数,同时可以发现在内部调用了一个OnWndMsg函数,真正的消息路由,也就是消息映射就是由此函数完成的。OnWndMsg函数定义也位于WinCore.cpp文件中:

 

BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)

{

     LRESULT lResult = 0;

 

     // special case for commands

     if (message == WM_COMMAND)

     {

         if (OnCommand(wParam, lParam))

         {

              lResult = 1;

              goto LReturnTrue;

         }

         return FALSE;

     }

 

     // special case for notifies

     if (message == WM_NOTIFY)

     {

         NMHDR* pNMHDR = (NMHDR*)lParam;

         if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))

              goto LReturnTrue;

         return FALSE;

     }

 

     // special case for activation

     if (message == WM_ACTIVATE)

         _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));

 

     // special case for set cursor HTERROR

     if (message == WM_SETCURSOR &&

         _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))

     {

         lResult = 1;

          goto LReturnTrue;

     }

     ……………………………….

     return TRUE;

}

OnWndMsg函数的处理过程是:

首先判断消息是否消息响应函数。

判断方法是在相应窗口类中查找所需的消息响应函数。因为传递给windowproc函数的是窗口子类指针,所以OnWndMsg函数回到相应的子类头文件中查找,看看DECLARE_MESSAGE_MAP()宏之上,两个AFX_MSG注释宏之间是否有相应的消息响应函数声明;再到子类的源文件中,看看BEGIN_MESSAGE_MAPEND_MESSAGE_MAP()两个宏之间是否有相应的消息映射宏。

如果通过上述步骤,找到了消息响应函数,那么接着就会调用该响应函数,对消息进行处理。

如果在子类中没有找到消息响应函数,那么就交由基类进行处理。

通过以上步骤,MFC就实现了具体的消息映射,从而完成对消息的相应。

二,绘制线条
1
,利用SDK全局函数实现:
获得设备描述表::getDCm_hWnd),移动到线条起点MoveToEx(),画线LineTo(),释放设备描述表::ReleaseDC(m_hWnd,hdc)
2
,利用MFCCDC类实现:【该类封装了所有与绘图相关的操作,提供成员m_hDC保存DC句柄】
pDC->
要用“->”而不是“.”,因为其为指针???yyy
3
,利用MFCCClientDC类实现:【派生于CDC类,不需显式地释放资源】
dc
不用“->”而是“.”,因为其是类。还有GetParent()函数。可以划到视类窗口和工具栏
【响应函数在视类中,怎么能响应框架类中的左键点击消息???】
4
,利用MFCCWindowDC类实现:【派生于CDC类,不需显式地释放资源,用GetParent()函数可以划到视类窗口和工具栏,标题栏,菜单栏】用GetDesktopWindow()函数还可以在桌面画线。
【后两个函数怎么划的线不是真正的鼠标控制的位置???】
5
,彩色线条
CPen
类。
构造GDI对象,用SelectObject函数选入设备表。该函数返回原来的画笔指针。

三,画刷绘图
1
,简单画刷CBrush
2
,位图画刷
3
,透明画刷用GetStockObject函数获得透明画刷句柄,由句柄转为透明画刷对象。转化函数FromHandle
CBrush::FromHandle()CBrush.FromHandle()的区别???】
//
静态成员函数和静态成员变量,可以用类::函数名的形式直接调用,而无需先定义一个该类的对象!!!【因为静态……属于类本身,在类加载时即为他们分配了空间,所以可以如前所说的来访问,而非静态……属于对象,故必须先对象化后引用。】

四,绘连续线条
WM_MOUSEMOVE
的响应函数OnMouseMove
五,绘扇形效果的线条
SetROP2
函数。

 

原创粉丝点击