在 eMbedded VC++ 创建的 DLL 中子类化 C# 窗口
如何在 eMbedded VC++ 创建的 DLL 中捕获 C# 应用程序窗口消息。
引言
我正在开发一个 PDA(个人数字助理)应用程序时,其中一个要求是在 eMbedded VC++ 创建的 DLL 中子类化由 C# 应用程序创建的窗口。C# 应用程序加载 eMbedded VC++ 创建的 DLL 以执行录音功能。
解决方案
该 GUI 使用 C#(.NET Compact Framework)开发,而录音功能则使用 eMbedded VC++ 创建的 DLL。现在,波形音频输入设备将通知消息发送到指定的窗口,但问题是如何获取在 C# 应用程序中创建的窗口句柄,以便将其作为参数传递给 waveInOpen
函数?我们需要以某种方式将窗口句柄传递给 DLL,以便 DLL 可以子类化该窗口,并且消息可以在 DLL 本身中处理。
以下是解决上述问题的尝试。
首先,DLL 中实现的功能使用 C# 应用程序中的 DllImport
调用。您需要编写以下代码来访问从该 DLL(Recorder.dll)导出的函数。我将所有这些函数放在一个名为 Wrapper
的类中。
public class Wrapper
{
[DllImport("Recorder.dll", EntryPoint="StartRecording")]
static extern public bool StartRecording ();
[DllImport("Recorder.dll", EntryPoint="StopRecording")]
static extern public bool StopRecording ();
[DllImport("Recorder.dll", EntryPoint="StartPlaying")]
static extern public bool StartPlaying(string sFile);
[DllImport("Recorder.dll", EntryPoint="StopPlaying")]
static extern public bool StopPlaying ();
//Other functions
}
我在 DLL 中添加了另一个函数,它将接受 C# 窗口的窗口句柄。我在 C# 应用程序中导入了相同的函数。
[DllImport ("Recrdr.dll", EntryPoint="SetParentWnd")]
static extern public bool SetParentWnd (UInt32 hWnd);
现在,我需要将窗口句柄传递给此函数(**请注意**,this.Handle
在 .NET Compact Framework 中不受支持)。那么,我们该如何做?嗯,同样,我们需要调用 Windows API 来获取窗口句柄。为此,您需要导入 Windows DLL,coredll.dll,它实现了 GetForegroundWindow
函数。
操作方法如下。
[DllImport ("coredll.dll", EntryPoint="GetForegroundWindow")]
static extern public UInt32 GetForegroundWindow();
这再次添加到我之前提到的 Wrapper
类中。
从您的 C# 应用程序的表单加载函数调用此函数以获取前台窗口,并通过此句柄调用 Recrdr.dll 的 SetParentWnd
函数。
UInt32 unHandle = Wrapper.GetForegroundWindow ();
Wrapper.SetParentWnd (unHandle);
现在,在您的 eMbedded VC++ 代码中,添加以下代码行以捕获消息
LRESULT CALLBACK RecorderWndProc ( HWND hWnd, UINT unMessage, WPARAM wParam, LONG lParam )
{
switch (unMessage)
{
case <message>:
break;
default:
break;
}
return CallWindowProc ( g_lpfnWndProc, hWnd, unMessage, wParam, lParam );
// Call original window procedure
}
这是您的新窗口过程,您可以在其中捕获发送到 C# 窗口的任何消息。
每当调用 SetWindowHandle
函数时,都执行子类化。以下是相同的代码
bool CRecorder::SetWindowHandle(HWND hWnd) { if ( hWnd == NULL ) return false; m_hParentWnd = hWnd; // Do an instance subclassing so that you can trap messages here // and leave rest of the messages to the main window g_lpfnWndProc = (WNDPROC) SetWindowLong ( m_hParentWnd, GWL_WNDPROC, (LONG) RecorderWndProc ); if ( g_lpfnWndProc == NULL ) return false; return true; }