Example analysis of a simple Win32 program

  • 2020-04-02 02:43:27
  • OfStack

In this paper, the composition, structure, implementation method and operation principle of a Win32 program are analyzed in detail. Share with you for your reference. Specific analysis is as follows:

One, Windows programs and ordinary C or C++ programs are different

Anyone who has learned C or C++ knows that we write programs with an entry, the main function, but in Win32 programs, what is our entry function? How does it work, and how does it differ from the console programs we write in C or C++?

Programs we say first Win32 console with us a very important difference, is the Win32 program is a message response, such as clicking on a button, will generate a message onButoon, then the message will enter our programs maintained by a message queue, the program runs constantly in the process of take out the message queue, and make corresponding processing. Until the end of the program is retrieved message.

Understand the structure and composition of MSG

First, since Windows programs are triggered based on messages, how does Windows define a message? The following is the definition on the MSDN documentation:


typedef struct tagMSG {   // msg 
  HWND hwnd;
  UINT message;
  WPARAM wParam;
  LPARAM lParam;
  DWORD time;
  POINT pt;
} MSG;

Now let's analyze this structure:

HWND HWND: HWND is a window handle that uniquely identifies a window resource. As for what is a handle, it is similar to a pointer to C or C++. A handle is the identity of a resource, and it can be subdivided into HICON, HCURSOR, window handle, HWND, application instance handle, etc. The operating system specifies a unique identifier for each window, the window handle.
 
UINT message: message is a variable of type UINT (unsign int in C or C++) that identifies a specific message, such as a keyboard-pressed message. Message with an integer to represent, but an integer is usually difficult to remember, so in VC++ with Microsoft to give us the definition of some macros to represent, such as WM_KEYDOWN.

WPARAM WPARAM: integer parameter that indicates additional information for message.

LPARAM LPARAM: like wParam, is an integer parameter that indicates additional information for message. As with wParam, it is used to distinguish between different cases of the same message.

DWORD time: DWORD is an unsigned long in C or C++.

POINT pt: a POINT is a structure that represents a POINT in the real world with two long-type members x and y that represent the cursor or mouse coordinates at which the message is generated.

Thus, the information contained in a variable of MSG is considerable and detailed.

Understand the WinMain function

Then, just like the entry of C or C++ console program is the main function, the entry of Win32 program is also the main function, but it is called the WinMain function, it is defined as follows:


int WINAPI WinMain(
 HINSTANCE hInstance,   // handle to current instance
 HINSTANCE hPrevInstance, // handle to previous instance
 LPSTR lpCmdLine,     // command line
 int nCmdShow       // show state
);

Now let's analyze this function:

HINSTANCE HINSTANCE: HINSTANCE is a handle to the current application instance. An instance is a running program.

HINSTANCE hPrevInstance: hPrevInstance is a handle to the previous application instance.

LPSTR lpCmdLine:lpCmdLine is a pointer to a string that represents a command-line argument. What is a command-line argument? Char *argv[] in our C or C++ main function.

Int nCmdShow: is used to represent the display of a window, indicating whether it wants to maximize display, minimize display, normal-size display or hide display.

Like the main function, WinMain is called by the operating system, so these parameters are assigned by the operating system.

What is WINAPI? Actually it is a macro, it represents the __stdcall, said is the order of the arguments, but in VC, the parameters of the default order as __cdecl.

Create a window

So how do we design a window? To design a window, you are actually designing a window class to mark the various properties of a window, and there is already a class (or rather a structure) called WNDCLASS in VC. It is defined as follows, and the comments that follow illustrate their use:


typedef struct _WNDCLASS { 
 UINT style;       //Used to specify the type of the class, that is, the type of the window class
 WNDPROC lpfnWndProc;  //Specifies a window callback function that is a pointer to a function
 int cbClsExtra;     //Additional memory for a class, usually 0
 int cbWndExtra;     //The window attaches memory, which is usually 0
 HANDLE hInstance;  //The current instance handle is assigned a value using the parameter in WinMain
 HICON hIcon;     //Icon handle, used to indicate what icon the application is using, using the function LoadIcon for assignment
 HCURSOR hCursor; //Cursor handle to indicate the display when the mouse enters the application window area, assigned with the function LoadCursor
 HBRUSH hbrBackground;   //To indicate the background color of the program, use the function (HBRUSH)GetStockObject.
 LPCTSTR lpszMenuName;   //Specifies the name of the menu
 LPCTSTR lpszClassName;   //Specifies the name of the class
 } WNDCLASS;

Note: the procedure function of a type window, also called a callback function, works by calling a function to process a message to a window when the application receives it. This is done by the operating system rather than the application itself, but the code for the callback function itself must be done by the application itself. For a message, the operating system calls the function specified by the member of the lpfnWndProc in the type of the window that receives the message. Each of the different types of Windows has its own dedicated callback function, which is specified by the lpfnWndProc member.

In VC or when writing a Windows program, we often use a class of variables in which each bit corresponds to a property. When one of the variables is 1, it means that it has the characteristic corresponding to that bit; when the bit is 0, it means that there is no characteristic corresponding to that bit. When several bits in a variable are simultaneously 1, it represents a combination of several properties. It is not easy to remember which bit in a variable represents which meaning, so we often define some macros according to the capitalized English spelling of the feature. In the value corresponding to the macro, only the bit corresponding to the feature (bit) is 1, and the rest bits are 0. In fact, these macros are a single value of type UINT, so we can combine multiple properties with the | operator and remove one with the & ~.

So to create a window, first we create a WNDCLASS variable in the WinMain function, and assign a value to the member in the WNDCLASS variable, we can register the window, can call the function RegisterClass(& WNDCLS) to register a window, it needs a WNDCLASS type variable address. Then define a window handle HWND HWND; The function CreateWindow is then called, assigning the return value to HWND. Finally, the function ShowWindow(HWND,SW_SHOWNORMAL) is called. UpdateWindow (HWND); To display the window.

Establish a message loop

Now that the window is created, but as we said before, Windows programs are based on message triggering and processing, so how do we let the program let the system know what we're doing? For example, with a click of the mouse and a click of the keyboard, we will set up our message loop.
First, we define a variable of type MSG, such as MSG MSG;
Then execute the following loop:


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

Explanation:

The GetMessage function takes the message from our message queue. The first parameter is the MSG variable, which will automatically help us fill the member variable in MSG. The second parameter is a window handle, NULL means to accept all messages belonging to the calling thread; The third parameter specifies the minimum value of the message; The fourth parameter specifies the maximum value of the message. If these two parameters are set to 0, all messages in the message queue are retrieved. Its return value is of type BOOL and only returns FALSE if the message fetched is WM_QUIT; That is, unless the program is closed, it will be a dead loop, always processing our operations.

The TranslateMessage function, which translates, processes, and transforms messages and places new messages on message queues without affecting the original message queues.

The DispatechMessage function, which passes the received message to the window callback function for analysis and processing. Pass the message to the operating system and have the operating system call the window callback function to process the information.

Vi. Callback function (window procedure function)

Let's start with the definition:


LRESULT CALLBACK WinSunProc( 
 HWND hwnd, //Handle to the window
 UINT uMsg, //Message identifier
 WPARAM wParam, //MSG first additional parameter
 LPARAM lParam //MSG second additional parameter
 );

The CALLBACK is a macro that represents the _stdcall mentioned earlier, and the LRESULT is a long parameter.
When calling, pass the parameters of window class WNDCLASS, there is a switch statement to determine the type of message to be processed, and make corresponding processing, note that there must be a default: return DefWindowProc(HWND,uMsg,wParam,lParam) in the switch statement; Messages that do not appear in the case will be processed in the default way, otherwise the window will run in error, and even the window cannot be created and displayed.

Through the above analysis to restore a Win32 application of the complete execution process, I believe that the article described for everyone's Windows application design has a certain reference value.


Related articles: