问题描述
我正在研究的软件项目遇到了令人沮丧的问题。我得到了各种形式的设置帮助,例如,如果按F1键,将打开应用程序的CHM文件。
我希望它始终打开与当前表单相关的主题,但是当前它打开的位置取决于表单的焦点。如果重点关注某些字段,它将在帮助文档第一页的顶部打开;如果其他字段处于焦点位置,它将正确打开与当前表单相关的页面和标题。
对于各种表单,我都有以下设计器代码,而我只是在表单本身上设置了HelpKeyword,而不是表单的任何控件。
this.helpProvider.HelpNamespace = @"Path\To\ChmFile.chm";
this.helpProvider.SetHelpKeyword(this,"TopicName.htm#heading_name");
this.helpProvider.SetHelpNavigator(this,System.Windows.Forms.HelpNavigator.Topic);
根据实验,我确定带有SetShowHelp(false)
或Enabled = false
的项目是唯一显示正确的chm帮助位置的项目。当按F1使其焦点对准时(如果它们可以保持焦点),或者使用“这是什么”帮助光标按它们时,将适用此条件。
例如:
- 如果焦点位于主对话框的第一个控件(一个具有HelpString的TextBox,它隐式设置ShowHelp),然后按F1键,我将被发送到整个应用程序帮助页面(异常行为)。
- 如果焦点位于没有关联帮助字符串的主对话框TextBox上,然后按F1键,则会在主对话框的标题处显示“对话框”帮助页面(期望的行为)。
到目前为止,我发现的唯一解决方法是在每个带有HelpTopic
的控件上同时设置HelpNavigator
和HelpString
,但这是非常笨拙的操作,很难实现维持。
说明
我有意同时使用“这是什么?”帮助和F1帮助使用相同的形式。我不会接受一种解决方案,该解决方案说要禁用窗体上的所有控件的“这是什么”帮助,以便允许F1帮助起作用。对于此应用程序,交互式控件必须具有帮助工具提示, ,并且每个对话框在帮助文档中都必须有一个帮助部分。
如果无法使这两个帮助功能很好地协同工作,我将接受一种有效的解决方法,该方法不会像上述解决方法那样牺牲可维护性。
解决方法
只有在您澄清之后,我才能够完全理解您的问题并重现该问题。我以前不知道这种行为。 在Windows 10 PC上使用Visual Studio 2019具有相同的不良行为-无论是在Form_Load事件中进行编码还是在设计器代码中借助IDE(集成开发环境)进行编码,都无关紧要。
经过几个小时的实验(针对重现的问题),我希望将其范围缩小到完全不知道真正原因的地方。
通过实验,我已经完成了以下步骤和思想-仅供参考(请参见下面列表中的特殊说明):
- HelpNavigator枚举的默认值为
AssociateIndex
。如果您不小心设置了SetShowHelp = True
,并且缺少必需的属性,则对“索引”选项卡的调用可能会失败,破坏某些内容并转到CHM的主页主题。如果您的CHM中没有索引标签,则会出现另一个问题。 - 我删除或重命名了文件 hh.dat 几个例程,以将系统上的所有(!)CHM窗口重置为其默认设置。当您下次打开任何.chm文件时,Windows将创建hh.dat的新版本。您会在
C:\Users\%username%\AppData\Roaming\Microsoft\HTML Help
找到hh.dat。 但是--在第一个测试阶段中,现有问题没有成功。 - 仅用于更多测试(以后不再需要代码),我尝试了是否触发了Form3_HelpRequested。 但是-在第一个测试阶段不起作用。
private void Form1_HelpRequested(object sender,HelpEventArgs hlpevent)
{
// do whatever you're gonna do here
DialogResult dr = MessageBox.Show("HelpRequested on Form1 was fired!\n\nOpen CHM help?","Test case",MessageBoxButtons.YesNo);
switch (dr)
{
case DialogResult.Yes:
// FALSE will also open any associated help file
hlpevent.Handled = false;
break;
case DialogResult.No:
// TRUE will prevent windows from also opening any associated help file
hlpevent.Handled = true;
break;
}
- 最后一个困难的步骤是,我删除了HelpProvider组件,再次将其插入并再次正确设置了所有属性。 现在-它正在为我工作。具有属性
ShowHelp=True
的控件现在显示分配的主题,具有属性ShowHelp=False
的控件现在显示窗体的帮助主题。
您知道-这可能是一个复杂的步骤,应首先在测试环境中完成。确保正确设置了所有属性,并且可以通过HelpKeyword在CHM中访问该主题。
// Tell the HelpProvider what controls to provide help for,and what the help string is.
this.helpProvider1.SetShowHelp(this.cityTextBox,true);
this.helpProvider1.SetHelpNavigator(this.cityTextBox,HelpNavigator.Topic); // make sure to set "Topic"
this.helpProvider1.SetHelpKeyword(this.cityTextBox,@"/Garden/flowers.htm");
this.helpProvider1.SetHelpString(this.cityTextBox,"Enter the city here.");
提供城市文本框焦点和 F1 后,将显示帮助查看器窗口。在第二步中使用“这是什么” ?按钮将导致:
tl; dr
通过设计者代码或程序代码对属性的定义更多地取决于个人喜好。我自己更喜欢在程序代码中设置值,而不是通过Visual Studio的控件属性窗口来设置。
如果在此处将帮助功能的所有控件属性添加为代码,则可以轻松注释掉以解决问题。在具有许多控件的表单中,将代码的一部分保存到外部并稍后再插入它们会更容易。但是正如我所说-每个人都喜欢它。
// set F1 help topic for first form
private void Form1_Load(object sender,EventArgs e)
{
helpProvider1.SetHelpNavigator(this,HelpNavigator.Topic);
helpProvider1.SetHelpKeyword(this,@"/HTMLHelp_Examples/Jump_to_anchor.htm#SecondAnchor");
}
顺便说一句-“这是什么?”大型程序的帮助意味着付出巨大的努力,而根据我的经验,帮助创作(CHM)的使用越来越少。例如,这种帮助自Visual Basic 6起就有很长的历史。如今,您通常只为表单或对话框找到一个帮助主题,其中解释了单个控件。然后,您描述的问题根本不会出现。
仅供参考-在早期,需要ALIAS和MAP文件,TopicId
可能在今天使用它们。这两个文件的目的是简化开发人员和帮助作者之间的协调。映射文件将ID链接到地图编号-通常,开发人员可以轻松创建该ID,并将其传递给帮助作者。然后,帮助作者创建一个别名文件,将ID链接到主题名称。