Файл справки открыт из модального окна не отвечает
Использование 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
код идет не так:
- Это делает отправляет
HH_INITIALIZE
команда при запуске системы помощи. - Как описано в документации, это позволяет настроить справку HTML для запуска в том же потоке, что и вызывающее приложение, а не во вторичном потоке.
- Когда вы звоните
ShowModal
что вызываетDisableTaskWindows
который отключает окна в вызывающем потоке. - Поскольку окно просмотра справки было создано основным потоком вашего приложения (из-за
HH_INITIALIZE
команда), он отключается.
И именно поэтому вы не можете взаимодействовать с уже существующим окном справки, пока активна модальная форма Delphi.