> There are often times when for various reasons you need to allow
> pending messages in the queue to be processed but you would much
> rather not have errant mouse or keyboard events occur at that time.
> For example, you need to call Doevents sometimes to resolve paint
> problems, or when loading an HTML document into the web browser
> control, to allow messages to be processed before proceeding
> (normally, you loop, calling doevents, until document.readystate goes
> to "complete" - you can use the browser control events provided but
> they are not reliable and if you want to synchronously load a document
> the code is still going to have to spin somewhere).
> Doevents is also often required after setting focus to a control.
> But the problem is that doevents allows your code to be re-entered
> with mouse and keyboard events that you may not be prepared to handle
> at that time. This results in code that has static gate flags to
> protect it from re-entrancy. An even more annoying problem is that the
> keystrokes must then be discarded, so that typeahead is lost.
> The code below provides a replacement for DoEvents that will not
> remove any pending mouse or keyboard events from the message queue,
> but which will pump any other messages to their destination. This
> preserves typeahead while allowing your code to yield where needed.
> Private 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
> Private Declare Function TranslateMessage Lib "user32" (lpMsg As MSG)
> As Long
> Private Declare Function DispatchMessage Lib "user32" Alias
> "DispatchMessageA" (lpMsg As MSG) As Long
> Private Const QS_POSTMESSAGE = &H8
> Private Const PM_NOREMOVE = &H0
> Private Const PM_REMOVE = &H1
> Private Const QS_HOTKEY = &H80
> Private Const QS_TIMER = &H10
> Private Const QS_SENDMESSAGE = &H40
> Private Const PM_NOYIELD = &H2
> Private Const QS_MOUSEMOVE = &H2
> Private Const QS_MOUSEBUTTON = &H4
> Private Const QS_MOUSE = _
> (QS_MOUSEMOVE Or QS_MOUSEBUTTON)
> Private Const QS_KEY = &H1
> Private Const QS_INPUT = (QS_MOUSE Or QS_KEY)
> Private Const QS_PAINT = &H20
> Private Const PM_QS_INPUT = (QS_INPUT * (2 ^ 16))
> Private Const PM_QS_PAINT = (QS_PAINT * (2 ^ 16))
> Private Const PM_QS_POSTMESSAGE = _
> ((QS_POSTMESSAGE Or QS_HOTKEY _
> Or QS_TIMER) * (2 ^ 16))
> Private Const PM_QS_SENDMESSAGE = _
> (QS_SENDMESSAGE * (2 ^ 16))
> Private Type POINTAPI
> x As Long
> y As Long
> End Type
> Private Type MSG
> hwnd As Long
> message As Long
> wParam As Long
> lParam As Long
> time As Long
> pt As POINTAPI
> End Type
> Public Sub Yield()
> Dim m As MSG
> 'process any posted messages on the stack - not keyboard or mouse
> messages
> While PeekMessage(m, 0, 0, 0, PM_REMOVE Or PM_QS_POSTMESSAGE Or
> PM_QS_PAINT)
> TranslateMessage m
> DispatchMessage m
> Wend
> End Sub