Я не могу заставить контекстно-зависимую справку Delphi работать в диалоговых окнах открытия и сохранения

У меня есть приложение Delphi 2006 с файлом справки CHM. Все работает нормально, за исключением того, что я не могу получить помощь, чтобы подключиться к кнопке «Справка» на TOpenDialog и TSaveDialog.

Ниже показана простая программа, демонстрирующая это. При нажатии кнопки 2 открывается файл справки и отображается правильная страница. Нажатие кнопки 1 открывает диалоговое окно, но нажатие кнопки справки в диалоговом окне не оказывает никакого действия.

unit Unit22;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,
  HTMLHelpViewer ;

type
  TForm22 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form22: TForm22;

implementation

{$R *.dfm}

procedure TForm22.Button1Click(Sender: TObject);
begin
OpenDialog1.HelpContext := 10410 ;
OpenDialog1.Execute ;
end;

procedure TForm22.Button2Click(Sender: TObject);
begin
Application.HelpContext  (10410) ;
end;

procedure TForm22.FormCreate(Sender: TObject);
begin
Application.HelpFile := 'c:\help.chm' ;
end;

end.

person rossmcm    schedule 14.10.2010    source источник


Ответы (1)


С настройками по умолчанию обработка справочных сообщений TOpenDialog не работает (вы должны отправить их в Quality Central).

Конкретная причина заключается в том, что Windows отправляет справочное сообщение родительскому диалоговому окну, а не самому диалоговому окну, поэтому, если ваша форма не настроена для его обработки, она просто игнорируется.

Исправление состоит в том, чтобы установить для Application.ModalPopupMode значение pmAuto вместо значения по умолчанию pmНет. Вы можете сделать это один раз во время обычного кода запуска или непосредственно перед отображением диалогового окна. Когда это установлено, Delphi создает промежуточное окно (Dialogs.pas::TRedirectorWindow), которое правильно обрабатывает сообщение.

Если по какой-то причине вы не можете изменить ModalPopupMode, то, как я уже сказал, вам нужно обработать сообщение в вашей форме:

TForm22 = class(TForm)
...
  procedure WndProc(var Message: TMessage); override;
end;

initialization

var
  HelpMsg: Cardinal;

procedure TForm22.WndProc(var Message: TMessage);
begin
  inherited;
  if (Message.Msg = HelpMsg) and (OpenDialog1.Handle <> 0) then
    Application.HelpContext(OpenDialog1.HelpContext);
end;

initialization
  HelpMsg := RegisterWindowMessage(HelpMsgString);
end.
person Zoë Peterson    schedule 15.10.2010
comment
Спасибо за это. Сработало более простое исправление (Application.ModalPopupMode := pmAuto, вызываемое в переопределенном методе CreateWnd()) — я не знаю, какие другие возможные побочные эффекты могут быть в моем приложении. Предположительно, мне не нужно ничего делать при выходе, так как экземпляр TApplication все равно исчезнет. - person rossmcm; 15.10.2010
comment
@ user89691: Побочным эффектом будет то, что каждая открытая форма будет связана с формой, из которой она была открыта. А это значит, что он будет закрыт при закрытии родительской формы. Если вам нужно больше контроля, используйте pmExplicit в качестве PopupMode и установите для каждой формы PopupParent..., ну, явно... Parentend (в круглых скобках), потому что фактический родитель формы не затрагивается, только его PopupParent . - person Marjan Venema; 15.10.2010
comment
Хорошо, я все еще немного смущен здесь. Переопределение CreateWnd работает, так что безопасно ли оставить его таким? В качестве альтернативы My TOpenDialog и TSaveDialog создаются автоматически (т. е. компоненты помещаются в форму во время разработки). Так что я мог бы: 1) Непосредственно перед вызовом Execute сохранить текущее значение Application.ModalPopup. 2) затем установите Application.ModalPopup = pmAuto. 3) после вызова Execute восстановите Application.ModalPopup до сохраненного значения. Кажется, это работает, и у меня меньше шансов сломать его в другом месте, поскольку все осталось как было. - person rossmcm; 20.10.2010
comment
Оставлять так должно быть безопасно. Использование pmAuto ближе к поведению других приложений, отличных от Delphi. - person Zoë Peterson; 20.10.2010