Because it is classic all we have to share.
It is necessary to add a little:
Send this post mainly to let friends who want to know and understand Win32 programming, or students who have just started in this area can be a bit helpful.
Of course, it is a bit selfish, that is, I am afraid of my friends.
Try to recommend: "WINDOW Program Design" Beijing Publishing House Publishing
Win32 programming basics
Although the Windows application is thousands of change, it is dazzling, but the message mechanism and window processes always have their foundation, which is equivalent to grasping the key to the problem.
If you are previously a C programmer or MFC's faithful user, as long as you learn the syntax of the C language, you have a short C program, understand the following Win32 programming foundation is not a difficult thing.
A simplest Win32 program
In the previous C language programming, a simplest program can only have two lines.
Void main (void)
{Printf "Hello World!"
The Windows program to achieve the same function is also to write dozens of lines. This is not to indicate that the Windows application efficiency is low, it is difficult to master, but the program has a richer connotation in the Windows environment. The efficiency of the Windows program is not low. In all Windows applications, there is a process initialization process. This has to be used on dozens of statements. This initialized code is similar to that of any Windows applications. . The following is an example of a program easywin that implements the simplest function, describing the basic framework of the Windows program.
Open Visual C 6.0.
Select the New menu of the File menu, in the Dialog box that appears, select the Projects section (New Project), and take the Win32 Application item below, indicating that the application is created using the Win32 environment. First fill in "C: /" in the Locatin, then fill in "easywin" in the Project Name, other by default). Click the OK button.
Select the new menu again, in the dialog box that appears, select the Files section (new file), and take the C Source file below, indicating a new C source file. Enter "easywin" in the File column on the right, and finally make sure the Add to Project check box is ticked). Click the OK button.
Enter the following source code in the EASYWIN.CPP file.
// ******************************************************** *******************
// Project: Easywin
// File: easywin.cpp
// Content: A basic Win32 program // *********************************************** *****************************
#include
#include
// Function declaration
Bool Initwindow (Hinstance Hinstance, INT NCMDSHOW);
LResult Callback WinProc (HWND HWND, UINT MESSAGE, WPARAM WPARAM, LPARAM LPARAM);
// ******************************************************** *******************
// Function: WinMain ()
// Function: Win32 application portfolio function. Create a main window, process the message loop
// ******************************************************** *******************
INT Pascal Winmain (Hinstance Hinstance, // Current instance handle
Hinstance hprevinstance, // Previous instance handle
LPSTR LPCMDLINE, / / Command line character
INT ncmdshow) // window display method
{
MSG msg;
// Create a main window
IF (!in, ncmdshow)
Return False;
// Enter the message loop:
// Take a message from the message queue of the application, send it to the message processing process.
// When checking the WM_QUIT message, exit the message loop.
While (GetMessage (& MSG, NULL, 0, 0))
{
TranslateMessage (& MSG);
DispatchMessage (& MSG);
}
// End of the program
Return msg.wparam;
}
// ******************************************************** ******************
// Function: initwindow ()
// Features: Create a window.
// ******************************************************** ******************
Static Bool Initwindow (Hinstance Hinstance, Int Ncmdshow)
{
HWND HWND; // Window handle
WNDCLASS WC; // window structure
// Fill the window structure
Wc.style = CS_VREDRAW | CS_HREDRAW;
Wc.lpfnWndProc = (WndProc) WinProc;
wc.cbclsextra = 0;
wc.cbWndextra = 0;
wc.hinstance = hinstance;
Wc.hicon = loadicon (Hinstance, IDi_Application);
Wc.hcursor = loadingCursor (NULL, IDC_ARROW);
wc.hbrbackground = getStockObject (White_brush);
Wc.lpsz GeneNuname = NULL;
wc.lpszclassname = "easywin";
// Register window class
RegisterClass (& WC);
// Create a main window
HWND = CREATEWINDOW
"Easywin", // window name
"A basic Win32 program", // window title
WS_OVERLAPPEDWINDOW, // Window style, defined as ordinary
100, // X coordinate of the window position
100, // Y coordinate of the window position
400, // Width
300, // The height of the window
Null, // Parent Window Handle
Null, // Menu handle
Hinstance, // application instant sequence
NULL); // Create a data pointer
IF (! hwnd) Return False;
// Display and update the window
ShowWindow (HWND, NCMDSHOW);
UpdateWindow (HWND);
Return True;
}
// ******************************************************** ****************** // function: WinProc ()
// Function: Handle the main window message
// ******************************************************** ******************
Lresult Callback WinProc (HWND HWND, UINT MESSAGE, WPARAM WPARAM, LPARAM LPARAM)
{
Switch (Message)
{
Case WM_KeyDown: // Key Message
Switch (WPARAM)
{
Case vk_escape:
Messagebox (HWND, "ESC button is pressed!", "Keyboard", MB_OK;
Break;
}
Break;
Case WM_RBUTTONDOWN: / / mouse message
{
Messagebox (hwnd, "right mouse button!", "Mouse", mb_ok);
Break;
}
Case WM_Paint: // Window Heavy Pictures
{
Char hello [] = "Hello, I am easywin!";
HDC HDC;
Paintstruct PS;
HDC = beginpaint (hwnd, & ps); // acquire device environment handle
SetTextColor (HDC, RGB (0,255)); // Set text color
Textout (HDC, 20, 10, Hello, Strlen (Hello); // Output text
Endpaint (hwnd, & ps); // Release Resources
Break;
}
Case WM_DESTROY: // Exit Message
PostquitMessage (0); // Call exit function
Break;
}
// Call the default message processing process
Return DefWindowProc (Hwnd, Message, WPARAM, LPARAM);
}
The program is entered, you can compile execution. When you mouse mouse button or press the ESC button, a dialog box will pop up to represent your operation.
In fact, this program can be seen as a framework for all Win32 applications. In all programs in the later programs, you will find that they all add code on this program.
Winmain () function
The WinMain () function is the entry point when the application starts execution, and is usually the export point when the application ends task exits. It works as the main () function of the DOS program, one thing is that the winmain () function must have four parameters, which are passed to it. The prototype of the WinMain () function is as follows:
INT Pascal Winmain (Hinstance Hinstance, // Current instance handle
Hinstance hprevinstance, // Previous instance handle
LPSTR LPCMDLINE, / / Command line character
INT ncmdshow) // window display method
The first parameter hinstance is a handle that identifies the current instance of the application. It is a Hinstance type, and Hinstance is an abbreviation of Handle of Instance, represents the handle of the instance. Hinstance is a critical data that represents this parameter on behalf of the application, which requires this parameter during the later initialization program main window.
Here is two concepts, one is an example, one is a handle. The instance represents the entire process and method executing the application. If an application is not executed, it exists on the disk, then it is not instantiated; as long as one is executed, one instance of the program is run. Handle, as the name suggests, refers to an object's handle. In Windows, there are a wide variety of handles that are 32-bit pointer variables to point to the memory occupied by the object. The use of the handle can greatly facilitate Windows to manage various objects in its memory. The second parameter is HPREVINSTANCE, which is used to identify the previous instance handle of the application. This parameter is always NULL for Win32-based applications. This is because every instance of the application has its own independent address space in the Win95 operating system, even if the same application is executed twice, in memory, each instance of each instance is allocated new memory space. So after an application is executed, there will be no possibilities in the previous instance. That is, the parameters of HPREVINSTANCE are completely unnecessary, just to provide compatibility with 16-bit Windows applications, this parameter is retained. In the previous 16-bit Windows environment (such as Windows3.2), HPREVINSTANCE is used to identify the front handle of the application related to Hinstance.
The third parameter is lpcmdline, which is a pointer to the application command line parameter string. If you click Run in the "Start" menu of Win95, enter "EasyWIN Hello", then the string points to "Hello".
The last parameter is ncmdshow, an integer used to specify the window display mode. This integer value can be SW_SHOW, SW_HIDE, SW_SHOWMAXIMIZED, SW_SHOWMIMIMIZED, etc., and will be explained in the next section.
Registration window class
An application can have many windows, but only one is a main window, which is uniquely associated with instance handles of the application. In the above routine, the function of creating the main window is initwindow ().
You typically want to fill a window class structure WndClass and then call RegisterClass () to register the window class. Each window has some basic properties, such as window borders, window title bar text, window size, and location, mouse, background color, name of the processing window message function, and so on. The process of registration is to tell the system, then call the CREATEWINDOW () function to create a window. This is also like you to customize a dress, first tell the shop owner, your body size, cloth color, and your style, then he can make a satisfied clothes for you.
In the help of VC, you can see that the WNDCLASS structure is defined:
Typedef struct _wndclass {
Uint style; // Window style *
WndProc lpfnwndproc; // Specify the far pointer of the message processing function of the window *
INT cbclsextra; // Specify the number of additional bytes after assignment to the window structure *
INT CBWndextra; / / Specify the number of additional bytes after assigning the window instance
Handle Hinstance; / / Specify the instance handle corresponding to the window process *
Hicon Hicon; // Specify the icon of the window
Hcursor hcursor; // Specify the mouse in the window
Hbrush Hbrbackground; // Specify the background painting brush of the window
LPCTSTR LPSZMENUNAME; // The menu resource name of the window
LPCTSTR LPSZCLASSNAME; / / The name of the window *
} WNDCLASS;
In systems with new interface features in Win95 and WINNT, in order to support new window interface features, there is an extension window type WNDCLASSEX, which is defined as follows: typedef struct _wndclassex {
Uint cbsize; // Specify the size of the WNDCLASSEX structure
Uint style;
WndProc lpfnwndproc;
Int cbclsextra;
Int Cbwndextra;
Handle hinstance;
Hicon Hicon;
Hcursor hcursor;
Hbrush Hbrbackground;
LPCTSTR LPSZMENUNAME;
LPCTSTR LPSZCLASSNAME;
Small icon of Hicon HiconSM; //
WNDCLASSEX;
Two structures of WNDCLASS and WNDCLASSEX are basically consistent, just two members of CBSIZE and HICONSM in the WndClassex structure. Among the members of the WNDCLASS structure, it is specifically paying special attention after the comment.
The first member style of the WNDClass structure represents the style of the window class, which is often combined by some basic style "or" operations (operating position "|"). The following table lists some common basic window style:
Style meaning
CS_HREDRAW If the width of the window client is changed, redraw the entire window
CS_VREDRAW If the window customer area changes, redraw the entire window
CS_DBLCLKS can feel the double-click message in the window
CS_NOCLOSE Disables the "Close" command in the system menu
CS_OWNDC assigns individual independent device environments for each window of the window class
CS_CLASSDC assigns a shared device environment for each window of the window class
CS_PARENTDC specifies a sub-window inheriting the device environment of its parent window
CS_SAVEBITS Saves the screen image portion covered by the window as a bitmap. When the window is moved, Windows uses the saved bitmap to rebuild the screen image.
In the Easywin application, the WNDCLASS structure is filled and registered as follows:
Wc.style = CS_VREDRAW | CS_HREDRAW;
Wc.lpfnWndProc = (WndProc) WinProc;
wc.cbclsextra = 0;
wc.cbWndextra = 0;
wc.hinstance = hinstance;
Wc.hicon = loadicon (Hinstance, IDi_Application);
Wc.hcursor = loadingCursor (NULL, IDC_ARROW);
wc.hbrbackground = getStockObject (White_brush);
Wc.lpsz GeneNuname = NULL;
wc.lpszclassname = "easywin";
It can be seen that wc.style is set to CS_VREDRAW | CS_HREDRAW, indicating that the entire window is heard as long as the height or width of the window changes.
The value of the second member lpfnWndProc is (WndProc) WinProc. The message processing function of the window is indicated is a WinProc () function. Here, to specify the far pointer of the message processing function of the window, enter the function name of the message processing function, if necessary, the mandatory type conversion should be converted into a WNDPROC.
The next CBCLSEXTRA and WC.CBWndextra are set to 0 in most cases.
Then the Hinstance member gives it the instance handle of the application from WinMain (), indicating that the window is associated with this instance. In fact, as long as it is a registration window class, the value of the member is always the instance handle of the program, and you should remember it like your back book. The following HiCon is to let you specify an icon to this window, call LoadCon (Hinstance, IDi_Application), can call the internal pre-defined flag of the system as the icon of the Idc_Application as the icon of the window.
Similarly, call LoadCursor (NULL, IDC_ARROW) to pre-define the arrow type mouse inside the system to call the window.
HBRBACKGROUND members are used to define the background of the window on the window, which is the background color of the window. Call GetStockObject (White_Brush) You can get the pre-defined white painted white painted brush as a window in the system.
The above LoadCon (), loadCursor (), getStockObject () is Windows's API function, and their usage can be used to see the help of VC, here is not more introduced.
The value of the LPSzMenuname member we give NULL, indicating that the window will have no menu. If you want your window to have a menu, you assign the LPSZMenuname member to the string of the flag menu resource.
The last member of the WNDClass structure is a unique name that allows you to give this window class, because there are many window classes in the Windows operating system, you must use a unique name to represent them. Typically, you can name your program name to name the name of this window. This name will be used in the createWindow () function of the creation window.
After filling, for the WndClass structure, call the registerclass () function to register; for the WNDCLASSEX structure, call the RegisterClassex () function to register, their prototypes are as follows:
Atom RegisterClass (const wndclass * lpwndclass);
Atom RegisterClassex (Const WndClassex * LPWCX);
If the function is successful, it returns a non-0 value, indicating that a window class named Easywin has been registered. If it fails, it returns 0.
Create a window
When the window classes are registered, there will be no windows displayed because the process of registration is just ready for the creation window. The actual creation of a window is done by calling the CreateWindow () function. The general properties of the window have been pre-defined in advance, and the parameters in CREATEWINDOW () can further specify a more specific properties of a window, in the EasyWIN program, call the CREATEWINDOW () function to create a window as follows:
HWND = CREATEWINDOW
"Easywin", // Create a name of the window class used by the window *
"A basic Win32 program", // window title
WS_OVERLAPPEDWINDOW, // window style, defined as ordinary *
100, // X coordinate of the window position
100, // Y coordinate of the window position
400, // Width
300, // The height of the window
Null, // Parent Window Handle
Null, // Menu handle
Hinstance, // application instance sector *
NULL); / / generally null
The meaning of the parameters of the CreateWindow () function already introduces in the comments above. After comments, the parameters of the asterisk mark should focus on, and other parameters are very simple, not much introduction, see the help of VC.
The first parameter is the name of the window class used to create the window, note that this name should be consistent with the name of the window class registered earlier. The third parameter is the style of the created window, the following table lists the common window style:
Style meaning
WS_OVERLAPPEDWINDOW Creates a laminated window, a border, title bar, system menu, and maximum minimum button, is a collection of the following style: WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX
WS_POPUPWindow Creates a pop-up window, which is a collection of styles: WS_Border, WS_POPUP, WS_SYSMENU. WS_CAPTION and WS_POPUPWINDOW style must be used together to make the window menu visible
WS_OVERLAPPED creates a stacked window, which has title bar and border, like WS_TILED style
WS_POPUP This window is a pop-up window that cannot be used at the same time as WS_CHILD
WS_BORDER window has a single line border
WS_CAPTION window has title bar
WS_CHILD This window is a child window, cannot be used with WS_POPUP
WS_DISABLED This window is invalid, that is, no response to user operations
WS_HSCROLL window has horizontal scroll bar
The WS_ICONIC window is initialized to minimize
WS_MAXIMIZE window initializes to maximize
WS_MAXIMIZEBOX window has a maximum button
WS_MINIMIZE is the same as WS_MAXIMIZE
WS_MINIMIZEBOX window has a minimization button
WS_SIZEBOX border can make a size control window
WS_SYSMENU Creates a window with a system menu, must be used at the same time as the WS_CAPTION style
WS_THICKFRAME Creates a size controlled window with the WS_SIZEBOX style.
WS_TILED creates a stacked window with title bar
WS_Visible window is visible
The WS_VSCROLL window has a vertical scroll bar
The WS_OVERLAPPEDWINDOW flag is used in the program, which is a common flag that creates a normal window. In DirectX programming, we often use WS_POPUP, and the window created with this flag does not have the title bar and system menu. If the setting window is maximized, the client area can account for full screen to meet the needs of DirectX programming.
In the parameter behind the CreateWindow () function, the instance handle of the application is still used in Hinstance.
If the window is created success, the return value is the handle of the new window, otherwise returns NULL.
Display and update the window
After the window is created, it will not be displayed on the screen. To really display the window on the screen, you have to use the showWindow () function, its prototype is as follows:
Bool ShowWindow (HWND HWND, INT NCMDSHOW);
Parameters hWnd Specifies the handle to display the window, ncmdshow represents the display mode of the window, which is specified as the value passed from the NCMDSHOW of the WinMain () function.
Since the showWindow () function is not high, when the system is busy performing other tasks, the window will not immediately display it. At this time, call the UpdateWindow () function to display the window immediately. Its function prototype is as follows:
Bool UpdateWindow (HWND HWND);
Message loop
In Win32 programming, the message loop is a considerable concept, which seems very difficult, but it is very simple. In the Winmain () function, then the initwindow () function successfully created the application main window, then start the message loop, the code is as follows: While (GetMessage (& MSG, NULL, 0, 0)))
{
TranslateMessage (& MSG);
DispatchMessage (& MSG);
}
The Windows application can receive information entered in various forms, including the keyboard, mouse action, message generated by the memory, or a message sent by other applications, and the like. The Windows system automatically monitors all input devices and puts their messages into the message queue of the application.
The getMessage () function is used to take these messages one by one by the first-first principle, put it into a MSG structure. GetMessage () function prototype is as follows:
Bool getMessage
LPMSG lpmsg, // Pointer to a MSG structure, used to save your message
HWND hWnd, / / Specify which window of the window will be obtained
UINT WMSGFILTERMIN, / / Specify the minimum value of the obtained main message value
UINT WMSGFILTERMAX / / Specifies the maximum value of the acquired main message value
);
GetMessage () Copy the obtained message to an MSG structure. If there is no message in the queue, the getMessage () function will always be idle until there is a message in the queue again. If there is already a message in the queue, it will remove one after another. The MSG structure contains a complete information of a Windows message, which is defined as follows:
Typedef struct tagmsg {
HWND HWND; // Receive the window handle of the message
Uint message; // main message value
WPARAM WPARAM; // sub-message value, its specific meaning depends on the main message value
LPARAM LPARAM; // Secondary message value, its specific meaning depends on the main message value
DWORD TIME; // Message is delivered
Point pt; // mouse position
} Msg;
The main message in this structure indicates the type of message. For example, the keyboard message or mouse message, etc., the meaning of the sub-message is dependent on the main message value, for example, if the primary message is a keyboard message, then stored in the sub-message is a keyboard. Which of the specific keys of the specific key.
The getMessage () function can also filter messages, which is used to specify which window's message queue gets messages, and other window messages will be filtered. If this parameter is null, getMessage () gets a message from the message queue of all windows of the application thread.
The third and fourth parameters are used to filter the main message value in the MSG structure, the main message value outside WMSGFILTERMIN and WMSGFILTERMAX will be filtered out. If these two parameters are 0, then all messages are received.
When and only when the getMessage () function is acquired to the WM_QUIT message, the 0 value will be returned, so that the program exits the message loop.
The effect of the translateMessage () function is to convert the virtual key message to the character message to meet the needs of the keyboard input. The DISPATCHMESSAGE () function is completed by sending the current message to the corresponding window.
Turning a message loop is actually a simple step, almost all programs are in accordance with the method of Easywin. You don't have to go through the role of these functions, just a simple photo.
Message handler
The message handler is also called a window process. In this function, different messages will be allocated to different handles with the switch statement. Windows's message handling functions have a determined style, that is, the number of parameters and types of such functions, and the type of return values have a clear specification. In the specification of the VC, the prototype of the message processing function is defined: LRESULT CALLBACK WINDOWPROC (
HWND HWND, // Receive the handle of the message window
UINT UMSG, // main message value
WPARAM WPARAM, // subsis
LParam lparam // subsis value
);
If there are other messaging functions in your program, you must also be defined in this style, but the function name can be taken casually. The WinProc () function in EASYWIN is a typical message processing function.
The four parameters of the message processing function are obtained by get the MSG structure from the message queue from the message queue and then decomposed. The second parameter UMSG and the MSG structure are consistent, representing the main message value. The program uses the Switch statement to assign different types of messages to different handles.
The WinProc () function has clearly handled 4 messages, which are wm_keydown, wm_rbuttondown (right-click message), WM_Paint (Window Heavy Pictures), WM_DESTROY (Destroy Window Message).
It is worth noting that the application sent to the window is far more than the above, like WM_SIZE, WM_MINIMIZE, WM_CREATE, WM_MOVE, etc. There are dozens of frequently used messages such as WM_Size, WM_MOVE. To mitigate the burden of programming, Windows's API provides a defWindowProc () function to handle these most common messages. After calling this function, these messages will be processed in the system default manner.
Therefore, in the switch_case statement, it is only necessary to deal with the need for a particular response message, handle the remaining messages to the DefWindowProc () function, is a wise choice, which is also one of you must do.
End message loop
When the user presses Alt F4 or click the exit button in the upper right corner of the window, the system sends a message of WM_DESTROY to the application. When processing this message, call the postquitMessage () function that sends a WM_QUIT message to the message queue of the window. In the message loop, once retrieves this message, the GetMessage () function returns false, thus ending the message loop, then the program is also over.
summary
This chapter introduces the basics of Win32 programming, and master them is necessary before performing DirectX programming.
Through the study of this article, you should learn the following knowledge:
How to create a Win32 application engineering
Use the registerclass () function to register a window class, then call the CREATEWINDOW () function immediately to create an instance of a window.
Set the type of window and contact a message handler with the window
Turn on the message cycle with a fixed mode
Understand the definition rules of the message processing function, how to define a window message processing function
In the message processing function, finally you must call the defWindowProc () function to handle those default messages.
Call the postquitMessage () function to end the message loop