为 .NET 应用程序编写上下文帮助,随时随地为任何人
为 .NET 应用程序随时随地为任何人编写上下文帮助
Title: Context Help authoring anywhere/anytime/anyone for .NET application Author: rufei zhao Email: slimzhao@21cn.com Member ID: 2308266 Language: C# Platform: .NET 1.1+ etc Technology: .NET/C# Level: Beginner, Intermediate, Advanced Description: An article on howto make authoring the context help for UI easier.
引言
我为此启动了一个 sourceforge 项目,有关详细信息和进度跟踪,请访问 http://nethelpanywhere.sourceforge.net/
将上下文帮助功能添加到 .NET/Forms 的常用方法是为每个 Form 添加一个 HelpProvider 组件,然后在属性网格面板中编辑每个 UI 元素(如按钮、RadioButton、CheckBox、ComboBox 等)的帮助字符串。这很乏味,程序员不是编写应用程序帮助信息的合适人选,尤其是对于支持多语言的应用程序而言。
在一个典型的产品周期中,更改帮助字符串/图标/颜色调整总是一个反复的、无休止的过程。而且,对于这类非代码问题,您作为开发人员被迫集成这些资源并重新构建整个解决方案。
本文介绍了一种新的上下文帮助编写方法。使用此方法,多语言的帮助字符串会为正在运行的应用程序动态加载/编写。帮助字符串存储在 xml 文件中。每个运行应用程序的人都有能力编写关于如何使用 UI 元素(例如晦涩的按钮)的任何内容。而且,由许多人编写的帮助可以合并成一个,所以这也是一个分布式上下文帮助编写系统。
如果愿意,您也可以向最终用户开放此功能,以便您的应用程序用户能够编写他们自己关于您的 UI 元素的功能以及如何使用/避免使用它的想法,并与他人分享。
使用代码
要使用该组件,
At first add a reference to EasyHelp.dll
然后在您的 pre 的顶部添加以下行using Slimzhao;
在您的 Form 的构造函数中,在末尾添加以下几行EasyHelpString.AddNonParentUserControl(true, null);
EasyHelpString.InitHelpProvider(this);
变量或类名应该用 <code> 标签包裹,例如 this
.
关注点
EasyHelp 依赖于 Control 具有 Name 属性,Visual Studio IDE 将为每个控件生成一个唯一的名称,对于开发人员来说,您很少会注意到此属性,而且它总是无用的。
这里也出现了 easyhelp 的缺点:同一父控件的控件必须指定一个唯一的名称,因此 Visual Studio 生成的 UI,这不是一个问题,因为 IDE 将为每个 UI 生成不同的名称。对于更复杂的 UI(如动态 UI),设计器可能会省略 Name 属性。
也许新版本的 EasyHelp 应该依赖 Z 顺序来识别每个控件。
EasyHelp 注册了 ContextHelp 处理程序,并检查触发此事件时 Shift 键是否被按下。如果是,则弹出上下文帮助编写窗口,如果不是,则执行旧的操作,即弹出帮助字符串。
微软不允许您随意组合最小化框/最大化框/关闭框和“?”帮助框/帮助框,因此如果您想使用上下文帮助用于没有“?”框的表单,您需要自己触发该事件。
但您不能仅通过发送消息来实现。我的第一个想法是在按钮的 click 处理程序中执行此操作,例如
private void m_btn_help_Clicked(object sender, System.EventArgs e) { DefWindowProc(this.Handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0); }上面的代码将无法工作,因为当处理程序返回时,Button 的窗口过程会做其他事情,这会使上下文帮助状态消失。我使用以下技巧作为解决方法
private void m_btn_help_Clicked(object sender, System.EventArgs e) { if( m_hlpbtn_timer == null) { m_hlpbtn_timer = new Timer(); m_hlpbtn_timer.Interval = 100; //100 milli-seconds , 1/10 seconds m_hlpbtn_timer.Tick += new EventHandler(m_timer_Tick); } m_hlpbtn_timer.Start(); } private void m_timer_Tick(object sender, EventArgs e) { DefWindowProc(this.Handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0); m_hlpbtn_timer.Stop(); }