`
isiqi
  • 浏览: 16028942 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

「2012·4月号」自动完成菜单

 
阅读更多

自动完成菜单

[乌克兰]Pavel Torgashov著,野比译

自定义用于RichTextBox、TextBox和其他控件的自动完成菜单。


codeproject.com「2012四月最佳C#文章」获奖作品


击阅读原文

下载源代码 - 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()方法添加到菜单。比如:

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继承而来的那种。比如:

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;
    }
}

更多详细内容请参考Demo中的AdvancedSample例程。

快捷键:

你可以使用以下的快捷键:

  • Ctrl+Space - 强制打开AutocompleteMenu
  • 上、下、上翻页、下翻页 - 在菜单中来回移动
  • 回车、Tab、鼠标双击 - 插入选中的文本(Tab键只在AllowTabKey为true时才起作用)
  • Esc - 关闭菜单

注意,尽管窗体焦点位于文本框,这些按键仍然哼正常工作。

当你点选了菜单项,就会显示相应的工具提示。

自定义ListView

你可以用自定义控件来显示AutocompleteMenu(如ListView、ListBox、DataGridView、TreeView等等)。首先创建自己的控件(从Control类派生),然后实现IAutocompleteListView接口。更多详情请参考CustomListViewSample。

动态上下文菜单

如果你要显示的菜单并非固定内容,而是根据文本而动态改变,那么你会经常用到这个部分。

请注意菜单的SetAutocompleteItems()方法采用了IEnumerable接口作为要显示的菜单项集合参数。

所以,你不必在程序一开始就生成菜单项列表。你只需要在调用菜单项的时候再动态生成就可以了。

下面的代码演示了这个思路:

autocompleteMenu1.SetAutocompleteItems(new DynamicCollection(tb));
    ....
 
    internal class DynamicCollection : IEnumerable<AutocompleteItem>
    {
        public IEnumerator<AutocompleteItem> GetEnumerator()
        {
            return BuildList().GetEnumerator();
        }
 
        private IEnumerable<AutocompleteItem> BuildList()
        {
            //找到文本中所有单词
            var words = new Dictionary<string, string>();
            foreach (Match m in Regex.Matches(tb.Text, @"\b\w+\b"))
                words[m.Value] = m.Value;
 
            //返回自动完成项
            foreach(var word in words.Keys)
                yield return new AutocompleteItem(word);
        }
    }

完整的实现代码请参考DynamicMenuSample。

兼容性

自动完成菜单可以兼容TextBox、RichTextBox、MaskedTextBox、FastColoredTextBox(一个非常强大的支持代码着色的文本框控件。近期将对其进行翻译。——野比注)和其他派生自TextBoxBase的控件。

同样,自动完成菜单也兼容任何支持以下属性和方法的控件:

  • string SelectedText{get;set;}
  • int SelectionLength{get;set;}
  • int SelectionStart{get;set;}
  • Point GetPositionFromCharIndex(int charPos)

即使你的控件不支持这些方法(或属性),你也可以为它创建自己的包装器。要这样做,你必须创建自己的包装类,并实现ITextBoxWrapper接口。

下面是ITextBoxWrapper的方法和属性:

public interface ITextBoxWrapper
    {
        Control TargetControl { get; }
        string Text { get; }
        string SelectedText { get; set; }
        int SelectionLength { get; set; }
        int SelectionStart { get; set; }
        Point GetPositionFromCharIndex(int pos);
        event EventHandler LostFocus;
        event ScrollEventHandler Scroll;
        event KeyEventHandler KeyDown;
        event MouseEventHandler MouseDown;
    }

做好了包装器之后,你就可以简单地把AutocompleteMenu附加到你的控件上去了。就像这样:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
        //把myControl1附加到autocompleteMenu1
            autocompleteMenu1.TargetControlWrapper = new MyControlWrapper(myControl1);
        }
    }
 
    internal class MyControlWrapper : ITextBoxWrapper
    {
        private MyControl tb;
 
        public MyControlWrapper(MyControl tb)
        {
            this.tb = tb;
        }
 
    //在这里实现ITextBoxWrapper
    //(略)
    }

示例

Demo中包含了几个示例:

SimplestSample- 展示最简单的使用控件方法

CustomItemSample- 展示了怎样创建从AutocompleteItem派生的类

AdvancedSample- 展示了怎样创建自定义的带关键字、代码段、方法提示、文本纠错等的自动完成菜单

ExtraLargeSample- 演示了在极大量(100万)菜单项情况下组件的性能

ComboboxSample- 展示了怎样创建模拟Combobox,带特别大的下拉列表和子字符串搜索功能

MulticolumnSample- 展示了怎样制作多列自动完成菜单。就像这样:

CustomListViewSample- 展示了怎样在自动完成菜单中制作自定义ListView。就像这样:

DynamicMenuSample- 这个例子展示了怎样创建动态的上下文敏感的自动完成菜单

DataGridViewSample- 展示了怎样把AutocompleteMenu附加到DataGridView。就像这样:

历史

2012年4月13日 - 首发。

2012年4月21日 - 重构了控件。增加了对FastColoredTextBox和其他控件的支持。

2012年5月9日 - 重构了控件。增加了一些例子。

许可

本文及相关源代码和文件,均采用GNU通用公共许可证(LGPLv3)授权。

(本译文也如此——野比注)

关于作者

Pavel Torgashov

我是Pavel Torgashov。我住在乌克兰基辅市。
我从1998年就开始开发软件了。
我的联系email是:tp_soft[at]mail.ru

乌克兰

关于译者

野比「Conmajia」

我是野比,你也可以叫我Conmajia。
我最大的兴趣是绘画和雕刻,
欢迎指导。

联系方式:conmajia[at]gmail.com

中国

(全文完)

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

分享到:
评论

相关推荐

    Ajax 四级导航菜单ASP+Access动态版

    Asp+Ajax无限级联动下拉框菜单Access版 ASP仿Google输入框提示_自动完成功能 AJAX+ASP多级无限制级联菜单(地市版) ASP下结合AJAX实现输入框提示(自动完成) ASP 树形菜单TreeView 多样式版 jQuery实例_飞飞ajax带...

    Weback微信公众帐号管理系统

    它可以协助您管理您的公众微信帐号,通过微信公众互动管理系统的二次开发你可以实现微信和您现有系统的整合,也可以方便的设置自动回复、代码段执行、关键字智能匹配等多种规则, 甚至是完成一个人机交互的对话。...

    长虹智能电视强制刷机升级固件 D2000i 4月28日 ZLS59GiD-V1.00055.rar

    升级完成后,自动开机。 2、等完全正常后拨下U盘,否即开机又升。 3、启动升级,就要等5-30分钟,中途不能有任何断电。 不能升的按住待机键或其它按键,遥控开机试升级 维修模式进入方法 使用用户遥控器,按...

    密码管家 - 最强大的密码管理助手(2012年2月2日重新上传v2.5.0)

    3. 对程序中所有划屏操作的滑动方向进行调整使之符合大多数人的操作习惯,另外让各种弹出菜单在被点选后自动关闭以方便后续新操作的执行。 4. 为配合新增的快速输入功能以及进一步简化用户的操作,在来电或切换到...

    Exce百宝箱——2012版本.rar

    Exce百宝箱——2012版本.rar &lt;══════════════════┤ 功能介绍(总共142个功能) ├════════════════════&gt; 【公农双历查询】:生成多功能日历,可以查询所有节、假日和农历...

    桌面数据库-x86v2012.05.003

    桌面数据库-x86v2012.05.003 更新: 1、完善常用窗口网格右键菜单。 2、新增灵活自由的行计算功能,可批量赋值,不设计默认计算公式,亦可很快完成计算需求。 3、修改表格制作窗口原来一些不尽人意的地方,如打印...

    文章管理系统

    6.整合2012年03月27日~2012年06月07日补丁 2012年06月07日 ★更新方式:admin文件夹改成你后台目录名,然后补丁包里的所有文件覆盖进去。 1.[纠正]纠正一些站长工具检索不到网站关键词和网站描述 2.[纠正]纠正...

    C程序课程设计报告---通讯录管理系统.doc

    C语言课程设计 课 题 通讯录管理系统 专业班级 自动化1201 学生姓名 徐浩 学 号 201201020129 指导老师 欧阳湘江 田媛 张晓清 审 批 任务书下达日期 2012年 12月 27 日 任务完成日期 2013年 1 月 4 日 1. 设计内容与...

    sourceinsight代码编写辅助工具

    这个小工具可以在SourceInsight工程中为代码自动完成如下功能: 1、添加代码修改说明 如果是同时选中了多行代码,格式为 /*Start of CuiJin on xxxx年xx月xx日 Version(NetEye3.2)*/ if(){ …… }else{ …… }...

    人力资源管理软件(完全免费)

    人力资源管理软件提供了工号修改功能(在员工管理窗口的功能菜单下)(感谢中秋月,方方) 员工资料增加了离职原因信息 人力资源管理软件增加了离职分析报表 打印模板设计进行了优化,支持分类管理(人力资源软件) ...

    美萍足浴软件1010v2

    1、宾客结账:功能 本模块将自动统计每个登记客人在店时所发生的所有消费额和应付款额,并完成结帐收银操作。 (图9) 在主窗口中选要结账宾客的手牌后,点击菜单“收银结账→宾客结账”(或点击主窗口中的...

    微信公众平台应用开发:方法、技巧与案例.(机械工业.柳峰)

    2014年1月出版。 内容简介 该书系统讲解了微信公众平台应用开发的流程、方法和技巧,并配有若干完整的案例。 全书共11章,逻辑上划分为四个部分: 第一部分(第1~2章)介绍了公众平台的使用、公众账号的认证、...

    立方酒店管理系统(SQL三层)

    可以使客房状态盘按照几号楼第几楼层显示相应的客房; 可以使客房状态盘只显示某个团队的所有客房; 快速切换回全部客房; 6、 信息修改 可以更改客人的相关信息; 7、 信息导出 可以将客人信息按照一定格式...

    立方酒店管理系统 (大型代码)

    4、 集中的团队管理l 在团队管理页中可以集中完成团队接待,团队补登房间,团队取消房间,团队退房,团队结账,团账查询,补交押金,变更押金方式,团队预结账等一系列操作;l 方便快捷的查询团队的所有用房情况;l ...

    立方酒店管理系统

    l 可以使客房状态盘按照几号楼第几楼层显示相应的客房; l 可以使客房状态盘只显示某个团队的所有客房; l 快速切换回全部客房; 6、 信息修改 l 可以更改客人的相关信息; 7、 信息导出 l 可以将客人信息...

    Weback微信互动系统V10.2源码20130506

    它可以协助您管理您的公众微信帐号,通过微信公众互动管理系统的二次开发你可以实现微信和您现有系统的整合,也可以方便的设置自动回复、代码段执行、关键字智能匹配等多种规则, 甚至是完成一个人机交互的对话。...

    TabBars---VC6 IDE增强插件

    2005年4月,“TabBars”的测试工作完成,正式定版发布,版本号为:1.0.17.3169,2005年6月,代码整理完成,同时发布源代码。 本文主要介绍TabBars插件的功能和使用方法,关于如何编译、调试“TabBars”源代码和代码...

    MaxDOS 9.2 全能装机版

    31.更新所有网卡驱动至2012年6月.更新DISKGEN 3.8,更新HDDREG为最新汉化版. 32.增加控制台快速启动功能键,可在WINDOWS下按下 CTRL+ALT+M快速启动控制台. 33.增加在线更新功能.增加安装前卸载旧版本MAXDOS(建议正常...

    Whole.Tomato.Visual.Assist.X.v10.6.1822 2010年4月最新破解补丁

    其特性包括成员列表框、完成列表框、停驻工具提示、自动参数信息。您可以在IDE对话框选项内设定每个组件的工作状态。  Visual Assist X去除了默认Intellisense的几个不足之处,采用一系列新的特性对其进行了补充,...

Global site tag (gtag.js) - Google Analytics