Deep into the message mechanism in Windows kernel--c++

Source: Internet
Author: User
Tags getmessage message queue

In the article "message mechanism of programming thought", we talk about the concept of the message and the simulation of the message mechanism, this article will further talk about the message mechanism in C + +.

Analysis of core principles from simple examples

Before we talk, let's look at a simple example: Create a window and two buttons to control the background color of the window. The effect is as follows:


Figure 2:

Win32Test.h

#pragma once#include <windows.h>#include <atltypes.h>#include <tchar.h>//resource ID#define ID_BUTTON_DRAW#define ID_BUTTON_SWEEP 1001//Registration window classATOM Appregisterclass (hinstance hinstance);//Initialization windowBOOL InitInstance (HINSTANCE,int);//Message handler function (also called window procedure)LRESULTCALLBACKWndProc (HWND, UINT, WPARAM, LPARAM);//(white background) button eventvoidOnbuttonwhite ();//(gray Background) button eventvoidOnbuttongray ();//Draw EventsvoidOnDraw (hdc hdc);

Win32Test.cpp

#include "stdafx.h"#include "Win32Test.h"//character array length#define Max_loadstring//global variableHINSTANCE HInst;//Current instanceTCHAR g_sztitle[max_loadstring] = TEXT ("Message Process");//Window titleTCHAR g_szwindowclass[max_loadstring] = TEXT ("Apptest");//Name of the window classHWND G_hwnd;//Window handleBOOLG_bwhite =false;//Whether it is a white background//winmain Entry FunctionintApientry _tWinMain (hinstance hinstance, hinstance hprevinstance, LPTSTR lpCmdLine,intnCmdShow) {unreferenced_parameter (hprevinstance); Unreferenced_parameter (lpCmdLine);//Registration window class    if(! Appregisterclass (hinstance)) {return(FALSE); }//Initialize the application window    if(! InitInstance (HINSTANCE, ncmdshow)) {return FALSE; }//message loopMSG msg; while(GetMessage (&msg,NULL,0,0) {TranslateMessage (&msg);    DispatchMessage (&AMP;MSG); }return(int) msg. WParam;}//Registration window classATOM Appregisterclass (hinstance hinstance) {wndclassex Wcex; Wcex. cbsize=sizeof(Wndclassex); Wcex. Style= Cs_hredraw |    Cs_vredraw; Wcex. Lpfnwndproc= WndProc; Wcex. Cbclsextra=0; Wcex. Cbwndextra=0; Wcex. HInstance= HInstance; Wcex. Hicon= LoadIcon (NULL, idi_application); Wcex. Hcursor= LoadCursor (NULL, Idc_arrow); Wcex. Hbrbackground= (Hbrush) (color_window+1); Wcex. Lpszmenuname=NULL; Wcex. lpszClassName= G_szwindowclass; Wcex. HICONSM=NULL;returnRegisterClassEx (&AMP;WCEX);}//Save the instantiation handle and create the main windowBOOLInitInstance (HInstance hinstance,intnCmdShow) {hInst = hinstance;//save handle to global variablesG_hwnd = CreateWindow (G_szwindowclass, G_sztitle, Ws_overlappedwindow,0,0, -, -,NULL,NULL, HINSTANCE,NULL);//Create buttonHWND Hbtwhite = CreateWindowEx (0, L"button", L"White", Ws_child | ws_visible | Bs_text, -, -, -, -, G_hwnd, (HMENU) Id_button_draw, HInst,NULL); HWND Hbtgray = CreateWindowEx (0, L"button", L"Grey", Ws_child | ws_visible | Bs_center, -, -, -, -, G_hwnd, (HMENU) Id_button_sweep, HInst,NULL);if(!g_hwnd) {return FALSE;   } ShowWindow (G_hwnd, ncmdshow); UpdateWindow (G_hwnd);return TRUE;}//(window) Message processingLRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM WPARAM, LPARAM LPARAM) {intWmid, Wmevent;    Paintstruct PS; HDC hdc;Switch(message) { CaseWm_command:wmid = LoWord (WParam);//wmevent = HiWord (WParam);        Switch(Wmid) { CaseId_button_draw:onbuttonwhite (); Break; CaseId_button_sweep:onbuttongray (); Break;default:returnDefWindowProc (hWnd, message, WParam, LParam); } Break; CaseWM_PAINT:HDC = BeginPaint (hWnd, &ps);        OnDraw (HDC); EndPaint (HWnd, &ps); Break; CaseWm_destroy:postquitmessage (0); Break;default:returnDefWindowProc (hWnd, message, WParam, LParam); }return 0;}//Event handling//Press the event when HbtwhitevoidOnbuttonwhite () {g_bwhite =true; InvalidateRect (G_hwnd,NULL,FALSE);//Refresh window}//Press the event when HbtgrayvoidOnbuttongray () {g_bwhite =false; InvalidateRect (G_hwnd,NULL,FALSE);//Refresh window}//Draw events (redraw the image each time the refresh is refreshed)voidOnDraw (hdc hdc) {point oldpoint; Setviewportorgex (HDC,0,0, &oldpoint);    RECT Rcview; GetWindowRect (G_hwnd, &rcview);//Get the handle of the canvas sizeHbrush hbrwhite = (hbrush) getstockobject (White_brush); Hbrush Hbrgray = (hbrush) getstockobject (Gray_brush);if(G_bwhite)    {FillRect (hdc, &rcview, hbrwhite); }Else{FillRect (hdc, &rcview, Hbrgray); } Setviewportorgex (hdc, Oldpoint. x, Oldpoint. Y,NULL);}

In the above example, the message flows through the following process:


Figure 3: The process of message flow
This is in line with the "message mechanism of programming ideas" in Figure 1 (Message mechanism principle) is consistent, this is the core part of Windows Messaging mechanism, is also the core of Windows API development. Windows systems and programs under Windows are message-based and event-driven.
The role of RegisterClassEx is to register a window that must be registered with the Windows system to obtain a unique identity before calling CreateWindow to create a window.

while (GetMessage(&msg, NULL, 0, 0)){    TranslateMessage(&msg);    DispatchMessage(&msg);}

This while loop is a message loop that continuously fetches messages from the message queue and distributes the messages through DispatchMessage (&msg). Message Queuing is defined in the Windows operating system (we cannot see the code that corresponds to the definition), and for each executing Windows application, the system establishes a message queue, the application queue, that holds messages for various windows that the program may create. DispatchMessage will pass the message to the window function (that is, the message handler function) to deal with, that is, the WndProc function. WndProc is a callback function that is passed to the operating system through Wcex.lpfnwndproc when the window is registered, so the DispatchMessage distributes the message and the operating system calls the window function (WNDPROC) to process the message. For a callback function, refer to the callback function.
Each window should have a function responsible for message processing, and the programmer must be responsible for designing this so-called window function WndProc. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)the four parameters in the message are information about the messages (the handle of the message, the message type, and so on), and the functions are handled differently by switch/case according to the different message types. After receiving the corresponding type of message, the corresponding function can be called to deal with, such as Onbuttonwhite, Onbuttongray, OnDraw, which is the embryonic form of event processing. Invoking Defwindowproc,defwindowproc in default is the default message handler defined by the operating system, because all messages must be processed, and messages that the application does not process need to be handled by the operating system.

Definition and type of message

Windows messages are prefixed with wm_, meaning "windows message", such as Wm_create, WM_PAINT, and so on. The message is defined as follows:

typedef  struct  tagmsg{hwnd hwnd;    //the window handle that accepts the message         UINT message;    //message constant identifier, which is what we usually call the message number          WPARAM WPARAM;    //32 bit message, the exact meaning depends on the message value          LPARAM LPARAM;    //32 bit message, the exact meaning depends on the message value            DWORD time;    //the time the message was created              Point pt; //the position of the mouse/cursor in the screen coordinate system when the message was created } MSG;  

There are three main types of messages:
1. Command Message (WM_COMMAND): Command message is a command that the programmer needs the program to do certain things. Any message generated by the UI object is such a command message, possibly from a menu, accelerator key, or toolbar button, and so on, in Wm_command.
2. Standard window message: In addition to WM_COMMAND, any message beginning with WM_ is this category. The standard window message is the most common message in the system, which refers to the messages used by the operating system and the windows that control other windows. For example, CreateWindow, DestroyWindow, and MoveWindow will fire window messages, as well as mouse movements, clicks, and keyboard input are all part of this message.
3. Notification: This message is generated by the control in order to notify its parent window (usually a dialog window) of a situation. When a child control inside a window has something that needs to be notified to the parent window, it is now on. The notification message applies only to standard window controls such as buttons, list boxes, combo boxes, edit boxes, and Windows common controls such as tree view, List view, and so on.

Queue messages and non-queue messages

There is a system message queue in Windows, and for each executing Windows application, the system establishes a message queue, the application queue, that holds messages for various windows that the program may create.
(1) Queue message (Queued Messages)
Messages are saved in the message queue, and messages are retrieved from the message queue through a message loop and distributed to the various window functions to process, such as a mouse, keyboard message belongs to this kind of message.
(2) Non-queue messages (nonqueued Messages)
Is that the message is sent directly to the window function processing without passing through the message queue. such as: Wm_activate, Wm_setfocus, Wm_setcursor, wm_windowposchanged belong to this category.

The difference between PostMessage and SendMessage

The message sent by PostMessage is a queue message that posts the message to the message queue, the message sent by SendMessage is not a queue message, is sent directly to the window process, and the message is processed before it is returned.


Figure 4: Message Queuing

To prove the process, we can change the example above.
1. Add the definition of id_button_test in Win32Test.h

#define ID_BUTTON_TEST      1002

2. Send messages in Onbuttonwhite with SendMessage and PostMessage respectively
Events when Hbtwhite is pressed

void OnButtonWhite(){    true;    NULLFALSE);    //刷新窗口    0);    //PostMessage(g_hWnd, WM_COMMAND, ID_BUTTON_TEST, 0);}

3. Add Id_button_test judgment to the message loop

whileNULL00))    {        if (LOWORD(msg.wParam) == ID_BUTTON_TEST)        {            OutputDebugString(L"This is a ID_BUTTON_TEST message.");    // [BreakPoint1]        }        TranslateMessage(&msg);        DispatchMessage(&msg);    }

4. Increase id_button_test judgment in window processing function WndProc

case ID_BUTTON_TEST:    {        OutputDebugString(L"This is a ID_BUTTON_TEST message.");        // [BreakPoint2]    }    break;case ID_BUTTON_DRAW:    OnButtonWhite();    break;case ID_BUTTON_SWEEP:    OnButtonGray();    break;

Debugging with breakpoints we found that the Id_button_test message sent with SendMessage will only go into BreakPoint2, and postmessage send the Id_button_ Test will go into BreakPoint1 and BreakPoint2.


If you have any doubts and ideas, please give feedback in the comments, your feedback is the best evaluator! Due to my limited skills and skills, if the Ben Boven have errors or shortcomings, please understand and give your valuable advice!


======================== programming thought series of articles review ========================
Message mechanism of programming thought
Logging of programming ideas
Abnormal handling of programming thought
The regular expression of programming thought
An iterative device for programming ideas
Recursion of programming thought
The callback of programming thought

Deep into the message mechanism in Windows kernel--c++

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.