[Windows platform senior engineer]——Basic introduction: Win window principle

1. Windows program development process:

The Windows program is divided into two parts, "program code" and "UI resources", which are integrated into a complete EXE file through the RC compiler.

The so-called UI resources refer to things such as function menus, dialog box appearances, program icons, cursor shapes, and so on.

The actual content (binary code) of these UI resources is generated with the help of various tools and exists with various extensions, such as .ico, .bmp, .cur, etc. The programmer must describe them in a so-called resource description file (.rc).

The RC compiler (RC.EXE) reads the description of the RC file and then concentrates all the UI resource files into a .RES file, and then combines it with the program code. This is a complete Windows executable file.

2. The relationship between Windows programs and operating systems

The progress of Windows programs is driven by external events. In other words, the program keeps waiting (using a while loop), waiting for any possible input, then making judgments, and then doing appropriate processing. The above-mentioned "input" is captured by the operating system and entered into the program in the form of a message (a data structure).

3. The Windows window life cycle is as follows:

1. CreateWindow is called during program initialization to create a window for the program as the screen stage of the program. After CreateWindow generates the window, it will send wM_CREATE directly to the window function. The latter can then do some initialization operations (such as configuring memory, opening files, reading initial data...).

2 While the program is alive, use GetMessage to continuously grab messages from the message queue. If the message is WM_oUIT, GetMessage will return 0 to end the while loop, and then end the entire program.

3. DispatchMessage dispatches messages to window functions through the assistance and supervision of the Windows USER module. The message will be judged and processed there.

4. The program continues to perform steps 2 and 3.

5. When the user presses the Close command item in the system menu, the system sends out WM_CLOSE. Usually the window function of the program does not intercept this message, so DefWindowProc handles it.

6. After DefWindowProc receives WM_CLOSE, it calls DestroyWindow to clear the window. Destroy Window itself will send out WM_DESTROY.

7. The standard response of the program to WM_DESTROY is to call PostQuitMessage.

8. PostQuitMessage does not have any other operations, just send out WM_QUIT message, ready to get GetMessage in the message loop, as in step 2, end the message loop.

3. Principles of Windows Forms

The three core systems of Windows: the USER module responsible for window object generation and message distribution, the GDI module responsible for image display and drawing, and the KERNEL module responsible for memory, process, and IO management.

Imagine how to generate a window object on a pixel array. In fact, it is to use GDI to draw the window, and it is constantly refreshed and displayed on the screen at a certain frequency. This is the graphical interface. If the graphics are written under DOS or Windows DOS emulator The experience of the interface is easier to understand. So in fact, the generation of windows in the USER module relies on the GDI module (including menus, scroll bars, etc., are drawn using GDI).

So, let's talk about the Windows form principle from the USER module and GDI module below.

If you have been exposed to Win32 SDK programming, you know the process of generating a standard Windows form:

  1. Design window class,
  2. Registration window class,
  3. Create window,
  4. Display window,
  5. Start the message circulation pump to cyclically obtain messages and distribute them to the window procedure function for processing.

Paste a standard Windows form generation code:

#include <windows.h>
 
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("窗口类名称");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX   wndclassex = {0};
 
	//设计窗口类
    wndclassex.cbSize        = sizeof(WNDCLASSEX);
    wndclassex.style         = CS_HREDRAW | CS_VREDRAW;
    wndclassex.lpfnWndProc   = WndProc;
    wndclassex.cbClsExtra    = 0;
    wndclassex.cbWndExtra    = 0;
    wndclassex.hInstance     = hInstance;
    wndclassex.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
    wndclassex.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wndclassex.lpszMenuName  = NULL;
    wndclassex.lpszClassName = szAppName;
    wndclassex.hIconSm       = wndclassex.hIcon;
	
	//注册窗口类
    if (!RegisterClassEx (&wndclassex))
    {
        MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
        return 0;
    }
 
	//产生窗口
    hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, 
		                  szAppName, 
        		          TEXT ("窗口名称"),
                		  WS_OVERLAPPEDWINDOW,
		                  CW_USEDEFAULT, 
        		          CW_USEDEFAULT, 
                		  CW_USEDEFAULT, 
		                  CW_USEDEFAULT, 
        		          NULL, 
                		  NULL, 
		                  hInstance,
        		          NULL); 
			
	//显示窗口
    ShowWindow (hwnd, iCmdShow);
    UpdateWindow (hwnd);
	
	//启动消息循环泵循环获取消息分配到窗体过程函数处理
    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }
 
    return msg.wParam;
}
 
//窗体过程函数
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
 
    switch (message)
    {
    case WM_CREATE:
        return (0);
		
    case WM_PAINT:
        hdc = BeginPaint (hwnd, &ps);
        EndPaint (hwnd, &ps);
        return (0);
		
    case WM_DESTROY:
        PostQuitMessage (0);
        return (0);
    }
 
    return DefWindowProc (hwnd, message, wParam, lParam);
}

What needs to be understood is that all Windows forms and controls are created using CreateWindow or CreateWindowEx in the final analysis, and they all require the production process of standard Windows Forms.

Ordinary forms are easy to understand, and the main need to figure out is the process of generating dialog boxes and controls and message dispatching.

The management of the dialog box and its sub-controls relies on the built-in dialog box manager of Windows. The work of the dialog box manager includes:

1. Automatically generate dialog boxes and sub-controls based on the .rc files generated by the dialogs and sub-controls we designed in the resource designer (if you have the experience of manually writing .rc files, you know that writing RC files is actually to specify windows and sub-controls Parameters such as size, type, style, etc. The dialog manager will pass these parameters into the CreateWindow function to generate the form)

2. The modal dialog box directly displays the window. If the non-modal dialog box message indicates the WS_VISIBLE attribute, you need to call ShowWindow to display the window.

3. Maintain a message circulation pump. For modal dialog boxes, the message of the message pump does not pass through the parent window, so it appears modal; for non-modal dialog boxes, the message pump message passes through the main window and must be transmitted by the main window. Give a non-modal dialog box, behave as non-modal.

4. Maintain a built-in form procedure function. For the dialog box, it will handle the closing and opening of the dialog box and the focus and tab of the child window. The same is true for the child controls. Each child control has its own type of form procedure. Function, form procedure function handles the performance styles and behaviors of child controls gaining or losing focus, pressing or popping up, and creating.

For the dialog box, he will open a dialog box procedure function and let some messages be processed by the dialog box management function first. If the dialog box procedure function is not processed, it will be handed over to the default built-in procedure function for processing. For child controls, They did not open the procedure function, but the message to be processed by the built-in window function sent to the parent window for processing.

Then the dialog manager has completed the second half of the standard Windows form generation. As for the design window class and the registration window class, this is pre-made by Windows itself, such as the common "button", "listbox", " "edit" class and so on.

So since all forms (including dialogs and controls) are produced in the same process, we can replace part of the work of the dialog manager:

1. Without using the dialog box to read the .rc template, directly pass the parameters to the CreateWindow function to create the dialog box and the control. This is the common principle of dynamically creating the control .

2. Set the control self-drawing property such as BS_OWNDRAW, open the WM_DRAWITEM message of the control to the parent window, and the parent window will draw the button style. This is the principle of common control redrawing .

3. Replace the built-in form function and send the message to the custom form process function for processing. This is the principle of common control subclassing .

Friends who need Windows operating system and development tools can click to learn more and get it for free~

The next section talks about: MFC dialog box principle

 

Guess you like

Origin blog.csdn.net/Python6886/article/details/111396544