How to receive a message containing WM_COPYDATA?

Leonardo 91 Reputation points
2021-09-18T04:00:40.293+00:00

I figured out how to send the message with data, but i couldn't understand how to read it in the 'receiver app'

    // Sender
    void Msg(std::string msg) 
    {
        // Remove non utf8 char from string.
        string = sanitize_utf8(string);

        COPYDATASTRUCT cds{};
        cds.dwData = 1; 
        cds.lpData = (PVOID) string.c_str();
        cds.cbData = strlen((char*)cds.lpData); 


        auto response = SendMessage(hwnd, WM_COPYDATA, (WPARAM)w_hwnd, (LPARAM)&cds);

    }

While searching I could find some examples, but i still did not understand how to properly write it.
The receiver is a dll lib.

//Received
//??

I dont know much about c++, would like to ask if someone could explain me it with most details possible.

C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,519 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Sam of Simple Samples 5,516 Reputation points
    2021-09-18T05:59:18.73+00:00

    Do you use MFC? I assume not. Do you know how to make a window procedure to receive messages? In your window procedure you need to process the WM_COPYDATA message. Do you know how to do that? In that you can use:

    COPYDATASTRUCT *pcds = (PCOPYDATASTRUCT)lParam;
    

    And then the string would be (char*)pcds ->lpData.

    That is a simple sample. Be sure to read the documentation and other materials; there are many details you need to understand.

    I have created a sample. The complete sample is in GitHub at SimpleSamples/SampleCopydata: Sample use of the WM_COPYDATA message. It is a single-program sample, created in Visual Studio as a Windows Desktop Applicaiton. It needs to be executed twice. The first execution will be the receiver. The second execution will be the sender of a string. Each time the Send button is pressed a string with the current time is sent to the other instance.

    The data is sent using:

    // Format the time into a string
    TCHAR timeString[30];
    time_t secs = time(0);
    struct tm local;
    localtime_s(&local, &secs);
    swprintf(timeString, sizeof(timeString), L"%02d:%02d:%02d", local.tm_hour, local.tm_min, local.tm_sec);
    // Send the string
    COPYDATASTRUCT cds{};
    cds.dwData = 1;
    cds.cbData = (wcslen(timeString)+1)*sizeof(TCHAR);
    cds.lpData = (PVOID)timeString;
    SendMessage(OtherhWnd, WM_COPYDATA, NULL, (LPARAM)&cds);
    

    The data is received using:

    COPYDATASTRUCT *pMessageCDS = (PCOPYDATASTRUCT)lParam;
    // first save the string
    pSavedString = (TCHAR*)malloc(pMessageCDS->cbData);
    memcpy_s(pSavedString, pMessageCDS->cbData, pMessageCDS->lpData, pMessageCDS->cbData);
    // now use it now and later
    SetDlgItemTextW(hWnd, IDC_MESSAGE_EDIT, pSavedString);
    
    0 comments No comments

  2. Castorix31 81,461 Reputation points
    2021-09-18T06:21:08.927+00:00

    Just see the sample in the doc : Using Data Copy


  3. Leonardo 91 Reputation points
    2021-09-18T20:59:03.747+00:00

    @Sam of Simple Samples alsmot done, but what i can do about the loop in Step3? I still need the code to execute other things instead of stuck on a endless loop.

    // Step 4: the Window Procedure  
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)  
    {  
      
     const char* translatedMessage = TrMessage(msg);  
      
     std::wstringstream ss;  
     ss << L"\nmsg: " << msg << L" " << translatedMessage;  
     OutputDebugString(ss.str().c_str());  
      
        switch(msg)  
        {  
     case WM_COPYDATA:  
     {  
     OutputDebugString(L"\nWM_COPYDATA!");  
     PCOPYDATASTRUCT pcds = reinterpret_cast<PCOPYDATASTRUCT>(lParam);  
     auto string = (char*)pcds->lpData;  
      
     //.......  
      
     return 1;  
     }  
            case WM_CLOSE:  
                DestroyWindow(hwnd);  
            break;  
            case WM_DESTROY:  
                PostQuitMessage(0);  
            break;  
            default:  
                return DefWindowProc(hwnd, msg, wParam, lParam);  
        }  
        return 0;  
    }  
      
      
    int Main()  
    {  
        WNDCLASSEX wc;  
        HWND hwnd;  
        MSG Msg;  
      
        //Step 1: Registering the Window Class  
        wc.cbSize        = sizeof(WNDCLASSEX);  
        wc.style         = 0;  
        wc.lpfnWndProc   = WndProc;  
        wc.cbClsExtra    = 0;  
        wc.cbWndExtra    = 0;  
        wc.hInstance     = 0;  
        wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);  
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);  
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);  
        wc.lpszMenuName  = NULL;  
        wc.lpszClassName = L"myWindowClass";  
        wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);  
      
        if(!RegisterClassEx(&wc))  
        {  
            MessageBox(NULL, L"Window Registration Failed!", L"Error!",  
                MB_ICONEXCLAMATION | MB_OK);  
            return 0;  
        }  
      
     hwnd = CreateWindowEx(WS_EX_LEFT, // this is the default  
     L"myWindowClass",  // the name of the class, as passed to the RegisterClass function  
     NULL, //  Title  
     0,    //  dwFlags, in our case this really doesn't matter  
     0,    //  X   
     0,    //  Y   
     0,    //  W   
     0,    //  H   
     HWND_MESSAGE , //the most important flag! Creates a message-only window  
     0,    //  hMenu   
     0 ,   //  hInstance this function gets the instance handle of the current app  
     0     //  lpParam   
     );  
      
        if(hwnd == NULL)  
        {  
            MessageBox(NULL, L"Window Creation Failed!", L"Error!",  
                MB_ICONEXCLAMATION | MB_OK);  
            return 0;  
        }  
      
        ShowWindow(hwnd, SW_SHOW);  
        UpdateWindow(hwnd);  
      
        // Step 3: The Message Loop  
        while(GetMessage(&Msg, NULL, 0, 0) > 0)  
        {  
            TranslateMessage(&Msg);  
            DispatchMessage(&Msg);  
        }  
      
     return 0; // Msg.wParam;  
    }