Google
 
Web undim.blogspot.com
Visual Basic developer's world

Saturday, August 19, 2006
DoEvents evolution; the API approach.

Many of us have used several times DoEvents, to supply a bit of air to our App, on heavy-duty times such as loops for updates or inserts on recordsets etc. As we most know, DoEvents processes Windows messages currently in the message queue. But what if we wanted to execute DoEvents only in times, when we want to allow user (Keyboard and Mouse) input?

If there was such a function to inspect the message queue for user input, we would have a main benefit:

We would speed up our loops ‘cause we would process all the messages in
the queue (with DoEvents) only on user input. It’s faster to check for
a message than to process all messages every time.

API provides us with such a function: It’s called GetInputState and you can locate it in user32 library.

Here is the declaration:

Public Declare Function GetInputState Lib"user32" () As Long

The GetInputState function determines whether there are mouse-button or keyboard messages in the calling thread's message queue. If the queue contains one or more new mouse-button or
keyboard messages, the return value is nonzero else if there are no new mouse-button or keyboard messages in the queue, the return value is zero.

So we can create an improved DoEvents with a Subroutine
like this :

Public Sub newDoEvents()
If GetInputState() <> 0 then DoEvents
End Sub


You can use GetInputState() with many variations for example :


uCancelMode = False

Do until rs.Eof

Rs.AddNew

(..your source here)

Rs.Update

Rs.MoveNext

If GetInputState() <> 0 then

DoEvents

If uCancelMode Then Exit Do

End If

Loop

Msgbox “Finished.”


…or

we could use it in a ScreenSaver e.t.c.

Let’s go a little further now and see what exactly is behind GetInputState().

It is another API function located in User32 as well; GetQueueStatus()
The GetQueueStatus function indicates the type of messages found in the calling thread's message queue. Here are the flags that GetQueueStatus uses :

QS_ALLEVENTS An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue.

QS_ALLINPUT Any message is in the queue.

QS_ALLPOSTMESSAGE A posted message (other than those listed here) is in the queue.

QS_HOTKEY A WM_HOTKEY message is in the queue.

QS_INPUT An input message is in the queue.

QS_KEY A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN
message is in the queue.

QS_MOUSE A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, M_RBUTTONDOWN, and so on).

QS_MOUSEBUTTON A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).

QS_MOUSEMOVE A WM_MOUSEMOVE message is in the queue.

QS_PAINT A WM_PAINT message is in the queue.

QS_POSTMESSAGE A posted message (other than those listed here) is in the queue.

QS_SENDMESSAGE A message sent by another thread or application is in the queue.

QS_TIMER A WM_TIMER message is in the queue.

(I believe that GetInputState() is a GetQueueStatus(QS_HOTKEY Or QS_KEY Or QS_MOUSEBUTTON))

With these constants you can create your own GetInputState function that fits your needs. For example you can create a custom function that issues DoEvents when it’ll detects not only a Keyboard or Mouse Key input, but also a WM_PAINT signal.
Why’s that? ‘cause in your loop you might need to update the screen so you must let your custom function process the specific signal.


Look at this :


Public Const QS_HOTKEY = &H80
Public Const QS_KEY = &H1
Public Const QS_MOUSEBUTTON = &H4
Public Const QS_MOUSEMOVE = &H2
Public Const QS_PAINT = &H20
Public Const QS_POSTMESSAGE = &H8
Public Const QS_SENDMESSAGE = &H40
Public Const QS_TIMER = &H10
Public Const QS_ALLINPUT = (QS_SENDMESSAGE Or QS_PAINT Or _
QS_TIMER Or QS_POSTMESSAGE Or QS_MOUSEBUTTON Or QS_MOUSEMOVE Or _
QS_HOTKEY Or QS_KEY)
Public Const QS_MOUSE = (QS_MOUSEMOVE Or QS_MOUSEBUTTON)
Public Const QS_INPUT = (QS_MOUSE Or QS_KEY)
Public Const QS_ALLEVENTS = (QS_INPUT Or QS_POSTMESSAGE Or QS_TIMER Or QS_PAINT Or QS_HOTKEY)

Public Declare Function GetQueueStatus Lib "user32" (ByVal qsFlags As Long) As Long

Public Function cGetInputState()

Dim qsRet As Long
qsRet = GetQueueStatus(QS_HOTKEY Or QS_KEY Or QS_MOUSEBUTTON Or QS_PAINT)
cGetInputState = qsRet
End Function


With this function you can trigger the DoEvents to be executed only when the message queue contains Key input, Mouse button or a WM_PAINT signal.

Call it like this….


. . if cGetInputState() <> 0
then DoEvents

Labels: , ,


posted by Admin @ 6:50 AM  
1 Comments:
  • At 11:46 AM, Blogger TimAtAon said…

    Some questions about performance tweaking of cGetInputState (since generally this whole discussion is about avoiding doevents sluggishness):

    Instead of returning a variant from cGetInputState, why not return a Long?

    Why even have an intermediate storage for GetQueueStatus call - wouldn't setting the cGetInputState return value to the GetQueueStatus function's return value be faster?

    Would it be quicker to abs the cGetInputState function result before returning it so a faster test could be used in calling code (to test > 0 instead of <>0)? I guess the question is whether an abs and a > test is faster than just a <> call. Intuitively, I suspect the latter is, but sometimes, it is surprising once you do the timing. Thus testing should be done to be definitive.

     

Post a Comment

Important


Don't spam. Your spam posts are always removed.



<< Home
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
About Me

Name: Admin
Home: The NeverLands
About Me: A source code wonderer since the early 80s with my first ZX81 by Sinclair, home computer.
See my complete profile
Previous Post
Archives
Must-See Places
ΣΚΛΗΡΥΝΣΗ ΚΑΤΑ ΠΛΑΚΑΣ - ΕΓΚΕΦΑΛΟΣ - ΕΓΚΕΦΑΛΟΓΡΑΦΗΜΑ - ΑΝΟΙΑ - ΝΕΥΡΟΛΟΓΟΣ - ΨΥΧΙΑΤΡΟΣ - ΛΟΙΜΩΔΗΣ ΜΟΝΟΠΥΡΗΝΩΣΗ - ΠΑΡΚΙΝΣΟΝ - ΑΓΧΟΣ - ΚΑΤΑΘΛΙΨΗ - ALZHEIMER - EPSTEIN BARR eurolife
e-LaUgHs :-)
Template By
Free Blogger templates