将帮助文件链接到 Delphi XE2 应用程序 - 除主窗体外一切正常
Posted
技术标签:
【中文标题】将帮助文件链接到 Delphi XE2 应用程序 - 除主窗体外一切正常【英文标题】:Linking helpfile to an Delphi XE2 Application - everything works except main form 【发布时间】:2012-04-16 14:49:05 【问题描述】:我正在使用我们的软件设置帮助文件。我为许多特定的表单/框架/控件添加了 HelpContext 编号,它们都可以正常工作。问题是主要形式根本没有提供任何帮助。对于所有这一切,我只是使用 F1 来尝试触发帮助。
我根本不是 Delphi 或帮助文件方面的专家,但我会发布我所做的以及我看过的地方。
编辑:感谢一些帮助,我现在看到问题是由于主窗体是 MDI 父级。这仍然不能解决问题.. 对我来说这几乎像是一个错误,但我想这可能是出于某种原因故意的。 结束编辑
我包括这个单元:查看器的 htmlHelpViewer。在主窗体创建构造函数中,我添加了 Application.Helpfile := 'asdf.chm'。对于所有其他形式,我刚刚添加了上下文编号,它立即生效。我在主窗体上尝试过,没有任何反应。所以我尝试添加一个 Application.OnHelp 事件,但这不会在主窗体上调用(它适用于帮助工作的所有其他窗体)。
我能想到的最后手段是深入跟踪代码并查看发生了什么。我到了 Vcl.Forms 中的 TCustomForm.WMHelp 作为分裂发生的地方。所述函数有这个循环:
if iContextType = HELPINFO_WINDOW then
begin
Control := FindControl(hItemHandle);
while (Control <> nil) and ( not ControlHasHelp(Control)) do
Control := Control.Parent;
if Control = nil then Exit;
GetHelpInfo(Control, HType, ContextID, Keyword);
Pt := Control.ClientToScreen(Point(0, 0));
end
当主窗体调用帮助控件时,它将为 nil,然后它会退出。其他任何事情都会顺利进行。
我显然不知道为什么会这样。答案可能是非常基本的。任何想法将不胜感激!
【问题讨论】:
您是否为主表单本身设置了HelpContext
?
@DavidHeffernan:是的,我做到了。我应该提到这一点,但它只是主要形式,而不是它的孩子。我在表单上放了一个按钮(没有上下文帮助),当它有焦点时,我按 F1 键加载主表单的帮助上下文。如果没有可见的焦点,则不会加载任何帮助。
我会看看调试器下的 WMHelp 处理程序,看看 FindControl 返回了什么。
@DavidHeffernan 我往下看了看,但它似乎没有多大帮助。 FindControl 为表单返回 nil 并为有效的控件返回结果,但是当我去看看为什么我到达这一行 'Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)))' (在 Vcl.Controls 中, FindControl) 对于链接的控件,它返回一些东西。但是当它返回主要形式时,它返回 nil。我无法进行更深入的调试,因为它只是转到一个属性(或类似的东西)。
好吧,这就是问题的关键所在。 FindControl 返回nil
是没有帮助出现的原因。问题是为什么会这样。下一步是查看hItemHandle
是什么并尝试识别它。我会使用 Spy++ 来调试它的那一部分。
【参考方案1】:
根据您的 cmets,WM_HELP
消息的目标是您的 MDI 客户端窗口。由于这不是 VCL 控件,因此它不会响应 WM_HELP
消息。可以通过截取消息并请求主窗体处理来处理问题:
type
TMainForm = class(TForm)
protected
procedure WMHelp(var Message: TWMHelp); message WM_HELP;
end;
....
procedure TMainForm.WMHelp(var Message: TWMHelp);
begin
if (Message.HelpInfo.iContextType=HELPINFO_WINDOW)
and (Message.HelpInfo.hItemHandle=ClientHandle) then
Message.HelpInfo.hItemHandle := Handle;
inherited;
end;
如果你想更加防御,你可以这样写:
if (Message.HelpInfo.iContextType=HELPINFO_WINDOW)
and (FindControl(Message.HelpInfo.hItemHandle)=nil) then
Message.HelpInfo.hItemHandle := Handle;
我刚刚查看了我自己的 MDI 应用程序,我可以看到我有类似的代码来处理这个确切的问题。如果不是 10 多年前写的,我可能会记得更早!
【讨论】:
太棒了,非常感谢您的帮助!我不得不对你的代码做一个小的改动,我补充说:with Message.HelpInfo$IFNDEF CLR^$ENDIF do
因为编译器不喜欢 iContextType,我从 VCL.Forms 的 WMHelp 中得到了它。 (然后从and的第二部分取出Message.HelpInfo。)以上是关于将帮助文件链接到 Delphi XE2 应用程序 - 除主窗体外一切正常的主要内容,如果未能解决你的问题,请参考以下文章
新的 Delphi XE2 自动生成的内部版本号是不是链接到 1.1.2000 00:00:00?