支持拼音首字母查询的ComboBox

时间:2023-01-28 07:56:53

功能:输入字母,自动筛选Items中对应拼音首字母的项目,如:bk,筛选“博客”,“边框”等。另外支持英文字母开头项目,支持自定义项目颜色。

 

拼音方案直接引用微软自家的类库,详见:http://www.microsoft.com/zh-cn/download/details.aspx?id=15251

类库支持获取简体中文字符的常用属性比如拼音,多音字,同音字,笔画数。

请下载并在项目中引用ChnCharInfo.dll

 

支持拼音首字母查询的ComboBox支持拼音首字母查询的ComboBoxView Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.ComponentModel;
using System.Collections;
using Microsoft.International.Converters.PinYinConverter;
using System.Windows.Forms;
using System.Drawing;

namespace CustomControlLibrary
{
    public class ComboBoxEx : System.Windows.Forms.ComboBox
    {
        /// <summary>
        /// 解决ComboBox的一个Bug,详见:
        /// https://connect.microsoft.com/VisualStudio/feedback/details/721868/combobox-throws-argumentoutofrangeexception-after-clearing-while-in-droppeddown-state
        /// </summary>
        public override int SelectedIndex
        {
            get
            {
                if (Items.Count > 0)
                    return base.SelectedIndex;
                else
                    return -1;
            }
            set
            {
                if (Items.Count > 0)
                {
                    base.SelectedIndex = value;
                }
            }
        }

        public ComboBoxEx()
        {
            Enter += new System.EventHandler(ComboBoxEx_Enter);
            Leave += new System.EventHandler(ComboBoxEx_Leave);
            TextUpdate += new System.EventHandler(ComboBoxEx_TextUpdate);

            DrawMode = DrawMode.OwnerDrawVariable;
            DrawItem += new DrawItemEventHandler(ComboBoxEx_DrawItem);
        }

        #region 自定义绘制每项的颜色
        private void ComboBoxEx_DrawItem(object sender, DrawItemEventArgs e)
        {
            ComboBox cb = (ComboBox)sender;
            if (e.Index != -1)
            {
                cb.DrawMode = DrawMode.OwnerDrawVariable;
                // Draw the background of the ListBox control for each item.
                e.DrawBackground();
                // Define the default color of the brush as black.
                Brush myBrush = Brushes.Black;

                // Determine the color of the brush to draw each item based on the index of the item to draw.
                //if (e.Index % 2 == 0)
                //{
                //    myBrush = Brushes.DarkSlateGray;
                //}
                // Draw background color for each item.
                //e.Graphics.FillRectangle(myBrush, e.Bounds);

                // Draw the current item text based on the current Font and the custom brush settings.
                e.Graphics.DrawString(cb.Items[e.Index].ToString(), e.Font, myBrush, e.Bounds, StringFormat.GenericDefault);
                // If the ListBox has focus, draw a focus rectangle around the selected item.
                e.DrawFocusRectangle();
            }
        }
        #endregion

        #region 支持拼音首字母查询

        private ArrayList lstItems = new ArrayList();

        /// <summary>
        /// 汉字转拼音首字母
        /// </summary>
        /// <param name="scrChar"></param>
        /// <returns></returns>
        public List<string> Chinese2Pinyin(char scrChar)
        {
            try
            {
                ChineseChar cnChar = new ChineseChar(scrChar);
                List<string> lstStr = new List<string>(cnChar.PinyinCount);
                for (int i = 0; i < cnChar.PinyinCount; i++)
                {
                    lstStr.Add(cnChar.Pinyins[i]);
                }
                return lstStr;
            }
            catch
            {
                return new List<string> { scrChar.ToString() };
            }
        }

        private void ComboBoxEx_Enter(object sender, EventArgs e)
        {
            ComboBox cb = (ComboBox)sender;
            lstItems.Clear();
            lstItems.AddRange(cb.Items);
        }

        private void ComboBoxEx_Leave(object sender, EventArgs e)
        {
            ComboBox cb = (ComboBox)sender;
            object obj = null;

            if (cb.Items.Count != 0)
                obj = cb.SelectedItem;

            cb.DataSource = null;
            cb.Items.Clear();
            //cb.Items.AddRange(this.lstTeam.ToArray());
            cb.DataSource = (ArrayList)lstItems.Clone();
            cb.SelectedItem = obj;
        }

        private void ComboBoxEx_TextUpdate(object sender, EventArgs e)
        {
            try
            {
                ComboBox cb = (ComboBox)sender;
                cb.DataSource = null;

                if (cb.Items.Count == 0)
                {
                    cb.SelectedIndex = -1;
                    cb.SelectedItem = null;
                }

                if (string.IsNullOrWhiteSpace(cb.Text))
                {
                    cb.Items.Clear();
                    cb.Items.AddRange(lstItems.ToArray());
                }
                else
                {
                    ArrayList lstCurItems = new ArrayList();

                    int count = cb.Text.Length - 1;
                    if (0 == count)
                        lstCurItems = lstItems;
                    else
                        lstCurItems.AddRange(cb.Items);

                    cb.Items.Clear();
                    foreach (object obj in lstCurItems)
                    {
                        if (count < obj.ToString().Length)
                        {
                            foreach (string item in Chinese2Pinyin(obj.ToString()[count]))
                            {
                                if (item.ToLower()[0] == cb.Text.ToLower()[count])
                                {
                                    cb.Items.Add(obj);
                                    break;
                                }
                            }
                        }
                    }
                }
                if (cb.Items.Count == 0)
                {
                    cb.SelectedIndex = -1;
                    cb.SelectedItem = null;
                    cb.Text = null;
                }
                cb.SelectionStart = cb.Text.Length;
                cb.DropDownHeight = 140;
                cb.DroppedDown = true;
                cb.Cursor = Cursors.Default;
            }
            catch (Exception)
            {
                throw;
            }
        } 

        #endregion
    }
}

 

P.S.

纯经验记录,方便大家!代码没技术含量,还有可改进的地方。