实现C#响应非托管C++的消息

来源:互联网 发布:大智慧期货软件 编辑:程序博客网 时间:2024/04/30 07:16

写了一个小程序,用钩子来监测窗口,当发现被测窗口后在C# (UI)做出响应。

 

众所周知,C++中交互是消息机制的,而消息机制依托于回调(CallBack)函数。C#中是事件(event),事件又依托于代理(delegate),所以要实现在C#中响应非托管C++的消息,只能从delegate下手了。

 

先写一个C++的回调:

typedef void(*CallFun)(LPTSTR title);

void FindOutWnd(CallFun f, LPTSTR s);

CallFun m_cfFun = NULL;

extern "C" __declspec(dllexport) void __stdcall SetActive(CallFun f);     //C#中调用这个函数来设置回调函数指针。

 

函数原型:

void FindOutWnd(CallFun f, LPTSTR s)

{

     f(s);

}

 

__declspec(dllexport) void __stdcall SetActive(CallFun f)

{

     m_cfFun = f;

}

 

在钩子函数中调用:

void CALLBACK WinCreateNotifyProc(HWINEVENTHOOK hEvent, DWORD event,

                                       HWND hwndMsg, LONG idObject,

                                       LONG idChild, DWORD idThread, DWORD dwmsEventTime)

{

     if( event != EVENT_OBJECT_NAMECHANGE /*&& event != EVENT_OBJECT_CREATE*/)

          return;

     TCHAR strName[STR_SIZE];

 

     IAccessible *pacc = NULL;

     VARIANT varChild;

     VariantInit(&varChild);

 

     HRESULT hr = AccessibleObjectFromEvent(hwndMsg, idObject, idChild, &pacc, &varChild);

     if(!SUCCEEDED(hr))

     {

         VariantClear(&varChild);

         return;

     }

 

     GetObjectName(pacc, &varChild, strName, STR_SIZE);

     if(_tcsstr(strName, _T("***")))      //Your window’s name.

{

         if(m_actFun)

              FindOutWnd(m_cfFun, strName);

}

}

 

C#的代码:

[DllImport("WinEngine.dll", ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]

        public static extern void SetActive(DelegateFind f);

 

        public delegate void DelegateFind([MarshalAs(UnmanagedType.LPWStr)] StringBuilder sb);

        public static void OnFind(StringBuilder sb)

        {

            MessageBox.Show("Call Back Test:" + sb.ToString());

        }

 

        static DelegateFind find = new DelegateFind(OnFind);

 

别忘了:调用SetActive()将代理与回调关联。

SetActive(find); 

 

最后别忘了统一一下C#C++的调用方式,C#默认是stdcallC++默认是cdecl方式。