2014-10-16 270 views
2

我工作在一個非常古老的VB6應用程序,這仍然是我們公司的主要項目。在開始這個項目之前,我從未使用過Visual Basic中的VB6。我遇到了很多有doevents的地方,以保持表單的響應性,並且我越深入挖掘doevents所做的更多工作,當我試圖調試代碼時,我不得不撓頭。VB6查看消息隊列

我正在研究一種方法,可能會告訴doevent實際上是否會在我們碰到那行代碼時做任何事情。我希望是否有人對窗口泵和消息隊列有更多的瞭解,可以告訴我,我的方法能否有效告訴我這種方法是否可行。 我正在嘗試使用PeekMessage來查看它們是否在隊列中的任何消息就在我打開一個doevents行之前。

Public Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" (lpMsg As msg, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long 

Public Type POINTAPI 
    X As Long 
    Y As Long 
End Type 

Public Type msg 
    hWnd As Long 
    Message As Long 
    Wparam As Long 
    lParam As Long 
    time As Long 
    pt As POINTAPI 
End Type 

Public Sub PeekAtMessages() 
     Dim oPeekMessage As msg 
     Dim bPeekMessage As Boolean 
     Dim lCtr As Long 
     bPeekMessage = True 

     bPeekMessage = PeekMessage(oPeekMessage, frmMain.hWnd, 0, 0, 0) 
     Debug.Assert bPeekMessage = True 
     Debug.Print "DoEvents: Message= Hex(" & Hex(oPeekMessage.Message) & ") Dec(" & oPeekMessage.Message & ") hWnd=" & oPeekMessage.hWnd & " lParam=" & oPeekMessage.lParam & " time=" & oPeekMessage.time & " Wparam=" & oPeekMessage.Wparam 
End Sub 

Public Sub MyDoEvents() 
     PeekAtMessages 
     DoEvents 
End Sub 

所以,我希望,當我打電話MyDoEvents我只會打Debug.Assert bPeekMessage = True如果沒有消息是在隊列中。這將允許我通過舊的未註釋的代碼來判斷一個doevents是否真的做了一些事情。

我測試了這一點,看起來我沒有發生任何事件時只碰到Debug.Assert,但我仍然不知道我的發現是否正確/可靠。有沒有其他人有嘗試查看doevent即將做什麼的經驗?

+0

僅當MyDoEvents運行時沒有消息在隊列中等待時,並不能保證沒有可能是真的情況。 – 2014-10-16 23:33:33

+0

@EricJ。是的,我明白了,我發現了一些地方,當它通過它們時,有一些是隊列中的東西,而第二次是它通過隊列中沒有任何東西。儘管消息代碼含糊其辭,但我並沒有試圖用這種方法去除「doevents」,只是爲了可能看到他們即將做的事情。 – 2014-10-16 23:35:20

+0

你得到一個很高興的工作在一個非常古老的VB6應用程序,這是你公司的主要項目 – rupweb 2017-06-27 11:09:39

回答

1

要記住的是,DoEvents是一個神奇的詞。那些模糊或根本不知道它做什麼的人會隨機嘗試它以防萬一。

VB6清除它自己的消息隊列,然後調用Sleep(0),這意味着所有其他應用程序都可以清除隊列。

當然,VBRuntime將你的代碼和執行VB6事件進行交互有着與多線程相同的問題,全局/靜態變量可以被訪問,部分更新等等。我從來沒有見過DoEvents聲明或任何思想的同步已經給了它。

Spy ++窗口消息spyer包含在VB6和SDK中。

在Windows中,某些消息按需生成。定時器,畫圖和其他一些實際上並不在隊列中。如果隊列爲空並且程序查詢,則Windows會查看是否設置了繪畫或其他標誌。如果是這樣,則生成一條消息並清除該標誌。因此,Paint等是FLAGS而不是隊列中的消息。

+0

是的我的團隊中的每個人都談論他們,他們也像魔術一樣,這真的讓我很煩惱,人們正在使用它們,他們在做什麼。謝謝,儘管在與他們一起工作時做出了更有教育的決定,但這對我確實有幫助。我將研究同步,看看我是否可以在我的一個問題領域實施它。我們有一個checkscaning類,在主窗體中的另一個項目中,它遍佈着'doevents' ... – 2014-10-17 23:27:41

+1

我認爲這些規則將不會訪問任何全局的東西 - 在過程中使用DoEvents之後打開文件,變量等。同時確保程序在任何情況下都不能重新進入。因爲單線程程序標誌應該足夠了。 – triggeradeadcat 2014-10-17 23:39:00