2

我正在编写一个从 Component 派生的自定义控件。

在这个控件中,我需要能够以某种方式获取操作系统消息 WM_DEVICEDCHANGED 以从中创建一些事件。

通常我会直接在应用程序表单中覆盖 WndProc,但这个功能直接放在控件中是非常重要的。

即使控件将始终在窗体上使用,重要的是在从组件派生的控件上接收操作系统消息,因此当将控件放在窗体上时,无需在窗体中手动为其添加功能。

我已经看到一些提到 NativeWindow 和其他解决方案的示例,但是我无法在其中找到头部或尾部,所以我希望这里有人可以帮助我。

谢谢...

4

1 回答 1

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;
    }
}
于 2013-03-24T00:44:34.310 回答