夏天/isummer

Sun of my life !Talk is cheap, Show me the code! 追风赶月莫停留,平芜尽处是春山~

博客园 首页 新随笔 联系 管理

  Window消息可以分为三类:(1)标准Window消息(CWnd子类处理)(2)控制通知消息(CWnd子类处理),(3)命令消息(应用中的5类都可以)。所有派生自CCmdObjec对象的类都可以处理Windows消息。

  (1)前缀以“WM_  ”开头,但是WM_COMMAND消息除外。如窗口重回WM_PAINT,WM_QUIT  (2)WM_COMMAND消息,窗口上的各种空间发出的消息  (3)WM_COMMAND消息,只是指控制界面发出的消息,如菜单项与工具栏的按钮操作。MFC为“标准菜单”“工具栏”提供为独特的唯一表示符ID。

  Windows消息与程序进行交互,MFC提供了消息的大部分处理流程,只需要程序猿完成与特定消息、特定环节、特定位置、特定时间处理的方法实现。在FMC中各类的消息处理必然都是一个类的成员函数。MFC中为每个接受Window消息处理的类中都定义了“消息映射函数”,完成将Window消息与特定的消息成员处理函数相关的声明,当特定消息出现时候,就调用响应的成员处理函数。并且消息的处理函数用afx_msg标识与普通函数进行区别,此预定义为空,仅仅作为标识作用。

// Type modifier for message handlers
#ifndef afx_msg
#define afx_msg         // intentional placeholder
#endif

  类的定义文件:

// TextEditorDoc.cpp 

IMPLEMENT_DYNCREATE(CTextEditorDoc, CDocument) //声明中第一个参数是消息映射函数的类, 第二个参数是其基累
BEGIN_MESSAGE_MAP(CTextEditorDoc, CDocument) ON_COMMAND(ID_N_ITEM1,
&CTextEditorDoc::OnNItem1) END_MESSAGE_MAP()

  类的声明文件:如果函授此声明的.h文件中有次DECLARE_MESSAGE_MAP()声明,则其CPP文件中,就要有BEGIN_MESSAGE_MAP(CTextEditorDoc, CDocument)END_MESSAGE_MAP()的定义。

// 生成的消息映射函数
protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnNItem1();

  Window消息还带有其他的数据信息,用于对如同时WM_COMMAND消息的不同消息发送者的ID的信息区别不同的执行函数。不应该把一个消息映射给多个处理函数,因为MFC的消息处理机制第二个以及以后的所有处理消息都不回执行。

  Windows消息处理函授不能乱放。如标准Window消息,以及控制通知消息一般是CWnd派生类可以处理,而Doc类则明显不能处理。所有的标准Window消息MFC都提供了默认的消息处理,这样如果本消息处理或者自己处理,或者处理后继续传递给默认的消息处理。

  MFC定义处理Windows消息的(单文档应用程序)一般流程如下View -> Doc -> DocTemplate -> Fram -> App

  IDR_   一般表示窗口定义完整资源

      如(1)工具栏按钮图标ID标识前缀,(2)

  ID_   MFC约定此为菜单项的ID规范

  利用类向导添加类成员,注意:如果手动添加(0)变量的初始化放在构造函数中(1)如果实在堆中分配空间,在析构函数中进行释放

  对于菜单的特定条目会要处理两类消息:

  (1)COMMAND        :按下菜单项中触发的消息,消息响应函数完成对应的特定行为

  (2)UPDATE_COMMAND_UI  :取决于菜单的状态,如复选菜单,工具拦按钮等,在新菜单出现直线处理消息响应函数。

两类消息的映射形式:

BEGIN_MESSAGE_MAP(CTextEditorDoc, CDocument)
    ON_COMMAND(ID_N_ITEM1, &CTextEditorDoc::OnNItem1)
    ON_UPDATE_COMMAND_UI(ID_N_ITEM1, &CTextEditorDoc::OnUpdateNItem1)
END_MESSAGE_MAP()

 


 

   单文档中添加工具栏简单操作:

 

 


  窗口绘制经验,当外部事件调整窗口大小,绘制窗口颜色等,需要程序某部分需要发送WM_PAINT,window标准消息给应用程序,从而对响应的窗口进行重绘动作。

MFC收到WinOS消息队列中的WM_PAINT,后,通知WinOS去调用WinPro执行重绘的响应处理。

  WinOS默认为窗口定义本地坐标系,如下图所示,WinOS需要知道需要重绘的窗口ID的左上角在[屏幕]的位置。

  

  WindowOS使用图形定义界面GDI(Graphic,Device,Interface)抽象所有的图形输出硬件,实现程序与具体硬件的解耦。

  WindowOS使用设备上下文CDC,一种WindOS的数据结构,将该包含的信息通过GDI物理硬件上的具体动作。MFC的CDC类中封装了一个设备上下文,对该类对象的操作可以影响到最终响应的硬件。CWnd类的onDraw()通过调用设备上下文,就可以执行响应的绘制处理。通过更改设备上下文的属性可以操作具体的物理设上下文CDC的设备映射默认是以像素为单位距离计算,可以变换,所以具体的输出图形的效果与具体的硬件设备的DPI有关。MFC已经对一些细节进行了封装。

  MFC绘图的机制:

  继承Cwnd的派生类实现的onDraw(),每当窗口重新使,需要执行此函数,如View类。方法传入的是设备上下文指针。无论如何修改设备上下文的画笔,画刷,颜色扥个,函数的末尾都要讲画笔画刷等替换回来。

// CTextEditorView 绘制

void CTextEditorView::OnDraw(CDC* pDC)
{
    CTextEditorDoc* pDoc = GetDocument();//返回现有视图相关联的对象
    ASSERT_VALID(pDoc);//调试版本使用,确保参数有效。发布版本将被忽略。
    if (!pDoc)
        return;

    // TODO:  在此处为本机数据添加绘制代码
}

  由于鼠标的交互主要是View区域,所以一般鼠标的响应函数放在View中(视图类)。

  鼠标可能存在某个窗口在收到LbuttonUp之前,没有收到LbuttonDown,如按下后滑动到另一个控件View上。程序猿需要注意

   MFC支持只绘制部分区域的工作区。如果现实的比较复杂时,则可以接上大量的时间。通过调用CWnd成员的InvialdateRect(CRectangle,Bool)函数,对响应窗口的指定位置进行绘制。参数1需是需要在此Wnd类对应的窗口中从新绘制的区域,如果为0,则对此类的整个窗口进行绘制。参数2,True,擦除举行的背景,False,举行与背景的颜色进行重接显示,默认True擦除。InvilateDate()函数执行把需要重绘的区域传递给WinOs,然后维护者不同窗口发来的重绘无效的举行,形成一个包络矩形。最后WM_PAINT消息发送到响应的CWnd窗口对象是进行onDraw()重绘。而每个CWnd派生类都会通过UpdateWindow()而发送一个处理本窗口的WM_PAINT的消息。所以InvalidateRect()用法后,紧跟着一个UpdateWindow()这样是提高效率。

  

  CDocument::UpdateAllViews(三个参数),提供了一个文档将更新消息发送到所有视图。参数1:指向修改文档的视图,或 NULL,如果将更新所有视图。将会使document的所有相关的View调用其OnUpdate()函数。或者进行重载,进行参数传递。

  

  

posted on 2016-07-28 03:54  夏天/isummer  阅读(350)  评论(0编辑  收藏  举报