Principle of windows message mechanism framework [simple version]

Principle of windows message mechanism framework

 

 

Combined with two figures to understand

Windows and window classes

A Windows UI Application (e) has a main thread (g), one or more windows (a), and one or more child threads (k) [worker or UI threads].

The application must specify a window class and register with Windows (d) before it can create window (a) and display it. Window class is a structure containing window attributes, such as window style, icon, cursor, background color, menu resource name and window class name. Registering a window class associates the window procedure, class style, and other class properties with the class name.

Each window class has an associated window procedure (c), which is shared by all windows (a) of the same class in the application. The window procedure handles messages for all windows of this class.

#include <stdio.h>
#include <windows.h>
#include <stdexcept>
using namespace std;

//Callback function prototype declaration,Returns the result code of long shaping,CALLBACK Yes, it means stdcall call LRESULT CALLBACK WinProc(
                            HWND hwnd,      // handle to window
                            UINT uMsg,      // message identifier
                            WPARAM wParam,  // first message parameter
                            LPARAM lParam   // second message parameter
);

//(1) WinMain function,Program entry point function
int WINAPI WinMain(
                   HINSTANCE hInstance,      // handle to current instance
                   HINSTANCE hPrevInstance,  // handle to previous instance
                   LPSTR lpCmdLine,          // command line
                   int nCmdShow              // show state
                   ){
    //(2)
    //one.Design a window class,Similar blank filling questions,Use window structure
    WNDCLASS wnd;
    wnd.cbClsExtra = 0; //Extra memory for class
    wnd.cbWndExtra = 0;    //Extra memory for windows
    wnd.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);//Create an empty brush to fill the background
    //Load cursor,If the standard cursor is loaded,The first instance ID is set to null
    wnd.hCursor = LoadCursor(NULL, IDC_CROSS);
    wnd.hIcon = LoadIcon(NULL, IDI_ERROR);
    wnd.hInstance = hInstance;//The instance handle assignment is the handle value allocated by the program startup system
    wnd.lpfnWndProc = WinProc;//Message response function
    wnd.lpszClassName = "gaojun";//The name of the window class,It will be used when registering
    wnd.lpszMenuName = NULL;//Default to NULL No title block
    wnd.style = CS_HREDRAW | CS_VREDRAW;//Defined as horizontal and vertical redraws
    //two.Register window class
    RegisterClass(&wnd);
    //three.Create windows based on custom window classes
    HWND hwnd;//Save the generated window handle after creating the window for display
    //If it is a multi document program,Then the last parameter lParam Must point to a CLIENTCREATESTRUCT structural morphology
    hwnd = CreateWindow("gaojun", "WIN32 application program", WS_OVERLAPPEDWINDOW,
 CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);
    //four.Display window
    ShowWindow(hwnd, SW_SHOWDEFAULT);
    //five.update windows
    UpdateWindow(hwnd);
    
    //(3).Message loop
    MSG msg;//Message structure
    //If the message is wrong,The return value is-1,When GetMessage Get yes from message queue WM_QUIT Message time,The return value is 0
    //You can also use PeekMessage Function to retrieve a message from the message queue
    BOOL bSet;
    while((bSet = GetMessage(&msg, NULL, 0, 0)) != 0){
        if (-1 ==  bSet)
        {
            return -1;
        }
        else{
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return 0;//Program end,Return 0
}

//In the message loop, different responses are made to different types of messages
LRESULT CALLBACK WinProc(
                         HWND hwnd,      // handle to window
                         UINT uMsg,      // message identifier
                         WPARAM wParam,  // first message parameter
                         LPARAM lParam   // second message parameter
                         ){
    switch (uMsg)
    {
    case WM_CHAR://Character key message
        char szChar[20];
        sprintf(szChar, "char is %d;", wParam);//Format operation,stdio.h
        MessageBox(hwnd, szChar, "gaojun", 0);//Output operation windows.h in
        break;
    case WM_LBUTTONDOWN://Left mouse button press message
        MessageBox(hwnd, "this is click event!", "click", 0);
        HDC hdc;
        hdc = GetDC(hwnd);//Get device context handle,Used to output text
        //stay x=0,y=50(pixel)Output text where needed
        TextOut(hdc, 0, 50, "response WM_LBUTTONDONW news!", 
strlen("response WM_LBUTTONDONW news!"));
        ReleaseDC(hwnd, hdc);//After use DC Be sure to pay attention to release after
        break;
    case WM_PAINT://The window reacts to the times message
        HDC hDc;
        PAINTSTRUCT ps;
        hDc = BeginPaint(hwnd, &ps);
        TextOut(hDc, 0, 0, "This is a Paint event!", strlen("This is a Paint event!"));
        EndPaint(hwnd, &ps);
        break;
    case WM_CLOSE://messages turning off
        if (IDYES == MessageBox(hwnd, "Are you sure you want to close the current window?", "Tips", MB_YESNO))
        {
            DestroyWindow(hwnd);//Destroy Window 
        }        
        break;
    case WM_DESTROY:
        PostQuitMessage(0);//After response message,Deliver an exit message and use the program to exit safely
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);//Call the default message processing procedure function
    }
    return 0;
}

 

Window procedure (also called DefaultWindowProcedure)

Window procedure (c) is a function of receiving and processing all messages sent to window (a). Each window class (b) has an associated window procedure (c), and each window (a) created with this class uses the same window procedure to respond to the message. The system sends the message to the window process by passing the message data to the process as a parameter. The window procedure then performs the appropriate action on the message. It checks the message identifier and uses the information specified by the message parameters when processing the message.

Window procedures usually do not ignore messages. If it does not process the message, it must send the message back to the system for default processing. The window procedure performs this operation by calling the DefWindowProc function (f), which performs the default operation and returns the message result. The default window procedure function DefWindowProc defines some basic behaviors shared by all windows. The default window procedure provides minimal functionality for windows.

 

Windows Message..

Windows message (m) is just a set of parameters, such as window handle, message identifier and two values called message parameters (WPARAM and LPARAM). The window handle identifies the window to which the message is directed. The message identifier is a constant that identifies the purpose of the message. For example, the message identifier WM_PAINT tells the window that the process window's workspace has changed and must be redrawn.

There are two types of Windows messages, such as system defined messages and application defined messages. The system sends or publishes system defined messages when communicating with applications. Applications can also send or publish system defined messages. For example, WM_PAINT message identifier is used for system defined message, which requests the window to draw its content.

Applications can create messages used by their own windows or communicate with windows in other processes. If the application creates its own message, the window process that receives the message must interpret the message and provide appropriate processing.

Later net provides a unified standard custom message model, that is, synchronization context.

Message flow

DOS based applications make C runtime function calls to obtain input from the system. For example, it calls the gets () C-Runtime function to get input from the keyboard. However, Windows based applications do not make explicit function calls to get input. Instead, they wait for the system to pass input to them. This is why Windows based applications are event driven.

Whenever the user moves the mouse, click the mouse button or type on the [1] keyboard, and the device driver (p) or keyboard of the mouse will switch the details [2] to user32 DLL (n), which in turn converts the input into a Windows message and puts it in the system message queue (l) [3].

The Windows operating system deletes one message at a time from the system message queue, checks them to determine the target window, and then publishes [4] them to the message queue of the thread that created the target window. The thread's message queue receives all mouse and keyboard messages for Windows created by the thread. The thread deletes [5] messages from its queue and instructs the system to send them to [6 and 7] to the corresponding window process for processing. How does a thread delete messages from its message queues and processes? Now let's discuss it.

Message cycle (or) message pump

 

The Windows application has the WinMain() function, which is the entry point of the application, just like the main() function in the "C" language program. The WinMain() function acts as the main thread function of the application. The following three lines of code in the WinMain() function are called message loops or message pumps.

int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst,char * cmdParam, int cmdShow)
{

while (GetMessage(&Msg, NULL, 0,
//Note: there are three main functions for receiving messages: GetMessage, PeekMessage and WaitMessage.
0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);

}}

The GetMessage() call of the message loop checks for windows messages in the message queue. If a valid message is found, it is deleted from its queue. After deleting a message from the queue, the application can use the DispatchMessage() function to instruct the system to send the message to the window process for processing. If the message cannot be processed by the application, it will be sent to windows, and the system will call the DefaultWindowProcedure function for processing. If there is no message in the message queue, the GetMessage() call will be blocked until a valid message enters the message queue.

Between these two calls, the TranslateMessage () method call does nothing but converts a virtual key message into a character message. If you comment on this line, your application will still work. The only problem is that your test team will submit 50 keyboard related errors.

Added by rapmonkey on Wed, 26 Jan 2022 13:38:47 +0200