区分单击下拉列表三角形和单击其他任何位置的组合框

Posted

技术标签:

【中文标题】区分单击下拉列表三角形和单击其他任何位置的组合框【英文标题】:Distinguish between clicking the drop-down list triangle and clicking the ComboBox anywhere else 【发布时间】:2021-07-30 13:06:46 【问题描述】:

如何以编程方式区分用户单击下拉三角形(按钮)还是单击 ComboBox 上的其他任何位置? 我正在使用 Visual Studio 2010 而不是 excel。我使用的 ComboBox 没有建议的答案中提到的事件和成员:ComboDropDown、CellClick 和 GetCellRect()。 我有一个带有组合框的应用程序。我必须能够区分用户单击 ComboBox 按钮(以打开下拉列表)和用户单击显示的项目或下拉列表中的项目。

【问题讨论】:

你能说得更具体点吗?你追求什么?您想知道下拉列表何时显示吗? @Jimi 我有一个带有组合框的应用程序。我必须能够区分用户点击组合框按钮(为了打开下拉列表和用户点击显示的项目或下拉列表中的项目。 这是一个非常特殊的要求。你通常不需要知道这些,ComboBox 的标准操作不是基于这些细节。你应该解释你想要达到的目标——为什么你认为你需要这个:可能有一种不同的方式不会强迫你无缘无故地使用 NativeWindow 对象或 P/Invoking。 【参考方案1】:

我问这个问题是因为我不熟悉 ComboBox 事件,我想要一个快速简单的方法。 在看到没有答案后,我决定更彻底地调查这些 ComboBox 事件并尝试自己回答我的问题。 结果如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace ComboBoxClickEvents

    public partial class Form1 : Form
    
        public Form1()
        
            InitializeComponent();

            this.ClientSize = new Size(833, 650);

            _allFiredEvents = new ObservableCollection<string>();

            InitializeComboBox();
            PopulateComboBox();
            InitializeTextBox();
            PopulateAllCorrespondingEventsNamesByUserClickAction();
            PopulateUserActionByAllCorrespondingEventsNames();
            _allEventsSequences = _userClickActionByAllCorrespondingEventsNames.Keys.ToList();
        
            _allFiredEvents.CollectionChanged += new NotifyCollectionChangedEventHandler(delegate(object sender, NotifyCollectionChangedEventArgs e)
            
                if (e.Action == NotifyCollectionChangedAction.Add)
                
                    List<HashSet<string>> allHashSets = _userClickActionByAllCorrespondingEventsNames.Keys.ToList();
                    HashSet<string> currentSequenceOfEventsNames = new HashSet<string>(); // Contains the names of all the events that fired as a result of a user click action.
                    for (int i = 0; i < _allFiredEvents.Count; i++)
                    
                        string currentEventName = _allFiredEvents[i];
                        currentSequenceOfEventsNames.Add(currentEventName);
                    
                    HashSet<string> identicalSequenceOfEventsNames = FindHashSetWithTheSameItemsInListOfHashSets(allHashSets, currentSequenceOfEventsNames);
                    if (identicalSequenceOfEventsNames != null)
                    
                        string userClickAction = _userClickActionByAllCorrespondingEventsNames[identicalSequenceOfEventsNames];
                        int position = userClickAction.IndexOf(" or ");
                        if (position >= 0)
                        
                            if (comboBox1.Text == "")
                            
                                userClickAction = userClickAction.Substring(position + 4);
                            
                            else
                            
                                userClickAction = userClickAction.Substring(0, position);
                            
                        
                        userClickAction = "*****" + userClickAction;
                        textBox1.AppendText(userClickAction + Environment.NewLine);
                        _allFiredEvents.Clear();
                    
                
            
            );
            InitializeButtonExit();
        

        private ComboBox comboBox1;
        private Button buttonExit;
        private List<HashSet<string>> _allEventsSequences;
        private static ObservableCollection<string> _allFiredEvents;
        private static Dictionary<string, HashSet<string>> _allCorrespondingEventsNamesByUserClickAction;
        private static Dictionary<HashSet<string>, string> _userClickActionByAllCorrespondingEventsNames;
        TextBox textBox1;

        private void InitializeComboBox()
        
            comboBox1 = new ComboBox();
            comboBox1.Location = new Point(20, 20);
            comboBox1.MouseDown += new MouseEventHandler(ComboBox1_MouseDown);
            comboBox1.Click += new EventHandler(ComboBox1_Click);
            comboBox1.MouseClick += new MouseEventHandler(ComboBox1_MouseClick);
            comboBox1.MouseUp += new MouseEventHandler(ComboBox1_MouseUp);
            comboBox1.DropDown += new EventHandler(ComboBox1_DropDown);
            comboBox1.SelectionChangeCommitted += new EventHandler(ComboBox1_SelectionChangeCommitted);
            comboBox1.DropDownClosed += new EventHandler(ComboBox1_DropDownClosed);
            comboBox1.SelectedValueChanged += new EventHandler(ComboBox1_SelectedValueChanged);
            comboBox1.SelectedIndexChanged += new EventHandler(ComboBox1_SelectedIndexChanged);
            comboBox1.TextChanged += new EventHandler(ComboBox1_TextChanged);
            this.Controls.Add(comboBox1);
        

        private void PopulateComboBox()
        
            comboBox1.Items.Add("First Item");
            comboBox1.Items.Add("Second Item");
            comboBox1.Items.Add("Third Item");
            comboBox1.Items.Add("Fourth Item");
            comboBox1.Items.Add("Fifth Item");
        

        private HashSet<string> FindHashSetWithTheSameItemsInListOfHashSets(List<HashSet<string>> allHashSets, HashSet<string> soughtHashSet)
        
            HashSet<string> currentHashSet = null;
            bool hashSetWithTheSameNumberOfItemsFound = false;
            bool identicalHashSetFound = false;
            int hashSetsCounter = 0;
            while (hashSetsCounter < allHashSets.Count && !identicalHashSetFound)
            
                do
                
                    currentHashSet = allHashSets[hashSetsCounter];
                    if (currentHashSet.Count != soughtHashSet.Count)
                    
                        hashSetsCounter++;
                    
                    else
                    
                        hashSetWithTheSameNumberOfItemsFound = true;
                    
                
                while (hashSetsCounter < allHashSets.Count && currentHashSet.Count != soughtHashSet.Count);
                bool discrepancyFound = false;
                int itemsCounter = 0;
                if (hashSetWithTheSameNumberOfItemsFound)
                
                    itemsCounter = 0;
                    foreach (string item in currentHashSet)
                    
                        if (soughtHashSet.Contains(item))
                        
                            itemsCounter++;
                        
                        else
                        
                            discrepancyFound = true;
                            break;
                        
                    
                
                if (hashSetWithTheSameNumberOfItemsFound && !discrepancyFound)
                
                    identicalHashSetFound = true;
                
                else
                
                    hashSetsCounter++;
                
            
            if (!identicalHashSetFound)
            
                currentHashSet = null;
            

            return currentHashSet;
        
    
        private void PopulateAllCorrespondingEventsNamesByUserClickAction()
        
            _allCorrespondingEventsNamesByUserClickAction = new Dictionary<string, HashSet<string>>();
            HashSet<string> allCorrespondingEventsNames = new HashSet<string>();
            allCorrespondingEventsNames.Add("ComboBox1_MouseDown");
            allCorrespondingEventsNames.Add("ComboBox1_Click");
            allCorrespondingEventsNames.Add("ComboBox1_MouseClick");
            allCorrespondingEventsNames.Add("ComboBox1_MouseUp");
            _allCorrespondingEventsNamesByUserClickAction.Add("Default Item Clicked In The TextBox or The Empty TextBox Is Clicked", allCorrespondingEventsNames);

            allCorrespondingEventsNames = new HashSet<string>();
            allCorrespondingEventsNames.Add("ComboBox1_DropDown");
            allCorrespondingEventsNames.Add("ComboBox1_MouseDown");
            allCorrespondingEventsNames.Add("ComboBox1_Click");
            allCorrespondingEventsNames.Add("ComboBox1_MouseClick");
            allCorrespondingEventsNames.Add("ComboBox1_MouseUp");
            _allCorrespondingEventsNamesByUserClickAction.Add("Drop-Down Button Clicked", allCorrespondingEventsNames);

            allCorrespondingEventsNames = new HashSet<string>();
            allCorrespondingEventsNames.Add("ComboBox1_MouseDown");
            allCorrespondingEventsNames.Add("ComboBox1_Click");
            allCorrespondingEventsNames.Add("ComboBox1_MouseClick");
            allCorrespondingEventsNames.Add("ComboBox1_MouseUp");
            allCorrespondingEventsNames.Add("ComboBox1_SelectionChangeCommitted");
            allCorrespondingEventsNames.Add("ComboBox1_DropDownClosed");
            allCorrespondingEventsNames.Add("ComboBox1_SelectedValueChanged");
            allCorrespondingEventsNames.Add("ComboBox1_SelectedIndexChanged");
            _allCorrespondingEventsNamesByUserClickAction.Add("Default Item Is Clicked In The Drop-Down List, when the Drop-Down List was already open", allCorrespondingEventsNames);

            allCorrespondingEventsNames = new HashSet<string>();
            allCorrespondingEventsNames.Add("ComboBox1_SelectionChangeCommitted");
            allCorrespondingEventsNames.Add("ComboBox1_DropDownClosed");
            allCorrespondingEventsNames.Add("ComboBox1_SelectedValueChanged");
            allCorrespondingEventsNames.Add("ComboBox1_SelectedIndexChanged");
            _allCorrespondingEventsNamesByUserClickAction.Add("Default Item Is Clicked In The Drop-Down List immediately after clicking the Drop-Down Button", allCorrespondingEventsNames);

            allCorrespondingEventsNames = new HashSet<string>();
            allCorrespondingEventsNames.Add("ComboBox1_MouseDown");
            allCorrespondingEventsNames.Add("ComboBox1_Click");
            allCorrespondingEventsNames.Add("ComboBox1_MouseClick");
            allCorrespondingEventsNames.Add("ComboBox1_MouseUp");
            allCorrespondingEventsNames.Add("ComboBox1_SelectionChangeCommitted");
            allCorrespondingEventsNames.Add("ComboBox1_DropDownClosed");
            allCorrespondingEventsNames.Add("ComboBox1_TextChanged");
            allCorrespondingEventsNames.Add("ComboBox1_SelectedValueChanged");
            allCorrespondingEventsNames.Add("ComboBox1_SelectedIndexChanged");
            _allCorrespondingEventsNamesByUserClickAction.Add("An Item (Not The Default Item) Is Clicked In The Drop-Down List, when the Drop-Down List was already open", allCorrespondingEventsNames);

            allCorrespondingEventsNames = new HashSet<string>();
            allCorrespondingEventsNames.Add("ComboBox1_SelectionChangeCommitted");
            allCorrespondingEventsNames.Add("ComboBox1_DropDownClosed");
            allCorrespondingEventsNames.Add("ComboBox1_TextChanged");
            allCorrespondingEventsNames.Add("ComboBox1_SelectedValueChanged");
            allCorrespondingEventsNames.Add("ComboBox1_SelectedIndexChanged");
            _allCorrespondingEventsNamesByUserClickAction.Add("An Item (Not The Default Item) Is Clicked In The Drop-Down List immediately after clicking the Drop-Down Button", allCorrespondingEventsNames);
        

        private void PopulateUserActionByAllCorrespondingEventsNames()
        
            _userClickActionByAllCorrespondingEventsNames = new Dictionary<HashSet<string>, string>();
            HashSet<string> allCorrespondingEventsNames = _allCorrespondingEventsNamesByUserClickAction["Default Item Clicked In The TextBox or The Empty TextBox Is Clicked"];
         

_userClickActionByAllCorrespondingEventsNames.Add(allCorrespondingEventsNames, "在文本框中单击默认项或单击空文本框");

            allCorrespondingEventsNames = _allCorrespondingEventsNamesByUserClickAction["Drop-Down Button Clicked"];
         

_userClickActionByAllCorrespondingEventsNames.Add(allCorrespondingEventsNames, "Drop-Down Button Clicked");

            allCorrespondingEventsNames = _allCorrespondingEventsNamesByUserClickAction["Default Item Is Clicked In The Drop-Down List, when the Drop-Down List was already open"];
         

_userClickActionByAllCorrespondingEventsNames.Add(allCorrespondingEventsNames, "当下拉列表已打开时,单击下拉列表中的默认项目");

            allCorrespondingEventsNames = _allCorrespondingEventsNamesByUserClickAction["Default Item Is Clicked In The Drop-Down List immediately after clicking the Drop-Down Button"];
         

_userClickActionByAllCorrespondingEventsNames.Add(allCorrespondingEventsNames, "单击下拉按钮后立即在下拉列表中单击默认项");

            allCorrespondingEventsNames = _allCorrespondingEventsNamesByUserClickAction["An Item (Not The Default Item) Is Clicked In The Drop-Down List, when the Drop-Down List was already open"];
         

_userClickActionByAllCorrespondingEventsNames.Add(allCorrespondingEventsNames, "当下拉列表已打开时,单击下拉列表中的项目(不是默认项目)");

            allCorrespondingEventsNames = _allCorrespondingEventsNamesByUserClickAction["An Item (Not The Default Item) Is Clicked In The Drop-Down List immediately after clicking the Drop-Down Button"];
         

_userClickActionByAllCorrespondingEventsNames.Add(allCorrespondingEventsNames, "单击下拉按钮后立即在下拉列表中单击一个项目(不是默认项目)");

        private void InitializeTextBox()
        
            textBox1 = new TextBox();
            textBox1.Location = new Point(comboBox1.Location.X + comboBox1.Width + 20, 20);
            textBox1.Name = "textBox1";
            textBox1.Multiline = true;
            textBox1.ScrollBars = ScrollBars.Vertical;
            textBox1.Size = new Size(650, 530);
            this.Controls.Add(textBox1);
        

        private void InitializeButtonExit()
        
            buttonExit = new Button();
            buttonExit.Name = "buttonExit";
            buttonExit.Text = "Exit";
            buttonExit.Size = new Size(85, 32);
            buttonExit.Location = new Point((this.ClientSize.Width - buttonExit.Width) / 2, this.ClientSize.Height - buttonExit.Height - 20);
            buttonExit.Click += new EventHandler(ButtonExit_Click);
            this.Controls.Add(buttonExit);
        
    
        private void ComboBox1_MouseDown(object sender, MouseEventArgs e)
        
            string eventName = "ComboBox1_MouseDown";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        
    
        private void ComboBox1_Click(object sender, EventArgs e)
        
            string eventName = "ComboBox1_Click";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        
    
        private void ComboBox1_MouseClick(object sender, MouseEventArgs e)
        
            string eventName = "ComboBox1_MouseClick";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        

        private void ComboBox1_MouseUp(object sender, MouseEventArgs e)
        
            string eventName = "ComboBox1_MouseUp";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        

        private void ComboBox1_DropDown(object sender, EventArgs e)
        
            string eventName = "ComboBox1_DropDown";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        

        private void ComboBox1_SelectionChangeCommitted(object sender, EventArgs e)
        
            string eventName = "ComboBox1_SelectionChangeCommitted";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        

        private void ComboBox1_DropDownClosed(object sender, EventArgs e)
        
            string eventName = "ComboBox1_DropDownClosed";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        

        private void ComboBox1_SelectedValueChanged(object sender, EventArgs e)
        
            string eventName = "ComboBox1_SelectedValueChanged";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        

        private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        
            string eventName = "ComboBox1_SelectedIndexChanged";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        

        private void ComboBox1_TextChanged(object sender, EventArgs e)
        
            string eventName = "ComboBox1_TextChanged";
            _allFiredEvents.Add(eventName);
            textBox1.AppendText(eventName + Environment.NewLine);
        

        private void ButtonExit_Click(object sender, EventArgs e)
        
            this.Close();
        
    

【讨论】:

以上是关于区分单击下拉列表三角形和单击其他任何位置的组合框的主要内容,如果未能解决你的问题,请参考以下文章

ExtJS组合框无法渲染

extjs 组合框在单击时显示空白列表

如果单击 DOM 中的任何位置,则隐藏 div

选择/打开新下拉列表时自动关闭下拉列表(React)

单击任意位置时如何关闭下拉列表

ExtJS 组合框不呈现