帮助文件从模态窗口打开无响应 [英] Helpfile opened from modal window unresponsive

查看:152
本文介绍了帮助文件从模态窗口打开无响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Delphi XE2,Win64。



所以我有一个很大的表单的应用程序,如果我从主窗体打开帮助文件,并打开一个模态窗口,然后点击F1以在帮助文件窗口显示的模式窗口中触发上下文相关帮助,并显示正确的信息,但在关闭模态窗口之前,帮助文件无法关闭。如果我回到应用程序,直到模态窗口关闭,我甚至不能再获得帮助文件。



将此精确调用帮助文件从旧版本的我们的应用程序(使用Delphi 6构建)与新版本(使用Delphi XE2构建)在同一个文件夹中,当模式窗口中的F1键被触发时,帮助文件显示,并且可以是



帮助文件是.chm类型的文件。



总结。 >

启动应用程序
通过F1打开帮助文件
跳转到应用程序并在应用程序中打开模态窗口
通过点击F1 $ b启动模式窗口的帮助$ b帮助文件窗口无法关闭,直到我跳回到我的应用程序并关闭模式窗口。



有没有人知道为什么会这样? p>

我已经在互联网上搜索过,没有发现任何类似的问题。



我们被骗了



C heers
TJ



----编辑----



这是一些代码一个样本两个表单应用程序也表现出这种行为。

 程序Project1; 

使用
Vcl.Forms,
HTMLHelpViewer,
Unit1 in'Unit1.pas'{Form1},
Unit2 in'Unit2.pas'{ Form2};

{$ R * .res}

begin
Application.Initialize;
Application.HelpFile:='C:\helpfile.chm';
Application.MainFormOnTaskbar:= True;
Application.CreateForm(TForm1,Form1);
Application.Run;
结束。

这是Form1代码:



<$ p $单位Unit1;

接口

使用
Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,
Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.StdCtrls;

type
TForm1 = class(TForm)
Button1:TButton;
procedure Button1Click(Sender:TObject);
private
{私人声明}
public
{公开声明}
end;

var
Form1:TForm1;

实现

{$ R * .dfm}

使用Unit2;

procedure TForm1.Button1Click(Sender:TObject);
begin
Form2:= TForm2.Create(Application);
try
Form2.ShowModal;
finally
Form2.Free;
结束
结束

结束。

我将帮助文件中的两个表单上的helpcontext属性设置为两个有效的上下文。 >

运行应用程序 - F1打开帮助文件
点击按钮,因此Form2已创建并显示
F1调用帮助文件
无法关闭帮助文件直到我关闭Form2。



希望这有帮助。 - TJ

解决方案

这是一个严重的设计缺陷,在 HtmlHelpViewer 中。并且很容易重现你所描述的行为。做得很好,明确指出问题。这个问题同样影响32位和64位程序。



我个人不使用 HtmlHelpViewer ,因为它只是不工作我实现了 TApplication.OnHelp 的处理程序。它看起来像这样:

 类函数THelpWindowManager.ApplicationHelp(命令:Word; 
数据:THelpEventData; var CallHelp: Boolean):Boolean;
begin
CallHelp:= False;
结果:= True;
// argh,WinHelp命令
case命令
HELP_CONTEXT,HELP_CONTEXTPOPUP:
HtmlHelp(GetDesktopWindow,Application.HelpFile,HH_HELP_CONTEXT,Data);
结束
结束

将它放在一个类中,并将其分配给 Application.OnHelp 启动时:

  Application.OnHelp:= THelpWindowManager.ApplicationHelp; 

我刚刚测试了这个简单的两个表单应用程序,它的效果很好。在真实的代码中,你可能希望改善这一点。例如,我的实际代码更复杂。它在用户设置中存储帮助窗口关闭时的位置和窗口状态。然后再次显示时,恢复该位置和窗口状态。所以帮助窗口似乎记住了屏幕上最后的位置。






感谢@Sertac挖掘出细节在下面的评论。总而言之,这里的 HtmlHelpViewer 代码出错:


  1. 它发送<帮助中的href =http://msdn.microsoft.com/en-gb/library/windows/desktop/ms670090.aspx> HH_INITIALIZE 命令系统启动。

  2. 文档这个配置HTML帮助在与调用应用程序而不是辅助线程相同的线程上运行

  3. 当您调用 ShowModal 调用 DisableTaskWindows ,禁用调用线程中的窗口。

  4. 因为帮助查看器窗口已创建通过你的应用程序的主线程(因为 HH_INITIALIZE 命令),它被禁用。

这就是为什么在Delphi模态窗体处于活动状态时,您无法与预先存在的帮助窗口进行交互。


Using Delphi XE2, Win64.

So I have a large application with many forms and if I open the help file from the main form and open a modal window and then hit F1 to fire off context-sensitive help on the modal window the help file window shows with the correct info but the help file cannot be closed until I close the modal window. I cannot even get the help file to have focus again if I go back to the application until the modal window closes.

Calling this exact same help file from the old version of our application (built with Delphi 6) sitting within the same folder as the new version (built with Delphi XE2) the help file displays when the F1 key is hit from the modal window and is responsive and can be closed like I expect.

The help file is .chm type file.

To summarize.

Launch application Open help file by F1 Jump to application and open modal window in application Launch help from modal window by hitting F1 Help file window cannot be closed until I jump back to my application and close the modal window.

Does anybody have any idea at all why this would be?

I have searched the Internet and have not found any similar issue.

We are stumped.

Cheers TJ

----EDIT----

Here is some code for a sample two form app that also exhibits this behavior.

program Project1;

uses
  Vcl.Forms,
  HTMLHelpViewer,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.HelpFile := 'C:\helpfile.chm';
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Here is Form1 code:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit2;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.Create(Application);
  try
    Form2.ShowModal;
  finally
    Form2.Free;
  end;
end;

end.

I set the helpcontext property on the two forms to two valid contexts within my help file.

Run the app - F1 to open help file Hit button so Form2 is created and shown F1 to call help file Cannot close help file until I close Form2.

Hope this helps. - TJ

解决方案

This is a serious design flaw in HtmlHelpViewer. And it's easy to reproduce the behaviour you describe. Well done for specifying the problem so clearly. The issue afflicts both 32 and 64 bit programs equally.

Personally I don't use HtmlHelpViewer because it just doesn't work. I implement a handler for TApplication.OnHelp. It looks like this:

class function THelpWindowManager.ApplicationHelp(Command: Word; 
  Data: THelpEventData; var CallHelp: Boolean): Boolean;
begin
  CallHelp := False;
  Result := True;
  //argh, WinHelp commands
  case Command of
  HELP_CONTEXT,HELP_CONTEXTPOPUP:
    HtmlHelp(GetDesktopWindow, Application.HelpFile, HH_HELP_CONTEXT, Data);
  end;
end;

Put that in in a class and assign it to Application.OnHelp on startup:

Application.OnHelp := THelpWindowManager.ApplicationHelp;

I've just tested that out on the trivial two form application and it works well. In real code you may wish to embellish this. For example, my actual code is more complex. It stores in user settings the position and window state of the help window when it is closed. And then when shown again, that position and window state are restored. So that the help window appears to remember where it last was on the screen.


Thanks to @Sertac for dredging out the details in the comments below. In summary here's where the HtmlHelpViewer code goes wrong:

  1. It makes sends the HH_INITIALIZE command at help system startup.
  2. As described in the documentation this configures HTML Help to run on the same thread as the calling application instead of a secondary thread.
  3. When you call ShowModal that calls DisableTaskWindows which disables windows in the calling thread.
  4. Because the help viewer window was created by your app's main thread (because of the HH_INITIALIZE command), it gets disabled.

And that's why you cannot interact with the a pre-existing help window whilst a Delphi modal form is active.

这篇关于帮助文件从模态窗口打开无响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆