Message Mechanism and programming ideology mechanism of programming ideas

Source: Internet
Author: User

Message Mechanism and programming ideology mechanism of programming ideas

Message Mechanism of programming ideas Message mechanism starts from a story

Lu Yao's "ordinary world" was once again on fire because it was a TV series! Let's start from here. The novel begins with a scene like this:
Under the south wall root of a campus in a large courtyard dam in a high school in a half-mountain waist County, a dozen young men and women lined up by class, every shift's day-on-duty students are busy distributing meals to everyone ...... Vegetables are divided into Class A, Class B, and class C. The main type of dish a is potato, cabbage, and vermicelli. There are many meat slices. There is no meat for dish B, and dish C is only boiled with white radish. The staple food is also divided into three categories: white flour, corn flour, sorghum flour, white, yellow, and black, which represent three differences. The students play Europe, Asia, and Africa. Every person's meals were registered and paid for yesterday. In this long queue, the rich children with better scenery ranked first, students who are in poverty-stricken families and who are short of clothing can only be late after other students leave ......

Although this living example looks a little cool (we believe that you have been a student and may not be so cool), it is like the principle of message mechanism, perhaps the inspiration for the invention of the message mechanism is the original life! The students in the queue are message queues. When the students on duty distribute their meals, the messages are cyclically processed and the messages are processed.

What is a message?

What is a message? A message is a signal with certain information. If you click a window with the mouse, a message with the mouse is generated. If you enter characters on the keyboard, a message is generated. If you change the size of a window, a message is generated.
Where does a message come from? According to Von noriman's architecture, the computer consists of a memory, a memory, a controller, an input device, and an output device. Messages mainly come from input devices, such as keyboards, mice, and scanners, it can also be from windows and operating systems.
Three key points of the message mechanism: Message Queue, message loop (distribution), and message processing. Its structure is as follows:



Figure 1: Message Mechanism Principle

Message QueueIt is a type of queue for storing messages, with the features of first-in-first-out. Every time a message is generated, it is added to the Message Queue. In the Window, the message queue is defined in the operating system. A message queue is like a group of boys and girls waiting in a queue. In this group, Jing is better at the top and Jing is worse at the back. It can be understood as a priority queue! For more information about queues, see queue.
Message LoopIt is to continuously retrieve the first message from the Message Queue through a loop (such as while) and distribute the message. Similar to the example above, food is delivered on a daily basis.
Message ProcessingAfter receiving a message, it is processed according to different message types. In the preceding example, the students on duty receive messages for different levels of meals based on different types of meals, and the tickets in the hands of students receive messages.
EventIt is a specific processing based on the specific information of the received message. It is an event Response Function in the code. In the above example, it is a specific event for a middle school student to eat after receiving a meal.

Message Mechanism in C ++: Exploring core principles from a simple example

Before speaking, let's take a 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 1000 # define ID_BUTTON_SWEEP 1001 // register the window class ATOM AppRegisterClass (HINSTANCE hInstance); // initialize the window BOOL InitInstance (HINSTANCE, int ); // message processing function (also called Window Process) lresult callback WndProc (HWND, UINT, WPARAM, LPARAM); // (white background) button event void OnButtonWhite (); // (gray background) button event void OnButtonGray (); // draw event void OnDraw (HDC hdc );

Win32Test. cpp

# Include "stdafx. h "# include" Win32Test. h "// character array length # define MAX_LOADSTRING 100 // global variable HINSTANCE hInst; // the current instance TCHAR g_szTitle [MAX_LOADSTRING] = TEXT (" Message process "); // window title TCHAR g_szWindowClass [MAX_LOADSTRING] = TEXT ("AppTest"); // window class name HWND g_hWnd; // window handle bool g_bWhite = false; // whether it is a white background // The WinMain entry function int APIENTRY _ tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int n1_sho W) {UNREFERENCED_PARAMETER (hPrevInstance); UNREFERENCED_PARAMETER (lpCmdLine); // register the window class if (! AppRegisterClass (hInstance) {return (FALSE);} // initialize the application window if (! InitInstance (hInstance, nCmdShow) {return FALSE;} // message loop MSG; while (GetMessage (& msg, NULL, 0, 0) {TranslateMessage (& msg ); dispatchMessage (& msg);} return (int) msg. wParam;} // register the window class ATOM 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. h Instance = 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; return RegisterClassEx (& wcex) ;}// Save the instantiation handle and create the BOOL InitInstance (HINSTANCE hInstance, int nCmdShow) {hInst = hInstance; // save handle to the global variable g_hWnd = CreateWind Ow (g_szWindowClass, g_szTitle, WS_OVERLAPPEDWINDOW, 0, 0,400,300, NULL, NULL, hInstance, NULL); // create Button HWND hBtWhite = create1_wex (0, L "Button ", L "white", WS_CHILD | WS_VISIBLE | BS_TEXT, 100,100, 50, 20, g_hWnd, (HMENU) ID_BUTTON_DRAW, hInst, NULL); HWND hBtGray = create1_wex (0, L "Button", L "gray", WS_CHILD | WS_VISIBLE | BS_CENTER, 250,100, 50, 20, g_hWnd, (HMENU) ID_BUTTON_SWEEP, hInst, NUL L); if (! G_hWnd) {return FALSE;} ShowWindow (g_hWnd, nCmdShow); UpdateWindow (g_hWnd); return TRUE;} // (window) message Processing lresult callback WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) {case WM_COMMAND: wmId = LOWORD (wParam ); // wmEvent = HIWORD (wParam); switch (wmId) {case when: OnButtonWhite (); break; case ID_BUTTON_SWEEP: OnButtonGray (); break; default: return DefWindowProc (hWnd, message, wParam, lParam);} break; case WM_PAINT: hdc = BeginPaint (hWnd, & ps); OnDraw (hdc); EndPaint (hWnd, & ps); break; case WM_DESTROY: PostQuitMessage (0); break; default: return DefWindowProc (hWnd, message, wParam, lParam);} return 0 ;} // event processing // event void OnButtonWhite () {g_bWhite = true; InvalidateRect (g_hWnd, NULL, FALSE) When hBtWhite is pressed ); // refresh window} // event void OnButtonGray () {g_bWhite = false when hBtGray is pressed; InvalidateRect (g_hWnd, NULL, FALSE ); // refresh window} // draw events (re-draw images upon each refresh) void OnDraw (HDC hdc) {POINT oldPoint; SetViewportOrgEx (hdc, 0, 0, & oldPoint ); RECT rcView; GetWindowRect (g_hWnd, & rcView); // get the canvas size of the handle HBRUSH 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 preceding example, the message flow process is as follows:


Figure 3: Message Flow Process
This is consistent with Figure 1 (message mechanism principle), which is the core part of Windows message mechanism and the core part of Windows API development. Both Windows and Windows programs are message-based and event-driven.
RegisterClassEx registers a window. You must register a unique identifier with the windows system 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 retrieves messages from the message queue and distributes messages through DispatchMessage (& msg. Message Queue is defined in the Windows operating system (we cannot see the corresponding defined code). For every running Windows application, the system creates a message queue for it ", the application queue is used to store messages in various Windows that may be created by the program. DispatchMessage transmits the message to the window function (namely, the message processing function) for processing, that is, the WndProc function. WndProc is a callback function. In the registration window, wcex. lpfnWndProc is passed to the operating system. Therefore, after DispatchMessage is sent, the operating system calls the window function (WndProc) to process the message. For more information about callback functions, see callback functions.
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 are the relevant information of the message (the handle from which the message comes from, the message type, etc.). In the function, switch/case are used to process different messages based on different types. After receiving a message of the corresponding type, you can call the corresponding functions for processing, such as OnButtonWhite, OnButtonGray, and OnDraw. This is the prototype of event processing. DefWindowProc is called in default, and DefWindowProc is the default message processing function defined by the operating system. This is because all messages must be processed, and messages not processed by applications must be handed over to the operating system for processing.

Message definition and type

Windows messages are prefixed with WM _, which means "Windows Message", such as WM_CREATE and WM_PAINT. The message is defined as follows:

Typedef struct tagMsg {HWND hwnd; // The Window handle UINT message that receives the message; // message constant identifier, which is also known as the message number WPARAM wParam; // The specific additional information of a 32-bit message. The exact meaning depends on the message value LPARAM lParam; // The specific additional information of a 32-bit message. The exact meaning depends on the message value DWORD time; // The time when the message was created, POINT pt; // The cursor/cursor position in the screen coordinate system when the message was created} MSG;

There are three types of messages:
1. Command Message (WM_COMMAND): Command message is a command that the programmer needs to perform some operations on the program. All messages generated by the UI object are such command messages, which may come from menus, acceleration keys, or toolbar buttons and are displayed as WM_COMMAND.
2. Standard window message: Except for WM_COMMAND, all messages starting with WM _ are in this type. Standard window messages are the most common messages in the system. They are the messages used by the operating system and windows that control other windows. For example, CreateWindow, DestroyWindow, and MoveWindow will trigger window messages, move the mouse, and click, and keyboard input all belong to these messages.
3. Notification: this message is generated by the control to notify its parent window (usually a dialog box window) of a certain situation. When something happens to the child control in a window, which requires notifying the parent window, it will be playing now. The notification message is only applicable to standard window controls such as buttons, list boxes, Combo boxes, and edit boxes, as well as Windows public controls such as tree views and list views.

Queue messages and non-queue messages

In Windows, there is a system message queue. For every running Windows application, the system creates a "message queue" for it, that is, the application queue, stores messages of various Windows that may be created by the program.
(1) queue message (Queued Messages)
The message is saved in the message queue first, and the message is obtained from the Message Queue through the message loop and distributed to various window functions for processing. For example, the mouse and keyboard messages belong to such messages.
(2) Non-queue message (NonQueued Messages)
The message is directly sent to the window function for processing without passing through the message queue. Such as WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR, and WM_WINDOWPOSCHANGED.

Difference between PostMessage and SendMessage

The message sent by PostMessage is a queue message, which will Post the message to the Message Queue. The message sent by SendMessage is a non-queue message and is directly sent to the window for processing, messages are returned only after they are processed.


Figure 4: Message Queue

To prove this process, we can change the example above.
1. Add the ID_BUTTON_TEST definition to Win32Test. h.

#define ID_BUTTON_TEST      1002

2. Do not use SendMessage or PostMessage to send messages in OnButtonWhite.
// Event when hBtWhite is pressed

Void OnButtonWhite () {g_bWhite = true; InvalidateRect (g_hWnd, NULL, FALSE); // refresh the SendMessage (g_hWnd, WM_COMMAND, ID_BUTTON_TEST, 0) window; // PostMessage (g_hWnd, WM_COMMAND, ID_BUTTON_TEST, 0 );}

3. Add the ID_BUTTON_TEST judgment in the message loop.

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

4. Add the ID_BUTTON_TEST judgment in the 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;

Using breakpoint debugging, we found that the ID_BUTTON_TEST message sent by SendMessage only enters BreakPoint2, while the ID_BUTTON_TEST message sent by PostMessage enters BreakPoint1 and BreakPoint2.


======================================= Review of the series of programming ideas ==================
Logging of programming ideas
Exception Handling in programming ideas
Regular Expressions of programming ideas
Programming idea iterator
Recursion of programming ideas
Callback of programming ideology

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.