日期:2014-05-17  浏览次数:21069 次

「控件控」自动完成菜单、代码提示、函数列表、文本纠错等IntelliSense功能
题目很响亮吧。

我明后天出门郊游,闪人前从cp弄点好文过来,大家一起赏析。

个人认为这篇文章用好了能让你的程序直接跨入「专业」水准。至少「看起来」,但这就够了。

来点背景介绍,本文是乌克兰人Pavel Torgashov发表在codeproject上的文章,获得了今年"Best C# Article of April"的prize winner。

我已经征得Pavel本人同意,把这篇翻译出来,大家一起研究。

© Written by Pavel Torgashov 2012, translated by 野比「Conmajia」 2012

自动完成菜单
[乌克兰]Pavel Torgashov著,野比译
自定义用于RichTextBox、TextBox和其他控件的自动完成菜单。

 点击阅读原文
 下载源代码 - 192.4KB
 下载DEMO - 22.9KB



简介
我们所有人都用过VisualStudio的自动完成菜单,也就是IntelliSense。它非常管用,不是吗?不幸的是,.NET框架并没有包含内置的自动完成菜单组件。本文制作的组件将填补这个空缺。
AutocompleteMenu允许你轻松地在你的窗体上任何 TextBox或是RichTextBox里加入下拉提示框功能。(就像上面图中演示的那样——野比注)

实现
该组件包含了数个类。下面是主要的类极其功能小结:
AutocompleteMenu - 包含基本功能的主要组件。它订阅TextBox的事件,查找合适的变体,显示一个下拉菜单,并将新的文字插入文本框。
下面是AutocompleteMenu的基本属性:
 * AllowTabKey - 允许使用TAB键选择菜单项
 * AppearInterval - 菜单显示的间隔(毫秒)
 * ImageList - 保存菜单项用到的图片
 * Items - 菜单项列表(AutocompleteMenu最简单的用法)
 * MaximumSize - 弹出菜单最大尺寸
 * MinFragmentLength - 菜单显示的最小片段长度。只有当光标处当前片段长度不低于MinFragmentLength才会显示AutocompleteMenu。
 * SearchPattern - 搜索光标处片段的正则表达式
AutocompleteMenuHost - 从ToolStripDropDown派生的可视化组件。该控件能让你在不丢失窗体焦点的情况下显示菜单。
AutocompleteListView - 从UserControl继承的可视化组件。使用GDI+绘制下拉菜单的菜单项。该控件和ListView很像,但能够高效地显示大量的元素。
AutocompleteItem - 菜单项。这个类包含了菜单项的所有必要信息。你可以从AutocompleteItem继承出你的元素,并覆盖其虚方法,这样来扩展菜单功能。下面是AutocompleteItem的基本属性:
 * Text - 要插入文本框的文本
 * MenuText - 显示在弹出菜单上的文本
 * ImageIndex - 菜单项的图片索引
 * ToolTipTitle - 工具提示标题。如果ToolTipTitle为null,则不会显示工具提示
 * ToolTipText - 工具提示文本
 * Tag - 你可在此附加任何数据
下面是一些你可以重写的方法:
 * GetTextForReplace - 返回要插入的文本。你可以动态修改要插入的文本。例如,你可以插入当前日期。
 * Compare - 这个方法定义了菜单项显示与否。默认情况下,只有菜单项以给定的片段开头,才会显示该项。但是你可以重写这个方法的行为。比如,你可以用子字符串来比较,或是进行一些模糊比较。
 * OnSelected - 这个方法会在文本插入文本框的时候调用。你可以在这里对文本进行一些额外的操作。比如,你可以把光标移动到某处。
控件库里还提供了几个从AutocompleteMenu派生的有用的类:SnippetAutocompleteItem(可以用于插入代码段),MethodAutocompleteItem(可以在点后面插入方法名称),SubstringAutocompleteItem(用子字符串来比较文本),MulticolumnAutocompleteItem(绘制多列菜单)。
使用源代码
简单用法:
1) 把AutocompleteMenu组件扔到你的窗体上
2) 在AutocompleteMenu.Items里输入菜单项
就像这样

3) 设置你的文本框的AutocompleteMenu属性
就像这样

4) 搞定收工


高级用法:
1) 把AutocompleteMenu组件扔到你的窗体上
2) 创建一个菜单项列表,用SetAutocompleteItems()或是AddItem()方法添加到菜单。比如:
C# code
string[] snippets = { "if(^)\n{\n}", "if(^)\n{\n}\nelse\n{\n}", "for(^;;)\n{\n}", "while(^)\n{\n}", "do${\n^}while();", "switch(^)\n{\n\tcase : break;\n}" };  
   
private void BuildAutocompleteMenu()  
{  
    var items = new List<AutocompleteItem>();  
   
    foreach (var item in snippets)  
        items.Add(new SnippetAutocompleteItem(item) { ImageIndex = 1 });  
   
    //设置为自动完成源  
    autocompleteMenu1.SetAutocompleteItems(items);  
}  

同样,你也可以添加自己的菜单项,就是从AutocompleteItem继承而来的那种。比如:
C# code
internal class EmailSnippet : AutocompleteItem  
{  
    public EmailSnippet(string email): base(email)  
    {  
        ImageIndex = 0;  
        ToolTipTitle = "Insert email:";  
        ToolTipText = email;  
    }  
   
    public override CompareResult Compare(string fragmentText)  
    {  
        if (fragmentText == Text)  
            return CompareResult.VisibleAndSelected;  
        if (fragmentText.Contains("@"))  
            return CompareResult.Visible;  
        return CompareResult.Hidden;  
    }  
}