65.9K
CodeProject 正在变化。 阅读更多。
Home

在 eMbedded VC++ 创建的 DLL 中子类化 C# 窗口

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (2投票s)

2007年6月25日

CPOL

2分钟阅读

viewsIcon

23156

如何在 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.dllSetParentWnd 函数。

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;
}
© . All rights reserved.