HtmlHelpFunc.pas 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. unit HtmlHelpFunc;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2024 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Functions for HTML Help
  8. }
  9. interface
  10. {$I VERSION.INC}
  11. uses
  12. Windows;
  13. const
  14. HH_DISPLAY_TOPIC = $0000;
  15. HH_KEYWORD_LOOKUP = $000D;
  16. type
  17. THtmlHelp = function(hwndCaller: HWND; pszFile: PChar; uCommand: UINT; dwData: DWORD): HWND; stdcall;
  18. PHH_AKLink = ^THH_AKLink;
  19. THH_AKLINK = record
  20. cbStruct: Integer;
  21. fReserved: Bool;
  22. pszKeywords: PChar;
  23. pszUrl: PChar;
  24. pszMsgText: PChar;
  25. pszMsgTitle: PChar;
  26. pszWindow: PChar;
  27. fIndexOnFail: Bool;
  28. end;
  29. var
  30. HtmlHelp: THtmlHelp;
  31. procedure InitHtmlHelpLibrary;
  32. procedure FreeHtmlHelpLibrary;
  33. implementation
  34. uses
  35. Messages, SysUtils, CmnFunc2, PathFunc;
  36. var
  37. HHCtrl: THandle;
  38. procedure InitHtmlHelpLibrary;
  39. begin
  40. if HHCtrl = 0 then begin
  41. HHCtrl := LoadLibrary(PChar(AddBackslash(GetSystemDir) + 'hhctrl.ocx'));
  42. if HHCtrl <> 0 then
  43. HtmlHelp := GetProcAddress(HHCtrl, 'HtmlHelpW')
  44. else
  45. HtmlHelp := nil;
  46. end;
  47. end;
  48. procedure FreeHtmlHelpLibrary;
  49. begin
  50. if HHCtrl <> 0 then begin
  51. HtmlHelp := nil;
  52. FreeLibrary(HHCtrl);
  53. HHCtrl := 0;
  54. end;
  55. end;
  56. function CloseHtmlHelpWindowsEnumProc(Wnd: HWND; lParam: LPARAM): BOOL; stdcall;
  57. var
  58. PID: DWORD;
  59. ClassName: array[0..31] of Char;
  60. MsgResult: DWORD_PTR;
  61. begin
  62. if (GetWindowThreadProcessId(Wnd, @PID) <> 0) and
  63. (PID = GetCurrentProcessId) then begin
  64. if (GetClassName(Wnd, ClassName, SizeOf(ClassName) div SizeOf(ClassName[0])) > 0) and
  65. (StrIComp(ClassName, 'HH Parent') = 0) then begin
  66. { Consider only enabled windows. If an HTML Help window is disabled
  67. because it's waiting on a modal dialog (e.g. Properties) then it's
  68. probably not safe to close it. }
  69. if IsWindowEnabled(Wnd) then
  70. SendMessageTimeout(Wnd, WM_CLOSE, 0, 0, SMTO_BLOCK, 7500, @MsgResult);
  71. end;
  72. end;
  73. Result := True;
  74. end;
  75. procedure CloseHtmlHelpWindows;
  76. begin
  77. { Note: We don't call HtmlHelp(HH_CLOSE_ALL) here because its operation is
  78. asynchronous. (See: http://helpware.net/FAR/far_faq.htm#HH_CLOSE_ALL)
  79. If HHCTRL.OCX is unloaded too quickly after HH_CLOSE_ALL, a crash can
  80. occur. Even if HHCTRL.OCX isn't explicitly unloaded, it still *might* be
  81. possible for the main thread to exit while the HH thread is still in the
  82. process of closing the window and cleaning up the temporary file.
  83. Therefore, we use a different approach: we find the window(s) and send a
  84. WM_CLOSE message synchronously. }
  85. if Assigned(HtmlHelp) then
  86. EnumWindows(@CloseHtmlHelpWindowsEnumProc, 0);
  87. end;
  88. initialization
  89. finalization
  90. { Must explicitly close any open HTML Help window before terminating,
  91. otherwise it leaves behind a temporary file. (Most apps don't bother
  92. doing this, including IE and Outlook Express.) }
  93. CloseHtmlHelpWindows;
  94. end.