问题如下:
    当我在一个MDI程序的子窗体上(1)点击一下鼠标左键  或(2)在此窗体的文件框中输入2个文字    问题如下:
    (1)前者中的CLICK事件由谁来检测到,又由谁来生成这个CLICK消息,消息从何处产生,依次传往何处。
   
    (2)后者中的CHANG事件由谁来检测到,又由谁来生成这个CHANG消息,消息从何处产生,依次传往何处。 

解决方案 »

  1.   

    看下毛德操的windows源码分析里面有讲消息的传递处理
      

  2.   

    公共控件是当控件中发生事件(如用户输入)时,将通知消息发送到父窗口的子窗口。应用程序依赖于这些通知消息确定用户希望它采取的操作。大多数公共控件以 WM_NOTIFY 消息的形式发送通知消息。Windows 控件以 WM_COMMAND 消息的形式发送大部分通知消息。CWnd::OnNotify 是 WM_NOTIFY 消息的处理程序。与 CWnd::OnCommand 一样,OnNotify 的实现将通知消息调度到 OnCmdMsg 以在消息映射中进行处理。处理通知的消息映射项是 ON_NOTIFY。有关更多信息,请参见技术说明 61:ON_NOTIFY 和 WM_NOTIFY 消息。另外,派生类还可以使用“消息反射”处理自己的通知消息。
      

  3.   

    Windows 3.x的提醒消息
    在Windows 3.x,控件通过发送消息来通知父窗口事件的发生,例如鼠标点击,内容或选择的改变,控件背景绘制等。简单的提醒通过WM_COMMAND消息发送,消息的参数有提醒标志(如BN_CLICKED),控件ID(作为wParam)及控件句柄(lParam)。注意,由于wParam和lParam已被占用,因此没有办法传递更多的参数,这也是为什么只能通过这种方式发送简单提醒。例如在BN_CLICKED中,没有办法传递按键被点击时的鼠标位置。当Windows 3.x里的控件在发送提醒消息时,需要包含额外的数据,通常需要使用特定的消息,包括WM_CTLCOLOR、WM_VSCROLL、WM_HSCROLL、WM_DRAWITEM、WM_MEASUREITEM、WM_COMPAREITEM、WM_DELETEITEM、WM_CHARTOITEM、WM_VKEYTOITEM等。这些消息可以被反射回发送的控件。要了解更多信息,请参见TN062:Windows控件消息反射。Win32的提醒消息
    对于Windows 3.1中的控件,Win32 API使用大部分Windows 3.x中使用的提醒消息。然而Win32也增加了一些成熟的、复杂的控件来支持Windows 3.x。通常,这些控件在发送提醒消息的时候需要包含额外的数据。Win32 API的设计者选择用一个消息,WM_NOTIFY,而不是为每一个提醒消息增加一个对应的WM_*消息,以一种标准的格式来传递任意数量的额外数据。WM_NOTIFY消息将发送控件的ID作为其wParam,及一个结构体指针作为lParam。这个结构体要么是NMHDR,要么是更大的结构体,并且其第一个元素是NMHDR类型。注意,由于NMHDR是第一个元素,因此某个指向此结构体的指针也可以转换为NMHDR指针使用。在大多数情况下,此指针将指向一个更大的结构体,在使用时需要强制类型转换。仅在少数提醒消息中,例如通用提醒(消息名以NM_开始)及提示(tool tip)控件的TTN_SHOW和TTN_POP,使用NMHDR。NMHDR结构体包含发送此消息的控件的ID和句柄,以及提醒代码(例如TTN_SHOW)。NMHDR的格式如下:typedef struct tagNMHDR {    HWND hwndFrom;    UINT idFrom;    UINT code;} NMHDR;对于一个TTN_SHOW消息,成员code会被设置为TTN_SHOW。大多数提醒消息传递一个更大的结构体指针,并将NMHDR结构体作为其第一个元素。例如,在列表视图(list view)控件中按下键盘时发送的LVN_KEYDOWN消息,传递的结构体为LV_KEYDOWN,定义如下:typedef struct tagLV_KEYDOWN {    NMHDR hdr;       WORD wVKey;      UINT flags;  } LV_KEYDOWN;注意,由于NMHDR是此结构体的第一个成员,因此提醒消息传递的指针可以被转化为NMHDR或是LV_KEYDOWN指针。Windows新控件的通用提醒消息
    一些提醒消息对于所有的新控件是通用的,这些消息传递NMHDR结构体指针。提醒代码
     触发条件
     
    NM_CLICK
     用户在控件中点击鼠标左键
     
    NM_DBLCLK
     用户在控件中双击鼠标左键
     
    NM_RCLICK
     用户在控件中点击鼠标右键
     
    NM_RDBLCLK
     用户在控件中双击鼠标右键
     
    NM_RETURN
     控件获得焦点情况下,用户按下ENTER键
     
    NM_SETFOCUS
     控件获得焦点
     
    NM_KILLFOCUS
     控件丢失焦点
     
    NM_OUTOFMEMORY
     由于没有足够的内存,控件不能完成某操作
     ON_NOTIFY:在MFC应用程序里处理WM_NOTIFY消息
    CWnd::OnNotify函数处理提醒消息。其默认实现检查消息映射以查询可调用的处理函数。通常,程序员并不需要重写OnNotify,而应为自己的窗口类提供处理函数及其消息映射实体。通过ClassWizard 属性页或WizardBar,ClassWizard可以创建ON_NOTIFY消息映射实体,并提供处理函数体。要了解更多使用ClassWizard的信息,请参看Visual C++ Programmer's Guide的Mapping Messages to Functions。ON_NOTIFY消息映射宏格式如下:ON_NOTIFY(wNotifyCode, id, memberFxn)wNotifyCode要处理的提醒消息的代码,如LVN_KEYDOWN。id发送提醒消息的控件IDmemberFxn提醒消息的处理函数处理函数的原型如下:afx_msg void memberFxn(NMHDR * pNotifyStruct, LRESULT * result);pNotifyStruct上文中描述的参数结构体result在函数返回前应设置的返回代码例子要使成员函数OnKeydownList1处理ID为IDC_LIST1的CListCtrl发送的LVN_KEYDOWN消息,可以用ClassWizard添加以下代码到消息映射中:ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeydownList1)ClassWizard提供的函数体为:void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult){    LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;    // TODO: Add your control notification handler    //       code here        *pResult = 0;}注意,ClassWizard自动提供了参数的指针,可以直接使用pNMHDR或pLVKEYDOW来访问提醒结构体。ON_NOTIFY_RANGE
    若需要为一组控件处理相同的WM_NOTIFY消息,可以使用ON_NOTIFY_RANGE来代替ON_NOTIFY。例如,可以让一组按钮为某一提醒消息执行相同的操作。当使用ON_NOTIFY_RANGE,需要指定一组连续的控件ID,用于指定控件组的起始ID与结束ID。ClassWizard并不会处理ON_NOTIFY_RANGE,要使用它,需要手动添加消息映射。ON_NOTIFY_RANGE的消息映射实体及函数原因如下:ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn)wNotifyCode要处理的提醒消息的代码,如LVN_KEYDOWN。id控件组的起始IDidLast控件组的结束IDmemberFxn提醒消息的处理函数处理函数的原型如下:afx_msg void memberFxn(NMHDR * pNotifyStruct, LRESULT * result);pNotifyStruct上文中描述的参数结构体result在函数返回前应设置的返回代码ON_NOTIFY_EX,ON_NOTIFY_EX_RANGE
    若希望由多个对象处理提醒消息,可以使用ON_NOTIFY_EX(或ON_NOTIFY_EX_RANGE)来代替ON_NOTIFY(或ON_NOTIFY_RANGE)。EX版与常规版本的区别在于,EX版的处理函数有BOOL型的返回值,以决定消息的处理是否应该继续。若返回FALSE,则消息可以被多个对象处理。ClassWizard并不处理ON_NOTIFY_EX或ON_NOTIFY_EX_RANGE;要使用它们,需要手动添加消息映射。ON_NOTIFY_EX和ON_NOTIFY_EX_RANGE的消息映射实体及函数原型发下,参数的含义与常规版本一致:ON_NOTIFY_EX(nCode, id, memberFxn)ON_NOTIFY_EX_RANGE(wNotifyCode, id, idLast, memberFxn)两者的函数原型均为:afx_msg BOOL memberFxn(UINT id, NMHDR * pNotifyStruct, LRESULT * result);id表示发送提醒的控件的ID。若提醒消息已被处理完,函数应返回TRUE;否则,若需要进一步处理,函数返回FALSE
      

  4.   

    WM_NOTIFY 通知消息/提醒消息以上是关于此消息很详尽的资料了
      

  5.   

    问题如下:
      (1)前者中的CLICK事件由谁来检测到,又由谁来生成这个CLICK消息,消息从何处产生,依次传往何处。
    =======================
    你说的不是很清楚,一般来说,你在窗口上点左键,由鼠标的驱动程序产生获取鼠标的行为,由系统产生WM_LBUTTONDOWN消息,这个消息由应该是先发给系统消息队列,然后再由系统消息队列中取出来发到你程序所在的线程的消息队列中。你的程序用GetMessage取得消息,再分派给相应的窗口处理函数。
    如果你是点在控件上,比如按钮上,那么最终WM_LBUTTONDOWN由按钮所在内置的处理函数处理,产生WM_COMMAND消息发给按钮所在的父窗口。(2)后者中的CHANG事件由谁来检测到,又由谁来生成这个CHANG消息,消息从何处产生,依次传往何处。 
    ==================
    如果你在EDIT框中输入,最先也是由键盘的驱动产生通知系统,产生WM_KEYDOWN之类的消息,这些消息是经系统消息队列,线程所在的消息队列,最终交由EDIT控件这个窗口来处理,EDIT控件其实也是窗口, 也有系统内置的窗口处理函数,EDIT在处理WM_KEYDOWN消息时,和按钮一样,它向父窗口发送WM_COMMAND消息,你所说CHANG消息,其实从消息角度来看,是WM_COMMAND消息,CHANG是这个消息的一个通知码。
      

  6.   

    请问如何人为的通过程序发生一个CLICK事件,或者人为的通过程序产生一个CLICK消息。
      

  7.   

    自己用SendMessage向目标程序发送消息就是了。如果你是想模拟单击按钮之类的控件,那么SendMessage(hwnd,WM_COMMAND,...);如果仅仅是想模拟单击这个动作,那么用SendMessage(hwnd,WM_LBUTTONDOWN,...);