WndProc 的替代方案,因为在从组件派生的类中需要?
Posted
技术标签:
【中文标题】WndProc 的替代方案,因为在从组件派生的类中需要?【英文标题】:Alternative to WndProc because needed in Class derived from Component? 【发布时间】:2013-03-13 11:36:21 【问题描述】:我正在编写一个从 Component 派生的自定义控件。
在此控件中,我需要能够以某种方式获取操作系统消息 WM_DEVICEDCHANGED 以从中创建一些事件。
通常我会直接在应用程序表单中覆盖 WndProc,但此功能直接位于控件中非常重要。
即使控件将始终在窗体上使用,重要的是在从组件派生的控件上接收操作系统消息,因此当将控件放到窗体上时,无需手动为其添加功能 IN表格。
我看到了一些提到 NativeWindow 和其他解决方案的例子,但我无法找到其中的头或尾,所以我希望这里有人可以帮助我。
谢谢...
【问题讨论】:
您需要更具体一些,完全不清楚子类化主机表单是否可以工作或需要创建单独的窗口。记录您想要完成的任务,并至少提及您想要接收的消息。 对不起。我以为我已经写过我想收到 WM_DEVICECHANGED 消息。我想在我的组件中接收消息,而不是在使用组件的表单中接收消息。不在表单上使用 WndProc。 我可能解释得不太好,但基本上我希望能够在我的组件中做 WndProc 在表单类中所做的事情。 【参考方案1】:我想收到 WM_DEVICECHANGED 消息
好的,这只需要子类化您放置组件的窗体的窗口。任何***窗口都会收到该消息。向您的项目添加一个新类并粘贴如下所示的代码。建造。将新组件从工具箱顶部拖放到表单上。为 DeviceChange 事件添加一个事件处理程序,并添加与您感兴趣的设备更改通知类型相关的任何代码。您还可以将该代码放在 OnDeviceChange() 方法中,以进一步专门化通知并引发更具体的事件。您可以从这里拿走它。
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
public class DeviceChangeNotifier : Component
public delegate void DeviceChangeDelegate(Message msg);
public event DeviceChangeDelegate DeviceChange;
public DeviceChangeNotifier()
// Add initialization here
public DeviceChangeNotifier(IContainer container) : this()
// In case you need automatic disposal
container.Add(this);
public DeviceChangeNotifier(ContainerControl parentControl) : this()
// In case you want to use it without the designer
this.ContainerControl = parentControl;
public ContainerControl ContainerControl
// References the parent form
get return this.parentControl;
set
this.parentControl = value;
this.parentControl.HandleCreated += parentControl_HandleCreated;
private void parentControl_HandleCreated(object sender, EventArgs e)
// Subclass the form when its handle is created
snooper = new MessageSnooper(this, parentControl.Handle);
protected void OnDeviceChange(Message msg)
// Raise the DeviceChange message
var handler = DeviceChange;
if (handler != null) handler(msg);
public override ISite Site
// Runs at design time, ensures designer initializes ContainerControl
// so we'll have a reference to the parent form without it having to do any work
set
base.Site = value;
if (value == null) return;
IDesignerHost service = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (service == null) return;
IComponent rootComponent = service.RootComponent;
this.ContainerControl = rootComponent as ContainerControl;
private ContainerControl parentControl;
private MessageSnooper snooper;
private const int WM_DESTROY = 0x0002;
private const int WM_DEVICECHANGE = 0x0219;
private class MessageSnooper : NativeWindow
// Subclasses the parent window
public MessageSnooper(DeviceChangeNotifier owner, IntPtr handle)
this.owner = owner;
this.AssignHandle(handle);
protected override void WndProc(ref Message m)
if (m.Msg == WM_DESTROY) this.ReleaseHandle();
if (m.Msg == WM_DEVICECHANGE) owner.OnDeviceChange(m);
base.WndProc(ref m);
private DeviceChangeNotifier owner;
【讨论】:
谢谢。这样可行。它当然创建了一个新组件,但我认为我可以在没有帮助的情况下将它集成到我自己的组件中。 :) 或者,您也许可以使用 msgwindow 样式(不记得实际值)沿着 pinvoke 的讨厌之路进入 CreateWindow,这也应该给您一个消息泵......跨度> @JerKimball 谢谢,但我得到了 Hans 的解决方案。唯一有点烦人的是 ContainerControl 显示为公共属性。没有办法解决这个问题? 好的,忘记我的最后一个问题。那些日子我是个僵尸……[Browsable(false)] 是答案当然:)以上是关于WndProc 的替代方案,因为在从组件派生的类中需要?的主要内容,如果未能解决你的问题,请参考以下文章
SQL SSIS 使用派生列转换来处理空数据.. 替代方案?