Problem:
Marcel van Brakel has uncovered a real problem with HH_CLOSE_ALL. When you call HH_CLOSE_ALL on shut down, the HH API creates another thread and sometimes does not return until after you have performed UnLoadLibrary(hhctrl.ocx). In this case the HH_CLOSE_ALL thread returns to nothing and causes an access violation.
Discussion:
Ralph Walden (x-Microsoft) describes the problem:
The switch to a background thread was done after I left (the MS help team) in order to solve a problem with Visual Studio. I knew they should have fixed Visual Studio instead of "fixing" HTML Help (which wasn't broken). I've never actually tried it, but along with that change was a hack that allowed you to call the API in a way that it would create an interface, and then you'd call the API again to release that interface. You start off with HH_INITIALIZE and end with HH_UNINITIALIZE. Another alternative would be to set the HH_GPROPID_SINGLETHREAD property to TRUE -- that might get HTML Help back onto the parent's thread.
Fix:
More Tips:
- As described by Ralph above, you can try using the HH_INITIALIZE, HH_UNINITIALIZE commands. These are documented in the HH Workshop online help.
- Call HH_CLOSE_ALL earlier. Get more space between the HH_CLOSE_ALL and your call to UnloadLibrary. In VB and Delphi you would perform the call on the Form QueryUnload _not_ on the Form Close or Destroy.
- Marcel van Brakel seemed to fix it by calling Sleep(0); immediately after the call to HH_CLOSE_ALL. Again providing more time for the rogue thread to return.
Here is an alternative to using HH_CLOSE_ALL. What I do with my applications is keep the handle of the HH Windows when making a help call: _HHwinHwnd := htmlhelp(...) and on shutdown call:This is 10 times faster code, and eliminates the need for HH_CLOSE_ALL completely.
if IsWindow(_HHwinHwnd) then
SendMessage( _HHwinHwnd, wm_close, 0, 0 );
Also, as programming wizard Roland Mechling points out, don't blindly call HH_CLOSE_ALL on shutdown. If a user does not have HTML Help installed then this call will crash your application. Here is safer code. Notice we are checking if HH is installed before calling HtmlHelp();
procedure HHCloseAll;
begin
If @HH.HtmlHelp <> Nil then //HH API is available
begin
HH.HtmlHelp(0, nil, HH_CLOSE_ALL, 0);
Sleep(0);
end;
end;
Welcome to CnPack Forum (http://bbs.cnpack.org/) | Powered by Discuz! 5.0.0 |