Файл справки открыт из модального окна не отвечает

Использование Delphi XE2, Win64.

Итак, у меня большое приложение с множеством форм, и если я открою файл справки из основной формы и открою модальное окно, а затем нажму F1, чтобы запустить контекстную справку в модальном окне, окно справочного файла отобразится с правильной информацией, но файл справки не может быть закрыт, пока я не закрою модальное окно. Я даже не могу заставить файл справки снова сосредоточиться, если я возвращаюсь к приложению, пока модальное окно не закроется.

При вызове точно такого же файла справки из старой версии нашего приложения (созданного с Delphi 6), расположенного в той же папке, что и новая версия (созданного с Delphi XE2), файл справки отображается при нажатии клавиши F1 из модального окна и отзывчивый и может быть закрыт, как я ожидаю.

Файл справки - это файл типа.chm.

Подвести итоги.

Запуск приложения Откройте файл справки с помощью F1. Перейдите в приложение и откройте модальное окно в приложении. Запустите справку из модального окна, нажав клавишу "Файл справки F1". Невозможно закрыть окно, пока я не вернусь к своему приложению и не закрою модальное окно.

Кто-нибудь имеет какие-либо идеи, почему это будет?

Я искал в Интернете и не нашел подобной проблемы.

Мы в тупике.

Приветствия TJ

----РЕДАКТИРОВАТЬ----

Вот некоторый код для примера приложения с двумя формами, который также демонстрирует это поведение.

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.

Вот код Form1:

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.

Я установил свойство helpcontext в двух формах для двух допустимых контекстов в моем файле справки.

Запустите приложение - F1, чтобы открыть файл справки. Нажмите кнопку "Хит", чтобы создать форму Form2 и показать F1 для вызова файла справки. Невозможно закрыть файл справки, пока я не закрою форму Form2.

Надеюсь это поможет. - TJ

1 ответ

Решение

Это серьезный недостаток дизайна в HtmlHelpViewer, И легко воспроизвести поведение, которое вы описываете. Хорошо сделано для того, чтобы четко обозначить проблему. Эта проблема в равной степени затрагивает как 32-, так и 64-разрядные программы.

Лично я не пользуюсь HtmlHelpViewer потому что это просто не работает. Я реализую обработчик для TApplication.OnHelp, Это выглядит так:

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;

Поместите это в класс и назначьте его Application.OnHelp на старте:

Application.OnHelp := THelpWindowManager.ApplicationHelp;

Я только что проверил это в тривиальном приложении, и оно хорошо работает. В реальном коде вы можете это украсить. Например, мой реальный код более сложный. Он сохраняет в настройках пользователя положение и состояние окна справки, когда оно закрыто. И затем, когда снова показывается, это положение и состояние окна восстанавливаются. Чтобы появилось окно справки, чтобы вспомнить, где оно было в последний раз на экране.


Спасибо @Sertac за подробности в комментариях ниже. В итоге вот где HtmlHelpViewer код идет не так:

  1. Это делает отправляет HH_INITIALIZE команда при запуске системы помощи.
  2. Как описано в документации, это позволяет настроить справку HTML для запуска в том же потоке, что и вызывающее приложение, а не во вторичном потоке.
  3. Когда вы звоните ShowModal что вызывает DisableTaskWindows который отключает окна в вызывающем потоке.
  4. Поскольку окно просмотра справки было создано основным потоком вашего приложения (из-за HH_INITIALIZE команда), он отключается.

И именно поэтому вы не можете взаимодействовать с уже существующим окном справки, пока активна модальная форма Delphi.

Другие вопросы по тегам