【问题标题】:Windows ComboBox Intercept WM_COMMAND NotificationsWindows ComboBox 拦截 WM_COMMAND 通知
【发布时间】:2014-10-08 20:21:33
【问题描述】:

更新以反映我的请求的更实用的描述。

从功能上讲,我需要一个不直接继承自 System.Windows.Forms.ComboBox 类的只读 ComboBox。我需要将文本框部分设为只读,以便用户可以复制输入框中的文本但不能更改它。这不是使用DropDownDropDownList 模式的情况。

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

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

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

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

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

如何拦截(并可能忽略)来自现有 ComboBox 控件的 WM_COMMAND 消息。具体来说,我希望在某些情况下忽略消息 273 链。有没有办法在功能上对“外部”ComboBox 控件执行相同的操作,而我可以从继承的控件中执行相同的操作?既然我有Handle 用于ComboBox,我可以使用SetWindowsHookEx() 之类的东西来拦截消息吗?

【问题讨论】:

  • 所以您不希望用户能够从下拉列表中选择新值?那为什么要使用组合,只需使用只读编辑控件。
  • 通过拦截 WM_COMMAND,您可以深入了解 WIN32 API。除非你真的知道自己在做什么,否则我不会玩这个游戏。相反,有一个属性DropDownStyle 可以防止在ComboBoxTextBox 部分中输入文本。如果您想要阻止用户通过键入来更改选择,请尝试通过KeyPressKeyDownKeyUp 或任何Key* 事件拦截事件,然后再深入播放。或者更简单,使用另一个控件,因为 ComboBox 实际上用于允许用户在多个选项中进行选择。
  • 因为当用户操作对象时,控件将切换进/出只读模式。该应用程序是数据库的前端,具有可以编辑的内容和时间的特定规则。当用户配置对象时,我使用下拉菜单提供现有值供他们选择。我希望它只读而不是禁用,以便他们可以选择并复制使用的值。
  • 实际上,我想描述您的功能需求会比您抛出的这些技术要求更准确。 ;) 请编辑您的问题,使其表达您的功能要求、您希望它做什么以及何时以及为什么。
  • @Will:我很喜欢在野兽中进行管道,之前做过(制作了一个动态填充的自动完成源)。这并不是说我只想将他们的选择限制在预先确定的范围内,我想防止他们改变,同时保留他们选择和复制现有值的能力。此功能适用的情况可能很少见,但是当您需要它时...

标签: .net winapi combobox hook krypton-toolkit


【解决方案1】:

所以我找到了一个解决方案,可以“插入”控件的命令消息并能够中断它们。它涉及使用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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 2012-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多