Обновление
Согласно последним комментариям к отчету QC , представленному Altaveron, эта проблема будет решена в следующем обновлении Delphi, обновлении 4. Идействительно, Altaveron теперь подтверждает, что обновление 4 действительно решает проблему.
Это известная проблема с элементом справки MS HTML, hhctrl.ocx.Лучшее описание, о котором я знаю, - в HelpWare FAR HTML FAQ.Существует множество отчетов о контроле качества, описывающих проблему: 48983 , 67463 , 78998 , 89616 .
Согласнопоследний отчет о контроле качества, это исправлено в XE2, но вы сообщаете иначе, и я был бы склонен вам верить.Тем более, что сравнение источника для HtmlHelpViewer
модуля из XE и XE2 не показывает никаких изменений, которые появляются, связанные с этой проблемой.
Довольно сложно обойти эту проблему, так как код, который необходимо изменить,похоронен глубоко внутри блока HtmlHelpViewer
.Мне пришлось прибегнуть к исправлению вызова API HtmlHelp
.Например:
unit HtmlHelpFixer;
interface
implementation
uses
Windows;
function HtmlHelp(hWndCaller: HWND; pszFile: PWideChar; uCommand: UINT; dwData: DWORD): HWND;
begin
if uCommand=HH_CLOSE_ALL then begin
//don't call HtmlHelpW because it can result in a hang due to a bug in hhctrl.ocx
Result := 0;
end else begin
Result := HtmlHelpW(hWndCaller, pszFile, uCommand, dwData);
end;
end;
procedure PatchCode(Address: Pointer; const NewCode; Size: Integer);
var
OldProtect: DWORD;
begin
if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then begin
Move(NewCode, Address^, Size);
FlushInstructionCache(GetCurrentProcess, Address, Size);
VirtualProtect(Address, Size, OldProtect, @OldProtect);
end;
end;
type
PInstruction = ^TInstruction;
TInstruction = packed record
Opcode: Byte;
Offset: Integer;
end;
procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
NewCode: TInstruction;
begin
NewCode.Opcode := $E9;//jump relative
NewCode.Offset := NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode);
PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;
procedure RedirectHtmlHelp;
var
HtmlHelp: function(hWndCaller: HWND; pszFile: PWideChar; uCommand: UINT; dwData: DWORD_PTR): HWND;
begin
HtmlHelp := Windows.HtmlHelp;
RedirectProcedure(@HtmlHelp, @HtmlHelpFixer.HtmlHelp);
end;
initialization
RedirectHtmlHelp;
end.
Включите этот модуль в свой список .dpr uses
раньше, чем любой модуль, который что-либо делает с помощью HTML.
Версия кода, которую я использую, делаетнемного больше и предпринимает шаги, чтобы гарантировать, что все открытые окна справки закрыты, когда DLL выгружается.Это больше не происходит, потому что мы прекратили отправлять HH_CLOSE_ALL
.
. Вы захотите убедиться, что все окна справки закрыты, а затем отследите дескрипторы окон, возвращенные вызовами HtmlHelp
, которые вы можете теперьперехватывать.Затем при завершении работы отправьте сообщение WM_CLOSE
в те окна, которое заменяет пропущенный вызов HH_CLOSE_ALL
на HtmlHelp
.
Однако я считаю, что приведенный выше код поможет вам преодолеть ваше непосредственное препятствие с regsvr32, который выигралПоказывать справочные окна.
Не стесняйтесь экспериментировать!По крайней мере, приведенный выше код дает вам точки входа, с помощью которых вы можете изменить поведение устройства HtmlHelpViewer
.