.NET 中 ActiveX 控件的子类化窗口过程

Posted

技术标签:

【中文标题】.NET 中 ActiveX 控件的子类化窗口过程【英文标题】:Subclassing window procedure of an ActiveX control in .NET 【发布时间】:2011-05-05 15:18:18 【问题描述】:

我在我的应用程序中使用了 Flash ActiveX 控件。我想禁用它的右键菜单。由于控件没有为此提供 API,我想子类化窗口过程并拦截 WM_RBUTTONDOWN 消息。我在 Qt 下成功地做到了这一点,但我不知道如何在 C# 中做到这一点。

在我的 C++/Qt 实现中,我使用 SetWindowLong 来存储 activex 包装器的 this 指针,而该指针又具有存储原始窗口 proc 的字段。我将窗口过程设置为我的(再次使用SetWindowLong)以及我不想处理的任何消息,我使用CallWindowProc 将其传递给原始WNDPROC。

如何在 .NET 下做到这一点?

【问题讨论】:

【参考方案1】:

您可以在 C# 中以完全相同的方式执行此操作。您需要使用 P/Invoke 从托管代码调用非托管 Windows API。网上有很多文章介绍了如何使用 P/Invoke。

事实上,您可以使用NativeWindow 类以更简单的方式完成此操作,如here 所述。代码如下所示:

public class SubclassHWND : NativeWindow

   protected override void WndProc(ref Message m)
   
      // Perform whatever custom processing you must have for this message
      System.Diagnostics.Debug.WriteLine(m.ToString());
      // forward message to base WndProc
      base.WndProc(ref m);
   


SubclassHWND s = new SubclassHWND();
s.AssignHandle(theWindowHandle);
//Now s should be listening to the messages of the form.

另一种使用委托代替函数指针的方法是:Marshal.GetFunctionPointerForDelegate()

【讨论】:

我真的可以将 C# 方法传递给 SetWindowLong 吗? 是的,您可以这样做,而且这样做是例行公事。 我自己进行了一次网络搜索,发现实际上可以在没有 P/Invoke 的情况下以更简单的方式实现 - 请参阅编辑。 感谢您的回答。与此同时,我想出了如何实际将 C# 方法作为函数指针传递给 winapi,我将它添加到您对未来谷歌用户的回答中(如果您不介意:))。【参考方案2】:

虽然这是一个旧的,但我只是从这个链接中看到了这段代码,它非常有用。本质上,它是 ActiveX 控件本身的子类,并在此时禁用右键单击。

通过:http://www.codeproject.com/Articles/29102/How-To-Disable-FlashPlayer-AxShockwaveFlash-Right

public class IForcePlayer : AxShockwaveFlash

const int WM_RBUTTONDOWN = 0x0204;

protected override void WndProc(ref Message m)

    if (m.Msg == WM_RBUTTONDOWN)
    
        m.Result = IntPtr.Zero;
        return;
    
    base.WndProc(ref m);


【讨论】:

以上是关于.NET 中 ActiveX 控件的子类化窗口过程的主要内容,如果未能解决你的问题,请参考以下文章

activex 如何调用OnDraw函数

将静态控件子类化到对话框窗口

QT自定义控件消息实现

类中调用界面ActiveX控件报错当前线程不在单线程单元中因此无法实例化 ActiveX 控件的解决办法

不破坏复制/粘贴的子类编辑控件

当前线程不在单线程单元中,因此无法实例化 ActiveX 控件