Go deep into getmessage and peekmessage

Source: Internet
Author: User

Go deep into getmessage and peekmessage

This article focuses on the process and steps for processing events and messages in windows. This is especially detailed when the system handles mouse and keyboard events. Through this article, you will have a comprehensive understanding of the Message Processing Mechanism in windows.

Concept

 

This article explains the internal operation of getmessage and peekmessage, and is also a kind of MS-DOS with "messages and messages in 16 bits? /Microsoft? Windows? The impact of the environment. We will discuss the following topics:

· System and Application Queue (hereinafter referred to as "program queue ")

· Getmessage and peekmessage Functions

· Message filtering

· WM _ quit message

· Concession and sleep

· Concession issues

· Waitmessage

 

16 bit MS-DOS/Windows environment and 32 bit Win32? /Windows NT? The environment has some important differences. Although these differences cannot be ignored here, we still regard them as legacy issues, which will be explained in future articles.

 

Queue

To understand the operation of getmessage and peekmessage, you must first understand Microsoft? Windows? How the operating system stores events and messages. There are two types of queues in Windows that work for this purpose: system queue and message queue.

 

Hardware input: system queue

In Windows, drivers are responsible for responding to interrupt services from hardware such as the keyboard and mouse. During the interruption time, the keyboard and mouse driver will call some entry points specified in user. EXE to report the occurrence of an event. In Windows, the optical pen driver that is used for Optical pen computing also calls these entry points in the original Optical pen event.

  

In windows3.1, a system queue is a queue with a fixed length of 120 entry spaces. In general, these "small rooms" are sufficient, but if the application is suspended or does not process any messages in time for a long period of time, the system queue may be filled up. If this happens, any new event that tries to add it to the system queue will cause the system to beep. (Note: In dos, if a program occupies all system resources for a period of time and the machine cannot respond, if you press and hold a key, you will hear the sound of the chassis horn)

 

Sent messages and program queues

When an application starts, a queue is created accordingly. Program queues (sometimes called task queues) are often used to store messages that are being sent to a window of the application. Messages in the unique resident program queue are those explicitly sent by postmessage or postappmessage. (Sendmessage never uses the system queue) The postquitmessage function does not send a message to the program queue. (Wm_quit messages will be discussed below)

By default, each program queue can maintain eight messages. Generally, this is enough because postmessage is rarely used. However, if an application attempts to forcibly call many postmessages to an application, such applications will use the setmessagequeue function to increase the length of the message queue. You must be careful to use the setmessagequeue function, because it deletes the current program queue and creates a new queue of the expected size at any time. At this time, all messages in the old queue will be destroyed. Therefore, it must be called before all other application programming interfaces (APIS) in your winmain routine or after the application uses peekmessage to clear the queue explicitly.

 

How does getmessage and peekmessage work?

In Windows, getmessage and peekmessage execute the same code. The biggest difference between the two is that no message is returned to the application. In this case, peekmessage returns a null value to the application, and getmessage will sleep the application at this time. There are some other differences between them, which we will discuss below, but they are quite minor.

 

Getmessage and peekmessage Logic

The following describes the common code of getmessage and peekmessage in windows3.1 step by step.

Tip: The following steps are sorted by priority of the message type. For example, the message sent is always returned before the keyboard and mouse messages, and the keyboard and mouse messages are reversed before the drawing message, and so on.

1.       Check whether messages exist in the program queue serving "active tasks. If yes, delete the message first and return it to the application. Then, the getmessage and peekmessage in the application call some code to receive the message from the program queue, which is generated by the dynamic link library (DLL) called by the application. Remember, only messages sent by postmessage are resident in this queue.

2.       Check the message against all messages and form handle filters. If the message does not match the specified filter, the message is left in the program queue. If there are other messages after this message in the queue, the next message will be processed.

3.       If there is no message in the program queue, the system will scan the events in the system queue. This process is quite complex and we will add XX in the "scan system queue" section below. Generally, the system queue header event is used by this application, and the system will convert it into a message, and return the message to the application (it will not be placed in the application queue first ). Note that the process of scanning the system queue may result in the current active application giving control to other applications.

4.       If no event is waiting for processing in the system queue, check all forms related to the current application (task) to determine the update area. When a part of a form needs to be re-painted, an update area is created on the part of the form. This area will be combined with all existing update areas in the form and stored in the internal form struct. If getmessage or peekmessage finds that some forms have some unprocessed update areas in this task, a wm_paint message is generated and returned to the application for that form. Wm_paint never resides in any queue. At this time, an application will continuously receive wm_patin messages for a form until the update area is cleared by beginpaint/endpaint, validaterect, or validatergn.

5.       If no form needs to be updated in this task, getmessage and peekmessage will give control at this point, unless the peekmessage call is set to the pm_noyield attribute.

6.       When a concession is returned, check whether a timer expires in the current task. If yes, create a wm_timer message and return it. It occurs not only on the timer that "returns a wm_timer message to the form", but also on the timer that "calls a timer processing process. For more information, see the Microsoft Developer Network (msdn) Cd (including technical articles, Windows articles, core and driver articles) article timers and timing in Microsoft Windows ).

7.       If this application does not have a timer event service and an application is being terminated, the code will try to narrow down the local memory heap of the graphic device interface (GDI. Some applications, such as drawing applications (like paintbrush ?), A large amount of heap memory is allocated to GDI. When the application stops releasing these objects, the local memory heap of GDI expands with the free space. To restore idle space, localshrink is called in the memory heap of GDI during getmessage/peekmessage processing. This is completed once, and each time an application is terminated.

8.       At this time point, the Code forks into two channels. One is that the Code returns a valid message at will, and the other is a message or event that is not processed by this application at all, the Code determines which of the peekmessage and getmessage is called.

· Peekmessage. If the peekmessage is called and the pm_noyield flag is set, peekmessage returns a null value at the moment. The NULL return value indicates that there are no messages to be processed. If the pm_noyield flag is not set, peekmessage gives control at the moment. It will not sleep, but it will give a single chance to execute other prepared applications. (See the following section for details about the difference between concession and sleep) When concession is returned, peekmessage directly returns control to the application and a null value, it indicates that the application has no messages to process.

? Getmessage. At this moment, getmessage will sleep and wait for the application until some events need to be awakened. Control does not return to the application that calls getmessage until a message that must be processed by the application appears. Once the application crashes from the sleep state, the cycle inside the getmessage will return to the beginning (step 1 ).

 

Wh_getmessage hook

Before getmessage and peekmessage return a message to the called application, a test is performed to verify whether a wh_getmessage hook exists. If one of them has been installed, the hook will be called. If peekmessage does not find any available message and a null value is returned, this hook will not be called. During hook processing, you cannot know whether getmessage is called or peekmessage is called.

 

Scan System queue

In summary, events in the system queue are only records of hardware events. The main task for code scanning system queues is to create a message from these events and determine which form will receive the message.

The first time the Code finds an event in the system queue header, it will not be deleted immediately. Because mouse and keyboard events are only two types of events in the queue, the code will be split (Translator's note: similar to the switch statement in C) and each type of event will be processed separately.

 

Process mouse events in the system queue

The following describes how to process mouse events.

1.First, the corresponding form of the event screen coordinate is calculated. This calculation starts with a desktop form (call the form and click test), scanning every form (including child forms) from the beginning to the end until a form containing the mouse coordinate points is found, in addition, this form does not contain any child forms that contain the coordinate point.

Figure 2. Mouse event form click Test

For example, if the arrow in Figure 2 represents the current mouse position, any mouse action, like clicking the mouse key, will generate an event that will generate a message in Form B.

2.If a form uses setcapture to capture the mouse, the system queue scan code passes the normal click test and returns all the mouse messages to the captured form. For example, if setcapture is called for form a in Figure 2, all mouse actions at the position indicated by the arrow will generate messages in Form A instead of Form B.

3.If the event to be processed is a "Mouse press" event (any mouse Key), the code checks whether the event is converted to a double-click event. You can find the description about double-click conversion in ask dr. Gui #5 on the Microsoft Developer Network (msdn) Cd (Technical article, ask dr. GUI. Essentially, if the increment of time and distance is within the permitted range in the two mouse key press events, this event generates a double-click message, otherwise, it generates a standard "Press" event. All mouse events generate standard mouse messages, and double-click the test only in the form specified by the mouse event, including cs_dblclks.

4.A message is constructed from a mouse event.

5.If you click the mouse to test whether the event occurs in a non-customer area of a form, such as a border or title bar, the constructed message is mapped to the corresponding non-customer area message. For example, a wm_mousemove event will be reflected in the message "wm_ncmousemove.

6.Check the message against all specified message filters. (See "message range filtering and form handle filtering" below.) If the message does not match the filter, run the "system queue scan" code again to view the next message in the queue.

7.If the mouse message needs to go to the relevant form of another task different from the current task, the event will be left in the system queue, and if the task that will process the message is in sleep, will be awakened. This newly awakened task will not run immediately at the moment, but will only be marked as ready to run. If the message goes to another task and no event to be processed is found in the system queue, the system queue scan code returns the getmessage/peekmessage main code. For more information, see "concession and sleep" below.

8.If a mouse hook is installed, it will be called at the moment. If the mouse hook returns a non-zero value, the mouse event is ignored and deleted from the system queue. Then, the system queue scan code starts again. If the hook returns zero, the processing continues.

9.If the message is a "mouse-pressed" message, "system queue scan" activates the form as follows before returning the message.

? It looks up the form's "final top-level parent form" along the parent chain until it meets each other.

? It uses sendmessage to send a wm_mouseactivate message to the form's "final top-level parent form.

? The value returned from wm_mouseactvate will be tested below:

A)     If the returned value is null, ma_activate, or ma_activateandeat, The activatewindow function is called to activate the "final top-level parent form ".

B)    If the returned value is ma_noactivate or ma_noactivateandeat, the form is not activated.

Note: ma_activateandeat and ma_noactivateandeat will cause the "Mouse key press" event to be deleted from the system queue without generating a mouse press message.

C)    Finally, a wm_setcursor message is sent to the form, allowing the form to set the outline of the pointer.

10. If the mouse hook is called and the current mouse event is deleted from the system queue, check the "computer-based training" (CBT) Hook. If a CBT hook is installed, it will carry the hcbt_clickskipped hook code to call it.

11. The button status table contains three entries for tracking the mouse button status. These buttons are assigned to the virtual key code (vk_lbutton, vk_rutton, and vc_mbutton). They are used together with getkeystate to determine whether the mouse key is played or pressed. Before returning the mouse message, the "system queue scan" Code sets a key status table for (to pop up or press the message) and deletes the message from the system queue. If the peekmessage carries pm_noremove when it is called, The key status table will not be modified.

 

Handle Keyboard Events in the system queue

1.Check whether the ctrl key is pressed and the current event is pressed by the ESC key. If yes, the user -- direct form -- displays the task manager form. A wm_syscommand message will be sent to the activated form, and the wparam parameter is SC _taskdetail. Then press the keyboard to delete the event from the system queue, and the "system queue scan" code will start from the beginning again. If the activated form is a system module or a displayed "hard" system module message box (for example, a "int" 24-hour system error message box, or a MessageBox function that uses the mb_iconhand mb_systemmodal parameters) will be discarded.

2.Next, try to check whether the current event is a print screen press event. If yes, any activated form or entire desktop will be taken as a bitmap snapshot and saved to the clipboard. If the Alt key is pressed, an image of the activated form is copied to the clipboard; if not, the entire desktop is copied. Then press the print screen key to delete the event from the system queue. The "system queue scan" code will start from the beginning again. If a "hard" system module message box is displayed, this operation is ignored.

3.Next, check the hotkey. You can use the program manager to define a key event used to run an application. These keys are called hotkeys. If the current event is a key event, it will be tested to match the defined hotkey. If a match is found, a wm_syscommand message is sent to the activated form and the wparam parameter is SC _hotkey. Then press the keyboard to delete the event from the system queue, and the "system queue scan" code will start from the beginning again. If the activated form is a system module or a displayed "hard" system module message box, the test is skipped.

4.Generally, all keyboard messages (such as wm_keydown and wm_char) Go to the form with input focus. If the form with the input focus is associated with another currently executed task, the event will be left in the system queue, in addition, the task with a "focused form" will be awakened (if it is sleep ). The system queue scan code returns the primary getmessage/peekmessage code just as it does not need to discover any event to be processed. For more information, see "concession and sleep" and "how the application is awakened" below.

5.If there is no form with input focus, the keyboard message will go directly to the currently activated form without being translated into system key messages (such as wm_syskeydow, wm_syschar, and so on ).

6.Check the message against all specified message filters. (See "message range filtering and form handle filtering" below.) If the message does not match the filter, run the "system queue scan" code again to view the next message in the queue.

7.If the event is returned to the current task, it will be deleted from the system queue, unless the peekmessage is specified as the pm_noremove flag. See the "pm_noremove tag of peekmessage" below to learn more about events not deleted from the queue.

8.If a keyboard hook is installed, it will be called at the moment. If an event is deleted from the system queue, the hook call is accompanied by the hc_action attribute. If the event is not deleted from the system queue, the hook call has the hc_norem attribute.

9.If the keyboard hook is called and the current key event is deleted from the system queue, check the existing CBT hook. If a CBT hook is installed, call it and carry the hcbt_keyskipped hook code.

10.Finally, the message is added to the main getmessage/peekmessage code.

 

Peekmessage and pm_noremove

By default, peekmessage andGetmessage deletes messages and events from the system queue. However, sometimes an application may need to scan existing messages in the queue without deleting them. For example, an application is performing some processing, and these processing processes are expected to terminate as soon as available messages are found ".

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.