I am working on a Windows-only Qt application, and I need to receive data from a Microsoft OneNote plugin. The plugin is written in C#, and can send WM_COPYDATA messages. How do I receive these messages in a C++ Qt app?
I need to:
This can all be handled within Qt:
Extend QWidget with a class that will capture the WM_COPYDATA messages:
    class EventReceiverWindow : public QWidget
{
    Q_OBJECT
public:
    EventReceiverWindow();
signals:
    void eventData(const QString & data);
private:
    bool winEvent ( MSG * message, long * result );
};
Generate a GUID to set as the QWidget's windowTitle:
EventReceiverWindow::EventReceiverWindow()
{
    setWindowTitle("ProjectName-3F2504E0-4F89-11D3-9A0C-0305E82C3301::EventReceiver");
}
Override winEvent to handle the WM_COPYDATA structure and emit a signal when you get it:
bool EventReceiverWindow::winEvent ( MSG * message, long * result )
{
        if( message->message == WM_COPYDATA ) {
            // extract the string from lParam
            COPYDATASTRUCT * data = (COPYDATASTRUCT *) message->lParam;
            emit eventData(QString::fromAscii((const char *)data->lpData, data->cbData));
            // keep the event from qt
            *result = 0;
            return true;
        }
        // give the event to qt
        return false;
}
In another class, you can use this class to receive the message strings:
EventReceiverWindow * eventWindow = new EventReceiverWindow;
QObject::connect(eventWindow, SIGNAL(eventData(const QString &)), this, SLOT(handleEventData(const QString &)));
...
void OneNoteInterface::handleEventData(const QString &data)
{
    qDebug() << "message from our secret agent: " << data;
}
And in the program that is sending the messages, simply find the window by the unique window caption. Here's an example in C#:
private struct COPYDATASTRUCT
{
    public IntPtr dwData;
    public int cbData;
    [MarshalAs(UnmanagedType.LPStr)]
    public string lpData;
}
private const int WM_COPYDATA = 0x4A;
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
private void sendMessageTo(IntPtr hWnd, String msg)
{
    int wParam = 0;
    int result = 0;
    if (hWnd != IntPtr.Zero )
    {
        byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);
        int len = sarr.Length;
        COPYDATASTRUCT cds;
        cds.dwData = IntPtr.Zero;
        cds.lpData = msg;
        cds.cbData = len + 1;
        result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
    }
}
then you can:
IntPtr hwnd = FindWindowByCaption(IntPtr.zero, "ProjectName-3F2504E0-4F89-11D3-9A0C-0305E82C3301::EventReceiver");
sendMessageTo(hwnd, "omg hai");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With