zoukankan      html  css  js  c++  java
  • windows消息传送(自定义消息和WM_COPYDATA)

      通过SendMessge实现的进程间通信。

    0x01 自定义消息

    1,WINDOWS中自定义消息的定义和使用;

      (1)在WNDOWS中消息分系统消息和自定义消息。系统消息定义从0到0x3FF,使用0x400到0x7FFF定义自己的消息。Windows把0x400定义为WM_USER。如果想定义自己的一个消息,可以在WM_USER上加上一个值:

       #define UM_MSG  WM_USER+1

      (2)另一种自定义窗口消息的方法是用RegisterWindowsMessage()函数来注册这个消息。与在WM_USER上加上某个数相比,它的好处是不必考虑所表示的消息标识符是否超出工程的允许范围。如:

       const UINT RM_MSG = RegisterWindowMessage(L"HelloWorld");

       

      在接收消息的程序中,需要对添加对应消息的响应处理函数,并将消息和消息处理函数关联.

    0x02  WM_COPYDATA

        WM_COPYDATA消息,在win32中用来进行进程间的数据传输。

        

    typedef struct tagCOPYDATASTRUCT {
        ULONG_PTR dwData;                         //自定义数据
        DWORD cbData;                             //数据的大小(字节数)
        _Field_size_bytes_(cbData) PVOID lpData;  //指向数据的指针
    } COPYDATASTRUCT, *PCOPYDATASTRUCT;
    

      

      注意:该消息只能由SendMessage()来发送,而不能使用PostMessage()。因为系统必须管理用以传递数据的缓冲区的生命期,如果使用了PostMessage(),数据缓冲区会在接收方(线程)有机会处理该数据之前,就被系统清除和回收。此外如果lpData指向一个带有指针或某一拥有虚函数的对象时,也要小心处理。

    LRESULT SendMessage(
      HWND hWnd,      // 目标进程窗口句柄
      UINT Msg,       // WM_COPYDATA
      WPARAM wParam,  // 发送进程的窗体句柄
      LPARAM lParam   // 指向COPYDATASTRUCT数据结构的指针
    );
    

      接收进程窗体句柄可以通过FindWindow函数获取:

    CWnd* DlgHwnd = FindWindow(NULL, L"Client");
    

      

      源代码:

      1 // ServerDlg.cpp : 实现文件
      2 //
      3 
      4 #include "stdafx.h"
      5 #include "Server.h"
      6 #include "ServerDlg.h"
      7 #include "afxdialogex.h"
      8 
      9 #ifdef _DEBUG
     10 #define new DEBUG_NEW
     11 #endif
     12 #define UM_MSG  WM_USER+1
     13 
     14 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
     15 
     16 BOOL CStringToChar(char** DestinationString, CString& SourceString);
     17 const UINT RM_MSG = RegisterWindowMessage(L"HelloWorld");
     18 class CAboutDlg : public CDialogEx
     19 {
     20 public:
     21     CAboutDlg();
     22 
     23 // 对话框数据
     24 #ifdef AFX_DESIGN_TIME
     25     enum { IDD = IDD_ABOUTBOX };
     26 #endif
     27 
     28     protected:
     29     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
     30 
     31 // 实现
     32 protected:
     33     DECLARE_MESSAGE_MAP()
     34 };
     35 
     36 CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
     37 {
     38 }
     39 
     40 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
     41 {
     42     CDialogEx::DoDataExchange(pDX);
     43 }
     44 
     45 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
     46 END_MESSAGE_MAP()
     47 
     48 
     49 // CServerDlg 对话框
     50 
     51 
     52 
     53 CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
     54     : CDialogEx(IDD_SERVER_DIALOG, pParent)
     55     , m_CEdit_User_Message(0)
     56     , m_CEdit_Register_Message(0)
     57     , m_CEdit_CopyData_Message(_T(""))
     58 {
     59     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
     60 }
     61 
     62 void CServerDlg::DoDataExchange(CDataExchange* pDX)
     63 {
     64     CDialogEx::DoDataExchange(pDX);
     65     DDX_Text(pDX, IDC_EDIT_USER_MESSAGE, m_CEdit_User_Message);
     66     DDX_Text(pDX, IDC_EDIT_REGISTER_MESSAGE, m_CEdit_Register_Message);
     67     DDX_Text(pDX, IDC_EDIT_COPYDATA_MESSAGE, m_CEdit_CopyData_Message);
     68 }
     69 
     70 BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
     71     ON_WM_SYSCOMMAND()
     72     ON_WM_PAINT()
     73     ON_WM_QUERYDRAGICON()
     74     ON_BN_CLICKED(IDC_BUTTON_USER_MESSAGE, &CServerDlg::OnBnClickedButtonUserMessage)
     75     ON_BN_CLICKED(IDC_BUTTON_REGISTER_MESSAGE, &CServerDlg::OnBnClickedButtonRegisterMessage)
     76     ON_BN_CLICKED(IDC_BUTTON_COPYDATA_MESSAGE, &CServerDlg::OnBnClickedButtonCopydataMessage)
     77 END_MESSAGE_MAP()
     78 
     79 
     80 // CServerDlg 消息处理程序
     81 
     82 BOOL CServerDlg::OnInitDialog()
     83 {
     84     CDialogEx::OnInitDialog();
     85 
     86     // 将“关于...”菜单项添加到系统菜单中。
     87 
     88     // IDM_ABOUTBOX 必须在系统命令范围内。
     89     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
     90     ASSERT(IDM_ABOUTBOX < 0xF000);
     91 
     92     CMenu* pSysMenu = GetSystemMenu(FALSE);
     93     if (pSysMenu != NULL)
     94     {
     95         BOOL bNameValid;
     96         CString strAboutMenu;
     97         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
     98         ASSERT(bNameValid);
     99         if (!strAboutMenu.IsEmpty())
    100         {
    101             pSysMenu->AppendMenu(MF_SEPARATOR);
    102             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    103         }
    104     }
    105 
    106     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    107     //  执行此操作
    108     SetIcon(m_hIcon, TRUE);            // 设置大图标
    109     SetIcon(m_hIcon, FALSE);        // 设置小图标
    110 
    111     // TODO: 在此添加额外的初始化代码
    112 
    113     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    114 }
    115 
    116 void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
    117 {
    118     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    119     {
    120         CAboutDlg dlgAbout;
    121         dlgAbout.DoModal();
    122     }
    123     else
    124     {
    125         CDialogEx::OnSysCommand(nID, lParam);
    126     }
    127 }
    128 
    129 // 如果向对话框添加最小化按钮,则需要下面的代码
    130 //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
    131 //  这将由框架自动完成。
    132 
    133 void CServerDlg::OnPaint()
    134 {
    135     if (IsIconic())
    136     {
    137         CPaintDC dc(this); // 用于绘制的设备上下文
    138 
    139         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    140 
    141         // 使图标在工作区矩形中居中
    142         int cxIcon = GetSystemMetrics(SM_CXICON);
    143         int cyIcon = GetSystemMetrics(SM_CYICON);
    144         CRect rect;
    145         GetClientRect(&rect);
    146         int x = (rect.Width() - cxIcon + 1) / 2;
    147         int y = (rect.Height() - cyIcon + 1) / 2;
    148 
    149         // 绘制图标
    150         dc.DrawIcon(x, y, m_hIcon);
    151     }
    152     else
    153     {
    154         CDialogEx::OnPaint();
    155     }
    156 }
    157 
    158 //当用户拖动最小化窗口时系统调用此函数取得光标
    159 //显示。
    160 HCURSOR CServerDlg::OnQueryDragIcon()
    161 {
    162     return static_cast<HCURSOR>(m_hIcon);
    163 }
    164 
    165 
    166 
    167 void CServerDlg::OnBnClickedButtonUserMessage()
    168 {
    169     // TODO: 在此添加控件通知处理程序代码
    170     UpdateData(TRUE);
    171     
    172     CWnd* DlgHwnd = FindWindow(NULL,L"Client");
    173     if (DlgHwnd == NULL) {
    174         AfxMessageBox(TEXT("No Found"));
    175         return;
    176     }
    177     long ParameterData;
    178     ParameterData = m_CEdit_User_Message;
    179     DlgHwnd->SendMessage(UM_MSG, NULL, (LPARAM)ParameterData);// 发送.
    180 }
    181 
    182 
    183 void CServerDlg::OnBnClickedButtonRegisterMessage()
    184 {
    185     // TODO: 在此添加控件通知处理程序代码
    186     UpdateData(TRUE);
    187     CWnd* DlgHwnd = FindWindow(NULL, L"Client");
    188     if (DlgHwnd == NULL) {
    189         AfxMessageBox(TEXT("No Found"));
    190         return;
    191     }
    192     long ParameterData;
    193     ParameterData = m_CEdit_Register_Message;
    194     DlgHwnd->SendMessage(RM_MSG, NULL, (LPARAM)ParameterData);// 发送.
    195 
    196 }
    197 
    198 
    199 void CServerDlg::OnBnClickedButtonCopydataMessage()
    200 {
    201     // TODO: 在此添加控件通知处理程序代码
    202     UpdateData(TRUE);
    203 
    204     CWnd* DlgHwnd = FindWindow(NULL, L"Client");
    205     if (DlgHwnd == NULL) {
    206         AfxMessageBox(TEXT("No Found"));
    207         return;
    208     }
    209     char* DestinationString = NULL;
    210 
    211     CStringToChar(&DestinationString, m_CEdit_CopyData_Message);
    212 
    213 
    214 
    215     COPYDATASTRUCT ParameterData; // 给COPYDATASTRUCT结构赋值.
    216     ParameterData.dwData = 0;
    217     ParameterData.cbData = strlen(DestinationString);  //注意这里
    218     ParameterData.lpData = DestinationString;
    219 
    220     DlgHwnd->SendMessage(WM_COPYDATA, NULL, (LPARAM)&ParameterData);// 发送.
    221 
    222     if (DestinationString!=NULL)
    223     {
    224         delete[] DestinationString;
    225         DestinationString = NULL;
    226     }
    227 }
    228 BOOL CStringToChar(char** DestinationString, CString& SourceString)
    229 {
    230     if (SourceString.IsEmpty())
    231     {
    232         return FALSE;
    233     }
    234     int SourceStringLength = SourceString.GetLength();
    235     *DestinationString = (char*)malloc((SourceStringLength * 2 + 1) * sizeof(char));//CString的长度中汉字算一个长度    
    236 
    237     if (*DestinationString == NULL)
    238     {
    239         return FALSE;
    240     }
    241     USES_CONVERSION;
    242     strcpy(*DestinationString, W2A(SourceString.LockBuffer()));
    243     SourceString.ReleaseBuffer();
    244     return TRUE;
    245 }
    ServerDlg.cpp
      1 // ClientDlg.cpp : 实现文件
      2 //
      3 
      4 #include "stdafx.h"
      5 #include "Client.h"
      6 #include "ClientDlg.h"
      7 #include "afxdialogex.h"
      8 
      9 #ifdef _DEBUG
     10 #define new DEBUG_NEW
     11 #endif
     12 
     13 
     14 #define UM_MSG  WM_USER+1
     15 
     16 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
     17 const UINT RM_MSG = RegisterWindowMessage(L"HelloWorld");
     18 
     19 class CAboutDlg : public CDialogEx
     20 {
     21 public:
     22     CAboutDlg();
     23 
     24 // 对话框数据
     25 #ifdef AFX_DESIGN_TIME
     26     enum { IDD = IDD_ABOUTBOX };
     27 #endif
     28 
     29     protected:
     30     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
     31 
     32 // 实现
     33 protected:
     34     DECLARE_MESSAGE_MAP()
     35 };
     36 
     37 CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
     38 {
     39 }
     40 
     41 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
     42 {
     43     CDialogEx::DoDataExchange(pDX);
     44 }
     45 
     46 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
     47 END_MESSAGE_MAP()
     48 
     49 
     50 // CClientDlg 对话框
     51 
     52 
     53 
     54 CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
     55     : CDialogEx(IDD_CLIENT_DIALOG, pParent)
     56     , m_CEdit_User_Message(0)
     57     , m_CEdit_Register_Message(0)
     58     , m_CEdit_CopyData_Message(_T(""))
     59 {
     60     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
     61 }
     62 
     63 void CClientDlg::DoDataExchange(CDataExchange* pDX)
     64 {
     65     CDialogEx::DoDataExchange(pDX);
     66     DDX_Text(pDX, IDC_EDIT_USER_MESSAGE, m_CEdit_User_Message);
     67     DDX_Text(pDX, IDC_EDIT_REGISTER_MESSAGE, m_CEdit_Register_Message);
     68     DDX_Text(pDX, IDC_EDIT_COPYDATA_MESSAGE, m_CEdit_CopyData_Message);
     69 }
     70 
     71 BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
     72     ON_WM_SYSCOMMAND()
     73     ON_WM_PAINT()
     74     ON_WM_QUERYDRAGICON()
     75     ON_WM_COPYDATA()
     76     ON_MESSAGE(UM_MSG, (LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM))OnUserReceiveMsg)
     77     ON_REGISTERED_MESSAGE(RM_MSG, (LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM))OnRegisterReceiveMsg)
     78 END_MESSAGE_MAP()
     79 
     80 
     81 // CClientDlg 消息处理程序
     82 
     83 BOOL CClientDlg::OnInitDialog()
     84 {
     85     CDialogEx::OnInitDialog();
     86 
     87     // 将“关于...”菜单项添加到系统菜单中。
     88 
     89     // IDM_ABOUTBOX 必须在系统命令范围内。
     90     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
     91     ASSERT(IDM_ABOUTBOX < 0xF000);
     92 
     93     CMenu* pSysMenu = GetSystemMenu(FALSE);
     94     if (pSysMenu != NULL)
     95     {
     96         BOOL bNameValid;
     97         CString strAboutMenu;
     98         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
     99         ASSERT(bNameValid);
    100         if (!strAboutMenu.IsEmpty())
    101         {
    102             pSysMenu->AppendMenu(MF_SEPARATOR);
    103             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    104         }
    105     }
    106 
    107     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    108     //  执行此操作
    109     SetIcon(m_hIcon, TRUE);            // 设置大图标
    110     SetIcon(m_hIcon, FALSE);        // 设置小图标
    111 
    112     // TODO: 在此添加额外的初始化代码
    113 
    114     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    115 }
    116 
    117 void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
    118 {
    119     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    120     {
    121         CAboutDlg dlgAbout;
    122         dlgAbout.DoModal();
    123     }
    124     else
    125     {
    126         CDialogEx::OnSysCommand(nID, lParam);
    127     }
    128 }
    129 
    130 // 如果向对话框添加最小化按钮,则需要下面的代码
    131 //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
    132 //  这将由框架自动完成。
    133 
    134 void CClientDlg::OnPaint()
    135 {
    136     if (IsIconic())
    137     {
    138         CPaintDC dc(this); // 用于绘制的设备上下文
    139 
    140         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    141 
    142         // 使图标在工作区矩形中居中
    143         int cxIcon = GetSystemMetrics(SM_CXICON);
    144         int cyIcon = GetSystemMetrics(SM_CYICON);
    145         CRect rect;
    146         GetClientRect(&rect);
    147         int x = (rect.Width() - cxIcon + 1) / 2;
    148         int y = (rect.Height() - cyIcon + 1) / 2;
    149 
    150         // 绘制图标
    151         dc.DrawIcon(x, y, m_hIcon);
    152     }
    153     else
    154     {
    155         CDialogEx::OnPaint();
    156     }
    157 }
    158 
    159 //当用户拖动最小化窗口时系统调用此函数取得光标
    160 //显示。
    161 HCURSOR CClientDlg::OnQueryDragIcon()
    162 {
    163     return static_cast<HCURSOR>(m_hIcon);
    164 }
    165 
    166 void CClientDlg::OnUserReceiveMsg(WPARAM wParam, LPARAM lParam)
    167 {
    168     m_CEdit_User_Message = long(lParam);
    169     // 更新数据.
    170     UpdateData(FALSE);
    171 }
    172 
    173 void CClientDlg::OnRegisterReceiveMsg(WPARAM wParam, LPARAM lParam)
    174 {
    175     m_CEdit_Register_Message = long(lParam);
    176     // 更新数据.
    177     UpdateData(FALSE);
    178 }
    179 
    180 BOOL CClientDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
    181 {
    182     // TODO: 在此添加消息处理程序代码和/或调用默认值
    183     m_CEdit_CopyData_Message = (LPSTR)pCopyDataStruct->lpData;
    184     m_CEdit_CopyData_Message = m_CEdit_CopyData_Message.Left(pCopyDataStruct->cbData);
    185 
    186     // 更新数据.
    187     UpdateData(FALSE);
    188     return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
    189 }
    ClientDlg.cpp
  • 相关阅读:
    利用“通过'反射方式'创建的对象”来创建对象的性能问题?
    Linq 学习笔记(一)
    说说数据类型转换帮助类
    使用公共静态属性的方式来代替公共静态字段(C#)
    支持差异数据保存的数据库实体类设计(二)(续)
    编程杂记
    Linq 学习笔记(二)
    UI版本WinDBG常用命令
    Oracle数据库卸载
    SAS框架问世
  • 原文地址:https://www.cnblogs.com/lsh123/p/7441403.html
Copyright © 2011-2022 走看看