读取从c ++发送到C#的lParam作为字符串

时间:2015-08-29 21:23:47

标签: c# c++ interop marshalling

我有一个c ++应用程序,它使用SendNotifyMessage CB_FINDSTRINGEXACT 重定向到C#代码。现在,我想将其更改为 WM_COPYDATA ,但我无法使其正常工作。

C ++代码:

static LRESULT CALLBACK GetMsgHookCallback(int code, WPARAM wparam, LPARAM lparam){
if (code >= 0)
{
    UINT msg = 0;
    UINT msg2 = 0;

    msg = RegisterWindowMessage("WILSON_HOOK_GETMSG");
    msg2 = RegisterWindowMessage("WILSON_HOOK_GETMSG_PARAMS");

    HWND dstWnd = (HWND)GetProp(GetDesktopWindow(), "WILSON_HOOK_HWND_GETMSG");

    MSG* pMsg = (MSG*)lparam;

    if (msg != 0 && pMsg->message != msg && pMsg->message != msg2)
    {
        if (pMsg->message == CB_ADDSTRING)
        {
            SendNotifyMessage(dstWnd, msg, (WPARAM)pMsg->hwnd, pMsg->message);
            SendNotifyMessage(dstWnd, msg2, pMsg->wParam, pMsg->lParam); //plus more code...

现在,由于我的目的是阅读pMsg->lParam中的字符串而我无法使其从c#侧*开始工作,我试图以这种方式使用WM_COPYDATA:

                SendNotifyMessage(dstWnd, msg, (WPARAM)pMsg->hwnd, pMsg->message);
            SendNotifyMessage(dstWnd, msg2, pMsg->wParam, pMsg->lParam);

            // Added code
            CString *message = (CString*)pMsg->lParam;
            COPYDATASTRUCT cpd;
            cpd.dwData = 0;
            cpd.cbData = message->GetLength();
            cpd.lpData = (void*)message->GetBuffer(cpd.cbData);
            ::SendMessage(dstWnd, WM_COPYDATA, (WPARAM)pMsg->hwnd, (LPARAM)&cpd);
            SendNotifyMessage(dstWnd, WM_COPYDATA, (WPARAM)pMsg->hwnd, (LPARAM)&cpd);

但是,我从未在c#application *中收到任何 WM_COPYDATA

这是C#部分:

        int CB_FINDSTRINGEXACT = 0x0158;
    public const Int32 WM_COPYDATA = 0x4A;
    private void test(IntPtr Handle, IntPtr Message, IntPtr wParam, IntPtr lParam)
    {

        if (Message.ToInt32() == CB_FINDSTRINGEXACT)
        {
            String one = Marshal.PtrToStringAuto(lParam); // This gives accessviolationexception
            String dos = Marshal.PtrToStringAnsi(lParam);   // returns empty string
            Console.WriteLine("SOMETHING RECEIVED: "+one+". dos: "+dos+". tres: "+lParam.ToString()); // last part is only an intptr
        }
        if (Message.ToInt32() == WM_COPYDATA) // never true
            Console.WriteLine("COPYDATA: ");
    }

我已经尝试了很多解决方案,但我似乎都没有。如何在c#函数中从c ++中读取lParam(真的是一个String)?我想得到这个字符串。

EDIT1:

我尝试了几种方法让WM_COPYDATA正常工作,但没有成功。他们在这里:

                    // Test 1: c# never receives anything
                COPYDATASTRUCT* copy_data = (COPYDATASTRUCT*)(pCwpStruct->lParam);
                SendMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)&copy_data);
                SendNotifyMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)&copy_data);

                // Test 2: c# never receives anything
                LPCTSTR lpszString = (LPCTSTR)pCwpStruct->lParam;
                COPYDATASTRUCT cds;
                cds.dwData = 0;
                cds.cbData = sizeof(TCHAR)* (_tcslen(lpszString) + 1);
                cds.lpData = (PVOID)lpszString;
                SendMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)(LPVOID)&cds);
                SendNotifyMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)&cds);

1 个答案:

答案 0 :(得分:0)

有许多更正的评论,但它消失了,不知道为什么。我遵循了一些建议并解决了它。这是最终的代码:

C ++:

                LPCTSTR lpszString = (LPCTSTR)pCwpStruct->lParam;
                COPYDATASTRUCT cds;
                cds.dwData = 0;
                cds.cbData = sizeof(TCHAR)* (_tcslen(lpszString) + 1);
                cds.lpData = (PVOID)lpszString;
                SendMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)(LPVOID)&cds);

请注意,我已将 SendNotifyMessage 更改为 SendMessage 。这是我能让它发挥作用的唯一方式。

在c#应用程序中:

public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
        {

            if (m.Msg == WM_COPYDATA)
            {
                COPYDATASTRUCT cds;
                cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));

                if (cds.cbData > 0)
                {
                    byte[] data = new byte[cds.cbData];
                    Marshal.Copy(cds.lpData, data, 0, cds.cbData);
                    System.Text.Encoding unicodeStr = System.Text.Encoding.ASCII;
                    char[] myString = unicodeStr.GetChars(data);
                    string returnText = new string(myString);   // Here is the info
                }
                ...