Windows ComboBox拦截WM_COMMAND通知

时间:2014-10-08 20:21:33

标签: .net winapi combobox hook krypton-toolkit

更新以反映我的请求的更多功能描述。

从功能上讲,我需要一个不会直接从ComboBox类继承的只读System.Windows.Forms.ComboBox。我需要文本框部分是只读的,因此用户可以复制输入到框中的文本但不能更改它。这不是使用DropDown vs DropDownList模式的情况。

使用此article和一些实验,我已经处理了文本框部分,但仍需要防止由于下面列出的技术原因而对下拉组件进行更改。我仍然需要以下其中一项:

  1. 禁用ComboBox上的下拉按钮 - 以防止其打开
  2. 防止在点击ComboBox时打开下拉列表
  3. 防止从下拉列表中选择项目以更改控件中的选择(可能通过拦截和忽略点击的项目通知消息)

  4. 我在我的应用程序中使用KryptonToolkit来获得视觉上的美观。对于KryptonComboBox控件,它有一个内部的,扩展的System.Windows.Forms.ComboBox类来拦截绘制调用。它公开了对ComboBox对象的访问权限,因此我可以访问它Handle

    我使用A Complete Read Only ComboBox代码作为基础来创建KryptonComboBox的只读版本。您必须使用KryptonComboBox.Handle来获取Windows控件的实际句柄,而不是在SendMessage()调用中使用KryptonComboBox.ComboBox.Handle。通过这样做,我能够正确地在ComboBox的文本框部分设置只读模式。

    BUT!由于扩展控件的基类是KryptonComboBox而不是ComboBox,因此当WndProc()被调用时,它是KryptonComboBox的消息。因此,当处于只读模式时,我无法阻止控件对所单击的下拉项执行操作(更改选择)。

    如何拦截(并可能忽略)来自现有ComboBox控件的WM_COMMAND消息。具体来说,我希望在某些情况下忽略一条消息273链。有没有办法在函数上对一个“外部”ComboBox控件做同样的事情,我可以从一个继承的控件?由于我HandleComboBox,我可以使用SetWindowsHookEx()之类的内容拦截邮件吗?

1 个答案:

答案 0 :(得分:0)

所以我找到了一个解决方案,用于“插入”控件的命令消息并能够中断它们。它涉及使用System.Windows.Forms.NativeWindow类来创建ComboBox的监听器,这是(根据我的理解)称为子类。

听众类:

private class ComboBoxListener : NativeWindow, IDisposable {
    private ComboBox m_oComboBox;

    private EventHandler m_oComboBox_HandleCreated;
    private EventHandler m_oComboBox_HandleDestroyed;

    public ComboBoxListener(ComboBox oComboBox) {
        // Save the combobox and assign the handle if it's already created
        m_oComboBox = oComboBox;
        if (m_oComboBox.IsHandleCreated) {
            AssignHandle(m_oComboBox.Handle);
        }

        // Subscribe to the handle events of the combobox
        m_oComboBox.HandleCreated += m_oComboBox_HandleCreated = new EventHandler(ComboBox_HandleCreated);
        m_oComboBox.HandleDestroyed += m_oComboBox_HandleDestroyed = new EventHandler(ComboBox_HandleDestroyed);
    }

    ~ComboBoxListener() {
        Dispose(false);
    }

    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool bDisposing) {
        if (bDisposing && (m_oComboBox != null) && !m_oComboBox.IsDisposed) {
            // Unsubscribe from the combo box
            m_oComboBox.HandleCreated -= m_oComboBox_HandleCreated;
            m_oComboBox.HandleDestroyed -= m_oComboBox_HandleDestroyed;
        }
        m_oComboBox = null;

        // If a handle is currently assigned, release it
        if (this.Handle != IntPtr.Zero) {
            ReleaseHandle();
        }
    }

    private void ComboBox_HandleCreated(object sender, EventArgs e) {
        AssignHandle(m_oComboBox.Handle);
    }

    private void ComboBox_HandleDestroyed(object sender, EventArgs e) {
        ReleaseHandle();
    }

    protected override void WndProc(ref Message m) {
        // Do checks for whether to ignore the message
        // If ignoring, just call return and skip the base.WndProc(ref m) call
        base.WndProc(ref m);
    }
}

然后在KryptonComboBox的派生类的构造函数中,我添加了:

m_oComboBoxListener = new ComboBoxListener(this);

并在被覆盖的Dispose(bool disposing)

中添加了清理工作
// Dispose the listener
if (disposing && (m_oComboBoxListener != null)) {
    m_oComboBoxListener.Dispose();
}
m_oComboBoxListener = null;