• 23、Windows API 进程间通信,数据复制消息(WM_COPYDATA)


        WM_COPYDATA是一个非常特殊的消息,此消息可能携带一个比较大的消息参数,而其他消息都只能携带两个固定大小的参数(WPARAMLPARAM)

    在发送WM_COPYDATA消息时,WM_COPYDATAwParam参数应该赋值为发送此消息的窗口,而lParam消息参数指向一个COPYDATASTRUCT结构类型的变量。

    typedef struct tagCOPYDATASTRUCT {

        ULONG_PTR dwData;

        DWORD     cbData;

        PVOID     lpData;

    } COPYDATASTRUCT, *PCOPYDATASTRUCT;

    dwData可以是任意值,lpData是需要发送给目录窗口所在进程的数据,cbData字符指定了lpData内存区域的字节数,也就是需要发送给目标进程的lpData所指向的数据的大小。

    在消息发送时,系统会将整个COPYDATASTRUCTlpData所指向的内容全部发送给目标进程。目标进程窗口在收到WM_COPYDATA后,可以从lParam参数中提取出数据。

    1、一个例子

    数据发送端

    通过WM_COPYDATA进程间通信-发送端
    通过WM_COPYDATA进程间通信
    **************************************/
    /* 头文件 */
    #include
    <windows.h>
    #include
    <commctrl.h>
    #include
    "resource.h"
    /* 全局变量 */
    HINSTANCE hinst;
    HWND hwnd, hwndEdit;
    LPSTR lpszCopy
    = "you can input any text\n then click \'Send\' Item at Menu";
    /* 函数声明 */
    int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
    LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

    /* ************************************
    * WinMain
    *************************************
    */
    int WINAPI WinMain(
    HINSTANCE hinstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
    MSG msg;
    WNDCLASSEX wcx;

    hinst
    = hinstance; // 保存应用程序实例

    // 填充WNDCLASSEX
    wcx.cbSize = sizeof(wcx);
    wcx.style
    = CS_HREDRAW | CS_VREDRAW;
    wcx.lpfnWndProc
    = MainWndProc; // 消息处理函数
    wcx.cbClsExtra = 0;
    wcx.cbWndExtra
    = 0;
    wcx.hInstance
    = hinstance;
    wcx.hIcon
    = LoadIcon(NULL, IDI_APPLICATION);
    wcx.hCursor
    = LoadCursor(NULL, IDC_ARROW);
    wcx.hbrBackground
    = (HBRUSH)GetStockObject( WHITE_BRUSH);
    wcx.lpszMenuName
    = MAKEINTRESOURCE(IDR_MENU_COMMAND); // 菜单
    wcx.lpszClassName = "copydata"; // 窗口类名
    wcx.hIconSm = NULL;
    // 注册窗口类
    if(RegisterClassEx(&wcx) == 0)
    {
    return 0;
    }
    // 创建窗口
    hwnd = CreateWindow(
    "copydata",
    "Sample",
    WS_TILEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT,
    500, 400,
    (HWND) NULL,
    (HMENU) NULL,
    hinstance,
    (LPVOID) NULL);
    if (!hwnd)
    return 0;

    // 显示、刷新窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    // 消息循环

    BOOL fGotMessage;
    while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1)
    {
    TranslateMessage(
    &msg);
    DispatchMessage(
    &msg);
    }
    return msg.wParam;
    UNREFERENCED_PARAMETER(lpCmdLine);
    }

    /* ************************************
    * 消息处理函数
    *************************************
    */
    LONG APIENTRY MainWndProc(HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
    {
    switch (message)
    {
    case WM_CREATE:
    {
    // 在主窗口创建时,创建一个EDIT控件,用于编辑需要复制的内容
    RECT rectMain;
    GetClientRect(hwnd,
    &rectMain);
    hwndEdit
    = CreateWindow("EDIT",
    NULL,
    WS_CHILD
    | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
    ES_LEFT
    | ES_MULTILINE | ES_AUTOVSCROLL,
    0., 0, rectMain.right, rectMain.bottom,
    hwnd, NULL,
    (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    NULL);
    if(hwndEdit == NULL)
    {
    MessageBox(hwnd,
    "Create Window Error","ERROR",MB_OK);
    ExitProcess(
    0);
    }
    // 设置EDIT控件的内容
    SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM) lpszCopy);
    break;
    }
    case WM_COMMAND: // 菜单输入
    {
    // 如果通过菜单点击“send”按钮
    if (LOWORD(wParam) == ID_COMMAND_SEND)
    {
    // 获取EDIT控件中的文本
    DWORD dwTextLenth = GetWindowTextLength(hwndEdit);
    LPSTR szText
    = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_NO_SERIALIZE,dwTextLenth);
    GetWindowText(hwndEdit,szText,dwTextLenth);
    // 构造 COPYDATASTRUCT
    COPYDATASTRUCT cds;
    HWND hwnd2
    = FindWindow("copydata2","RECV COPY DATA");
    if(hwnd2 == NULL)
    {
    MessageBox(hwnd,
    "can not find window 2","ERROR",MB_OK);
    break;
    }
    cds.dwData
    = 0x12345678; // 自定义的数据
    cds.cbData = dwTextLenth; // lpData的长度
    cds.lpData = szText; // 需要复制的数据
    // 发送消息,COPYDATASTRUCT结构的指针做为lParam
    SendMessage(
    hwnd2,
    // 目的窗口
    (UINT) WM_COPYDATA, // 消息 ID
    (WPARAM) hwnd, // wParam,源窗口句柄
    (LPARAM) &cds // lParam,COPYDATASTRUCT
    );
    // 释放内存
    HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,szText);
    }
    break;
    }
    case WM_DESTROY: // 退出
    PostQuitMessage(0);
    return 0;

    default: // 其他消息的处理
    return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
    }

    数据接收端

    通过WM_COPYDATA进程间通信-接收端
    通过WM_COPYDATA进程间通信
    **************************************/
    /* 头文件 */
    #include
    <windows.h>
    #include
    <commctrl.h>
    /* 全局变量 */
    HINSTANCE hinst;
    HWND hwnd,hwndEdit;
    /* 函数声明 */
    int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
    LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

    /* ************************************
    * void main()
    * 功能 进程间mailslot通信客户端
    *************************************
    */
    int WINAPI WinMain(
    HINSTANCE hinstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
    MSG msg;
    WNDCLASSEX wcx;
    // 填充WNDCLASSEX
    wcx.cbSize = sizeof(wcx);
    wcx.style
    = CS_HREDRAW | CS_VREDRAW;
    wcx.lpfnWndProc
    = MainWndProc;
    wcx.cbClsExtra
    = 0;
    wcx.cbWndExtra
    = 0;
    wcx.hInstance
    = hinstance;
    wcx.hIcon
    = LoadIcon(NULL, IDI_APPLICATION);
    wcx.hCursor
    = LoadCursor(NULL, IDC_ARROW);
    wcx.hbrBackground
    = (HBRUSH)GetStockObject( WHITE_BRUSH);
    wcx.lpszMenuName
    = NULL;
    wcx.lpszClassName
    = "copydata2";
    wcx.hIconSm
    = NULL;
    // 注册窗口类
    if(RegisterClassEx(&wcx) == 0)
    {
    return 0;
    }
    // 创建窗口
    hwnd = CreateWindow(
    "copydata2",
    "RECV COPY DATA",
    WS_TILEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT,
    500, 400,
    (HWND) NULL, (HMENU) NULL, hinstance, (LPVOID) NULL
    );

    if (!hwnd)
    return 0;
    // 显示刷新窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    // 消息
    BOOL fGotMessage;
    while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1)
    {
    TranslateMessage(
    &msg);
    DispatchMessage(
    &msg);
    }
    return msg.wParam;
    UNREFERENCED_PARAMETER(lpCmdLine);
    return 0;
    }

    // 消息处理函数
    LONG APIENTRY MainWndProc(HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
    {
    switch (message)
    {
    case WM_CREATE:
    {
    // 创建主窗口时,创建一个EDIT控件
    RECT rectMain;
    GetClientRect(hwnd,
    &rectMain);
    hwndEdit
    = CreateWindow("EDIT",
    NULL,
    WS_CHILD
    | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
    ES_LEFT
    | ES_MULTILINE | ES_AUTOVSCROLL,
    0., 0, rectMain.right, rectMain.bottom,
    hwnd,
    NULL,
    (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    NULL);
    if(hwndEdit == NULL)
    {
    MessageBox(hwnd,
    "Create Window Error","ERROR",MB_OK);
    ExitProcess(
    0);
    }
    break;
    case WM_COPYDATA:
    {
    // 当收到WM_COPYDATA消息时,从lParam中提取出
    // COPYDATASTRUCT
    PCOPYDATASTRUCT lpcds = (PCOPYDATASTRUCT)lParam;
    // 将复制的数据在界面上显示
    SetWindowText(hwndEdit,(LPSTR)lpcds->lpData);
    break;
    }

    case WM_DESTROY: // 退出
    PostQuitMessage(0);
    return 0;

    default: // 其他消息处理
    break;
    }
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
    }

    Interprocess Communications[2]

    参考

    [1] 精通Windows API 函数、接口、编程实例

    [2] http://msdn.microsoft.com/en-us/library/ms648710%28VS.85%29.aspx

  • 相关阅读:
    基于term vector深入探查数据
    oracle 行转列
    oracle 统计成绩
    最全最新个税计算公式---今天你税了吗?
    .net反混淆脱壳工具de4dot的使用
    使用ILSpy软件反编译.Net应用程序的方法及注意事项
    EmguCV使用Stitcher类来拼接图像
    从睡姿就可以看出你的性格,据说非常准,快存!
    分享几个.NET WinForm开源组件,纪念逐渐远去的WinForm。。。
    【转载】关于.NET下开源及商业图像处理(PSD)组件
  • 原文地址:https://www.cnblogs.com/mydomain/p/1932112.html
Copyright © 2020-2023  润新知