无奈接收到一个C++写的Windows动态库,该动态库是基于MFC的框架写的,偏偏原作者当年痴迷于Windows下的消息机制。所以该动态库的初始化接口中需要传递一个窗口句柄,用于动态库方便上传消息。
而现在我需要写一个Windows服务程序,为了方便开发,当时选用的就是C#。原本C#调用C++动态库,就只要考虑一下接口文件的数据类型就好了,现在要考虑的问题就比较复杂了。
首先,我们假设初始化接口的如下所示:
int WINAPI InitDll(HWND hwnd);
像这种句柄的参数,问题不大,因为说白了就是一个指针,在C#中我们可以用Intptr这个数据类型就可以搞定,更何况,在C#的窗口句柄类型本来就是Intptr。
public static extern int InitDll(IntPtr hwnd);
然后,我们需要在我们的项目中添加一个窗口,这个就和我们写桌面的C#程序一样添加。同时为了消息接收,需要重写消息接收方法。如果需要主程序去处理消息,那就做一个委托函数就好了,这里就不赘述。
public partial class HandleMsg : Form
{
public HandleMsg()
{
InitializeComponent();
}
// 消息接收方法重写
protected override void WndProc(ref Message e)
{
// 消息接收 并且处理你想做的事
}
}
接下来,我们就需要把这个窗口运行起来就好了(重点)。既然消息是异步的,那么窗口就必须运行在一个窗口线程,就我目前水平来讲的话,我还不知道如何自己去创建一个窗口线程,并且还不阻塞主线程。那我们可以参考一下正常的C#窗口程序的起始代码
// C#窗口程序的起始代码
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
仿照如上代码,我们可以在程序初始化的时候,创建一个线程,去运行如上的代码,就既可以不阻塞主线程,又可以运行窗口线程
// 创建窗口线程,并运行
Task.Factory.StartNew(() =>
{
handleMsg = new HandleDevMsg();
Application.Run(handleMsg);
}
);
while (handleMsg == null)
{
Thread.Sleep(50);
}
int nRet = InitDll(handleMsg.Handle);