2009-09-08 24 views
2

我们最大的一个旧VB6应用程序中有一些代码允许其他应用程序(包括某些dotNET应用程序)通过Windows消息传递一个ID - 然后使用此ID由VB6应用程序以常规的Windows窗体加载条目。消息挂钩在用户登录和验证后添加,并在注销后删除。VB6在使用活动Windows消息钩子进行调试时退出

Public Sub HookClaimFinderCall() 
    lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc) 
End Sub 

Public Sub UnhookClaimFinderCall() 
    Dim temp As Long 
    If gHW <> 0 Then temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc) 
End Sub 

Private Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long 
    If uMsg = WM_FINDCLAIM Then 
     MasterFindClaim lParam 
    End If 
    WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam) 
End Function 

但是,这有两个问题。第一个涉及到Visual Studio 6.如果代码正在调试,并且出现错误以显示“Continue End Debug帮助”对话框,则按下End立即退出Visual Studio(丢失任何未保存的更改)。如果消息挂钩尚未激活,则不会发生这种情况。是什么导致了这种情况,并且我能做些什么来阻止它加载加载该代码的代码?其次,如果用户退出应用程序而没有正确注销(通过任何方式),那么消息挂钩会发生什么?

我希望我有就在上述所有条款...

回答

5
  1. 你会得到崩溃(或消失VB6)如果你启动一个全局钩子,并试图在VB6调试。 VB6有点像模拟器,它并不完全重复VB6应用程序的运行时间,并且挂钩是其失败的一个方面(尽管如果你明白发生了什么,它不会被指责)。对于我们在应用程序中使用的所有全局钩子,我们检查VB6是否在IDE模式下运行(有几种方法可以执行此操作),如果是,请不要运行全局钩子。如果你绝对必须运行全局钩子,不要停止调试器中的应用程序 - 使用debug.print或其他方式,但不要停止应用程序,否则在“消失”之前你会有几秒到几秒的时间。
  2. 尽管您应该在退出应用程序之前解除绑定,但当消息泵遇到挂钩发生的应用程序的钩子和句柄不再存在时,忽略该钩子的操作相当复杂。现在,如果您运行应用程序并退出成千上万次,它可能会累积起来,但我认为这是您最担心的问题。
3

克里斯的答案是正确的。一些额外的要点。

  • 严格来说,这是子类化而不是消息挂钩。
  • 在您的WindProc中检测WM_NCDESTROY并在收到该消息时解除绑定也是很好的做法。该消息意味着窗口即将被销毁 - 如果用户退出应用程序,则应该收到该窗口,无论他们如何操作。
  • 在Windows 2000及更高版本中有一些API调用可以更容易地管理子类。与往常一样,卡尔彼得森拥有优秀的VB6代码here
+0

因此,而不是在我的应用程序的主卸载事件'unhook',我应该监视WM_NCDESTROY在相关的窗口,并在那里调用UnhookClaimFinderCall? – MartW 2009-09-08 20:36:24