zoukankan      html  css  js  c++  java
  • MFC窗口消息PostMessage和SendMessage

    以前这些消息用得比较少,但是今天碰到了个事儿,我看非用消息不可。

    事情是这样的,我在线程中需要刷新对话框上面的内容,但是每每执行到UpdateData时就出现了断言错误。

    查了相关资料,发现这个可能是多个模块调用同一个方法出现的问题。反正照我之前的逻辑走不通。

    我现在将更新对话框信息的函数,通过线程中发窗口消息,让对话框的消息处理函数来负责处理我自定义的消息,为我刷新对话框数据。

    // http://blog.csdn.net/a8082649/article/details/7733527

    1.自定义消息ID。

    #define WM_MY_MESSAGE (WM_USER+100)         WM_USER为windows系统为非系统消息保留的ID,这里至少要用100,因为其它控件的消息会占用一部分。

    2. 定义消息处理函数。

    消息处理函数为消息目标类的成员函数。首先应该在.h 文件中声明。这里以主窗口类为例,主窗口类名 CMainDialog,则首先在CMainDialog.h声明消息处理函数。

     

    protected: 

    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); 

     

    3.在CMainDialog.cpp中实现消息处理函数


    LPESULT CMainDialog::OnMyMessage(WPARAM wParam, LPARAM lParam)  {  // TODO: 处理用户自定义消息  ...  return 0;  }

    4.在CMainDialog.cpp中映射消息ID和消息处理函数

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
    //{{AFX_MSG_MAP(CMainFrame) 
    ON_WM_CREATE() 
    ON_WM_TIMER() 
    ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage) 
    //}}AFX_MSG_MAP 
    END_MESSAGE_MAP()

    在创建线程的时候将主窗口句柄作为参数传入线程,就可以用 PostMessage传递消息了。

    消息预处理函数

    添加消息处理函数PreTranslateMessage,此函数可以通过MFC ClassWizard添加

    1. BOOL CPreTranslateMessageDlg::PreTranslateMessage(MSG* pMsg)
    2. {
    3.     if (pMsg->message==WM_LBUTTONDOWN)
    4.     {
    5.         MessageBox("三三四四");
    6.     }
    7.     
    8.     return CDialog::PreTranslateMessage(pMsg);
    9. }

    此函数为手动添加的消息函数,可通过pMsg->message来判断是什么消息,比如WM_LBUTTONDOWN是左键单击消息,那当单击左键时就会执行此函数,同样当敲击一下键盘也会执行PreTranslateMessage函数

    // ===================================================================================================================

    SendMessage函数功能:该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。

    函数原型 :

    LRESULT SendMessage(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM IParam);

    参数:

    hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。

        wMsg用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量.

        wParam通常是一个与消息有关的常量值,也可能是窗口或控件的句柄

        lParam通常是一个指向内存中数据的指针。由于WParm、lParam和Pointer都是32位的,因此,它们之间可以相互转换

    返回值:返回值指定消息处理的结果,依赖于所发送的消息。

    SendMessage用例

    1.       系统消息(WM_)

    ::SendMessage(this->m_hWnd,WM_CLOSE,0,0);

    SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);

    SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);

    SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);

    SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);

    SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);

    SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);

    SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);

    SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);

    SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);

    SendMessage(hWnd,WM_KEYDOWN,VK_RETURN,0x001c0001);

    SendMessage(hWnd,WM_CHAR,VK_RETURN,0x001c0001);

    SendMessage HWND, WM_SHOWWINDOW, SW_HIDE, vbNull '隐藏窗体

    SendMessage HWND, WM_SHOWWINDOW, SW_NORMAL, vbNull '显示窗体

    SendMessage(HWND, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)   '关闭

    SendMessage(HWND, WM_SYSCOMMAND, SC_MINIMIZE, ByVal 0&) '最小化

    SendMessage(HWND, WM_PASTE, 0, 0) '粘贴

    SendMessage(HWND, WM_COPY, 0, 0) '复制

    SendMessage(HWND, WM_UNDO, 0, 0) '撤消

    2.       通告消息

    比如:给资源ID为IDC_BUTTON2的按钮,发送点击消息:

    SendMessage(WM_COMMAND,

    MAKELONG(IDC_BUTTON2,BN_CLICKED),

    (LPARAM)(GetDlgItem(IDC_BUTTON2)-> GetSafeHwnd()));

    或:

             ::SendMessage(m_hWnd,

    WM_COMMAND,

    MAKELONG(IDC_BUTTON2,BN_CLICKED),

    (LPARAM)(GetDlgItem(IDC_BUTTON2)-> GetSafeHwnd()));

    例:给菜单ID为ID_GET的菜单项,发送消息

    ::SendMessage(AfxGetMainWnd()->m_hWnd,WM_COMMAND,ID_GET,NULL);

     

    3.       用户自定义消息

     SendMessge(WM_MYMSG,0,0);

    或:

    ::SendMessge(::AfxGetMainWnd()->m_hWnd,WM_MYMSG,0,0);

    4.       向其他应用程序发送消息

    也可以为其他应用程序发送消息,前提是找到窗体的句柄,如:与FindWindow()函数一起使用;

    如:

    CString str="360w.txt -记事本";//向窗口为str的记事本窗口发送WM_CLOSE消息

             CWnd *pWnd=CWnd::FindWindow(NULL,str);//获取目的窗口对象

             ::SendMessage(*pWnd,WM_CLOSE,0,0);

    窗口标题的获取方法:

    1.       使用VC++自带工具SPY++

    2.       编程实现,可用EnumWindows函数实现;详见“枚举所有窗体,并向打开的窗体发送关闭消息”http://download.csdn.net/detail/nuptboyzhb/4162747

     

    举例:

    HWND gameh=NULL;  gameh=::FindWindow(NULL,"窗口标题");//参看游戏的标题.可以用vc6.0自带的Spy++工具查看

     CWnd* pWnd = CWnd::FromHandle(gameh);

    //在坐标为(x,y)的点,发送鼠标按下消息//注意,x,y是客户区的坐标

     ::SendMessage(*pWnd,WM_LBUTTONDOWN,0,(y<<16)+x);

    //发送鼠标移动消息,鼠标移动到点(x,y)

    ::SendMessage(*pWnd,WM_MOUSEMOVE,0,MAKELONG(x,y));

    //发送粘贴消息

    ::SendMessage(dlg_hwnd,WM_PASTE,0,0);

    5. 发送自己注册的消息 5.1 发送端:

    本示例先通过RegisterWindowMessage函数来注册一条消息,然后用Win32 API函数SendMessage()发送。 主程序端: 建立MFC对话框,添加一个按钮 在对话框CPP文件预处理下加入下面代码: static UINT NEAR WM_RGSMSG=RegisterWindowMessage("MESSAGE");//注册一条发送MESSAGE的自己注册的消息 在按钮单击事件函数中添加后: void CMyDlg::OnButton1() {  // TODO: Add your control notification handler code here  HWND  hwnd=::FindWindow(NULL,"接受窗口");//找到我们要发送消息的窗口句柄  if(hwnd==NULL)  {   AfxMessageBox("没有找到接受窗口");   return;  }  else   ::SendMessage(hwnd,WM_RGSMSG,1,0);//发送消息 }

    5.2 接收端:

    本示例接受方,仍然是先通过RegisterWindowMessage函数来注册一条相同的消息,然后定义消息宏,绑定处理函数 接收窗口: 建立MFC对话框工程 在对话框CPP文件预处理下加入下面代码: static UINT NEAR WM_RGSMSG=RegisterWindowMessage("MESSAGE");//注册一条发送MESSAGE的自己注册的消息 在消息宏声明处 将消息声明为: afx_msg LRESULT OnRgsmsg(WPARAM wParam,LPARAM lparam);    //声明消息映射函数 在建立消息映射表的地方添加如下代码: ON_REGISTERED_MESSAGE(WM_RGSMSG,OnRgsmsg)//注册的消息宏应放在这个位置 在CPP文件中,添加函数定义,代码如下: LRESULT CMyDlg::OnRgsmsg(WPARAM wParam,LPARAM lParam) {  AfxMessageBox("接收到消息");  return TRUE; }

    // http://blog.csdn.net/nupt123456789/article/details/7370463

  • 相关阅读:
    CMDXP.CMD命令大全
    ASP.NET 页生命周期概述
    使用 ASP.NET 2.0提供的WebResource管理资源
    软件包管理 之 Fedora / Redhat 软件包管理指南
    开源代码分析研究 之 BugNet (2008年1月14日更新 第一章BugNet 简介 已完成)
    软件包管理 之 如何编译安装源码包软件
    硬件管理 之 Linux 硬件管理的基础知识
    软件包管理 之 fedorarpmdevtools 工具介绍
    软件包管理 之 Fedora/Redhat 在线安装更新软件包,yum 篇 ── 给新手指南
    系统引导管理 之 系统引导过程及硬盘分区结构论述
  • 原文地址:https://www.cnblogs.com/liflying/p/4279255.html
Copyright © 2011-2022 走看看