2009-09-08 74 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