A detailed example of Windows program internal operating mechanism _c language

Source: Internet
Author: User
Tags function prototype getmessage message queue numeric value response code sprintf textout

This article takes the Sun Xin teacher VC + + program as the Foundation, explained in detail the Windows procedure internal operation mechanism, believed may help everybody better understand the Windows program operation principle and the corresponding VC + + program design. The specific contents are as follows:

To create an WIN32 application step:

1, write WinMain function;

2. Create window (step below):

A, design (one) window class (WNDCLASS)

B, register (the) window class.

C, create a window.

D, display and update the window.

3, write the message loop.

4, write the window process function.

WinMain.cpp #include <windows.h> #include <stdio.h> lresult CALLBACK Winazeproc (HWND hwnd,//Handle To Windows UINT umsg,//message identifier WPARAM WPARAM,///I-parameter LPARAM//LPARAM

Message parameter); int WINAPI WinMain (hinstance hinstance,//handle to current instance hinstance,//h
          Andle to previous instance LPSTR lpCmdLine,//command line int ncmdshow//show State
  ) {//Design a window class Wndclass wndcls;
  Wndcls.cbclsextra = 0;
  Wndcls.cbwndextra = 0;
  Wndcls.hbrbackground = (hbrush) getstockobject (Black_brush);
  Wndcls.hcursor = LoadCursor (NULL, Idc_cross);
  Wndcls.hicon = LoadIcon (NULL, idi_error);  Wndcls.hinstance = hinstance;
  The application instance handle is passed in by the WinMain function wndcls.lpfnwndproc = Winazeproc;
  Wndcls.lpszclassname = "aze_003";
  Wndcls.lpszmenuname = NULL; Wndcls.style = Cs_hredraw |

  Cs_vredraw;  RegisterClass (&AMP;WNDCLS);
  
Register window class  Creates a window that defines a variable used to save the handle HWND hwnd that is returned after a successful creation;

  hwnd = CreateWindow ("aze_003", "Application", Ws_overlappedwindow, 0, 0, +, NULL, null,hinstance, NULL);  ShowWindow (hwnd, SW_SHOWNORMAL);    Display window UpdateWindow (HWND);
  Refresh window//define message structure body, start message loop msg msg;
    while (GetMessage (&msg, NULL, 0, 0)) {translatemessage (&msg);
  DispatchMessage (&AMP;MSG);
return msg.wparam; //Write window procedure function lresult CALLBACK Winazeproc (HWND hwnd,//Handle to Window UINT umsg,//message identifier WP Aram WParam,//Parameter LPARAM LPARAM//Second message parameter) {switch (umsg) {case Wm_
    Char:char SZCHAR[20];
    sprintf (Szchar, "Char code is%d", wParam);
    MessageBox (hwnd, Szchar, "char", 0);
  Break
    Case Wm_lbuttondown:messagebox (hwnd, "Mouse clicked", "message", 0);
    HDC HDC;    HDC = GetDC (hwnd); Cannot invoke TextOut in response to WM_PAINT messages (hdc, 0, 50, "The Programmer's Home!", strlen ("The Programmer's House!").
    ") );
    ReleaseDC (hwnd, HDC); BReak;
    Case WM_PAINT:HDC HDC;
    Paintstruct PS;  HDC = BeginPaint (hwnd, &AMP;PS);
    BeginPaint only in response to WM_PAINT messages is called TextOut (HDC, 0, 0, "http://www.sunxin.org", strlen ("http://www.sunxin.org"));
    EndPaint (hwnd, &AMP;PS);
  Break Case Wm_close:if (Idyes = = MessageBox (hwnd, "Do you really Quit?")
    "," message ", Mb_yesno)) {DestroyWindow (HWND);
  } break;
    Case Wm_destroy:postquitmessage (0);
  Break
  Default:return DefWindowProc (hwnd, umsg, WParam, LParam);
return 0;

 }

After the program is run, the display interface is as follows:

Windows are divided into client areas (which are part of the window) and non-customer areas.

The title bar, menu bar, System menu, the smallest (large) box, and the adjustable border is called the non-client area of the window, managed by the Windows system; The application primarily manages the appearance and operation of the client area (display text, drawing graphics).

dialog boxes, message boxes are also windows, and there are many child windows on the dialog: Buttons, radio buttons, check boxes, group fanatics, text editing boxes, and more.

2, window and handle:

In a Windows application, a window is identified by a window handle (HWND), and to operate on a window, you must get a handle to the window.

Handles are an important concept in Windows programs (icon handle (HICON), cursor handle (hcursor), brush handle (Hbrush)).

3, message and Message Queuing:

Windows Programming mode is a kind of event-driven programming mode, mainly based on message . (When the system perceives an event, such as a mouse click), the system wraps the event into a message, posts it to the application's message queue, and then the application extracts the message from the message queue and responds. During this process, the operating system also "sends messages" to the application. "Send Message": Actual means: A window procedure function in the operating system calling program that handles messages

(1) Message: In Windows, messages are represented by the MSG structure, as follows:

The MSG structure contains message is information from a thread ' s message queue. 

typedef struct TAGMSG {
 hwnd  hwnd;     The window to which the message belongs, the UINT message associated with the window  ;   The message identifier
 WPARAM WPARAM;    Specifies the additional message for the message
 LPARAM LPARAM;    Specifies the additional message for the message
 DWORD time;     The time at which the message is posted to the queue point
 pt;      The current position of the mouse
} MSG, *pmsg;

in Windows, a message is represented by a numeric value, and Windows defines the value of the message as the form of a WM_XXX macro (Wm:window message), which is capitalized in the English spelling of some of the messages. such as: Wm_lbuttondown: The left mouse button press message, WM_KEYDOWN: Keyboard Press message, WM_CHAR: Character message ...

(2) Message Queuing: After each Windows application starts executing, the system creates a message queue for the change, which is used to store messages for the Windows created by the change program.

(3) Enter the team message and do not enter the team message:

Incoming messages are put into the application's message queue by the system and then removed and sent by the application;

No incoming team message is sent directly to the window when the system calls the window process;

Both end up with a system call window procedure function to process the message.

4. WinMain function

(i) the WinMain function on MSDN is defined as follows (with detailed comments):

The WinMain function is called by the system as the initial entry point for a windows-based application. 

int WINAPI WinMain (
 hinstance hinstance,   //handle to present instance current window handle
 hinstance hprevinstance,/ Handle to previous instance the previous open window handle
 LPSTR lpcmdline,     //Command line specifies the * command-line * parameter int to be passed to the application
 ncmdshow       Show state specifies how the window should be displayed, such as: maximum (small), hidden, etc.


(ii) Definition of the structural body of the window class:

(1) The corresponding code in this procedure is as follows:

typedef struct _WNDCLASS { 
  UINT    style;    Specifies * This type of * window style, such as: Cs_hredraw, Cs_vredraw, Cs_noclose, cs_dblclks
  WNDPROC lpfnwndproc  ;   function pointer, pointing to the window procedure function (the window procedure function is a callback function)
  int    Cbclsextra;   Generally 0
  int    cbwndextra;   Ibid.
  hinstance hinstance;   Specifies the instance handle of the program that contains the window procedure
  hicon   hicon;     Specifies the window class's icon handle
  hcursor  hcursor;   Specifies the cursor handle of the window class
  hbrush   hbrbackground;   Specifies the background brush handle for the window class; When the window is redrawn, the system uses the brush specified here to investigate the background of the window
  lpctstr  lpszmenuname;   Specifies the name of the menu resource * * menu is not a window * *
  lpctstr  lpszclassname;   Specifies the name of the window class
} wndclass, *pwndclass;

The callback function is not called directly by the implementing party of the function, but is invoked by the other party when a particular event or condition occurs, and is used to respond to the event or condition.

The implementation mechanism of the callback function is:

① defines a callback function .

② provides a side of the function implementation to register the callback function's function pointer to the caller at initialization time .

③ when a particular event or condition occurs, the caller uses the function pointer to invoke the callback function to process the event .

For the message processing mechanism for Windows, the process function of a window is invoked as follows:

① When designing the window class, assigning the address of the window process function to the LPFNWNDPROC member variable;

② calls RegisterClass (&wndclass) To register the window class, then the system has the address of the window procedure function we wrote.

③ When an application receives a message from a window, calling DispatchMessage (&msg) passes the message back to the system. The system invokes the window procedure function to process the message using the function pointer that was obtained when the window class was previously registered.

Tip: A Windows program can contain multiple window procedure functions, and a window procedure is always associated with a particular window class (specified by the LPFNWNDPROC member variable in the WNDCLASS structure), using the same window procedure based on the window created by the window class .

The type of the LPFNWNDPROC member variable is WNDPROC and is defined as follows:

typedef lresult (callback* WNDPROC) (HWND, UINT, WPARAM, LPARAM); Lresult=long, Callback=_stdcall WndProc is a function pointer type.

Note:WndProc is defined as a pointer type that points to a window procedure function, and the window procedure function must be in the same format as WndProc.

in VC + +, resources are identified by identifiers (IDs), and the same ID can identify multiple different resources (the ID of the resource is essentially an integer). such as: Menu resources: Idm_xxx (M for menu), Icon resources: idi_xxx (i icon), Button resources: idb_xxx (b for Button)

You can call Getstockobject (int fnobject) to get the system's standard brush. The statement reads as follows:

The Getstockobject function retrieves a handle to one of the stock pens, brushes, fonts, or palettes. 

Hgdiobj getstockobject (
 int fnobject  //Stock object type
);

Getstockobject function: Returns the handle of a variety of resource objects, such as: brush, brush, font, color palette, etc.

When a function returns, type conversion is required. Such as:

Wndcls.hbrbackground = (hbrush) getstockobject (Black_brush); 

(2) Registration window class: Design window Class (WNDCLASS), you need to call the RegisterClass function to register it, after registering successfully, you can create the window of the type. The statement reads as follows:

ATOM registerclass (
 CONST wndclass *lpwndclass//class data, pointer to window class object
               //pointer to a WNDCLASS structure. You are must fill the structure with the appropriate class attributes before passing it to the function. 
);

(3) Create window: CreateWindow function declaration is as follows:

HWND CreateWindow (
 lpctstr lpclassname,//Registered class name is: The name of the WNDCLASS member of the window class lpszClassName (must be registered first)
 LPCTSTR lpwindowname,//Windows name  specifies the name of the window
 DWORD dwstyle,//window style    Specifies the style to create the window, such as: Ws_overlappedwindow
 int x,        //Horizontal position of window
 int y,        //Vertical position of window
 int nwidth,      //WI Ndow width
 int nheight,     //window height
 HWND hwndparent,   //handle to Parent or owner window specifies the window that is created by the parent window Handle
 hmenu hmenu,     //menu handle or child identifier
 hinstance hinstance,//handle to Application Instanc E
 lpvoid lpparam    //Window-creation data as an additional parameter to the WM_CREATE message lparam The passed pointer (generally: NULL)
;

If the window is created successfully, the CreateWindow function returns the handle assigned to the window by the system, otherwise, returns null.

• Note: You should first define a window handle variable to receive the handle value after the window is created.

Display and update Windows:

(4) Display window: ShowWindow declaration as follows:

BOOL ShowWindow (
 hwnd hwnd,   //Handle to window) the window handle int ncmdshow//show State, which is returned after the window was successfully created  : sw_ HIDE, Sw_show, SW_SHOWNORMAL, sw_showminimized, sw_showmaximized
);

(5) Update (refresh) window: UpdateWindow function declaration prototype is as follows:

BOOL UpdateWindow (
 hwnd hwnd  //Handle to Window creates a successful windowed handle
);

The UpdateWindow function refreshes the window by sending a WM_PAINT message, and UpdateWindow sends the WM_PAINT message directly to the window process function for processing rather than to the message queue .

(iii), message circulation

After the window is created, displayed, updated, a message loop needs to be written and the message is constantly fetched and responded to from the message queue.

GetMessage () function: Fetching messages from message queues

BOOL GetMessage (
 lpmsg lpmsg,     //message information points to a messaging (MSG) structure, GetMessage message information taken from the thread's message queue is saved in the structure object The
 HWND hwnd,//Handle to Window      specifies which window to receive the message; NULL: A window message to receive all windows belonging to the calling thread
 UINT wmsgfiltermin,// The message specifies the minimum value to get the
 UINT Wmsgfiltermax  //Last message if wmsgfiltermin=0 and wmsgfiltermax=0 receive all messages
);

The GetMessage function receives a message other than Wm_quit that returns a value other than 0.

Message loop code, general form
  msg msg;
  while (GetMessage (&msg, NULL, 0, 0))
  {
    translatemessage (&msg);//translatemessage function converts virtual key message * is a character message that is posted to the message queue of the calling thread and is removed
    dispatchmessage (&msg) The next time the GetMessage function is called;  The DispatchMessage function assigns a message to the window process, with a window procedure function to handle the message
//dispatchmessage is actually passing the message to the operating system, and the operating system calls the window procedure function to process the message (response)
  }

The message processing mechanism for Windows applications is shown in the following illustration:

Message processing procedures for Windows applications:

(1) The operating system receives the application's window message and delivers the message to the application's message queue .

(2) The application extracts a message from the message queue by calling the GetMessage function in the message loop Rollup. After the message is taken out, the application can preprocess the message , such as discarding a response to some messages, or invoking translatemessage to produce a new message.

(3) The application invokes DispatchMessage and passes the message back to the operating system . Messages are represented by the MSG structure object, which contains the handle of the window that receives the message. Therefore: the DispatchMessage function always carries on the correct transmission.

(4) The operation uses the Lpfnwndproc member of the WNDCLASS structure to invoke the window procedure function, and process the message (that is, "the system sends the message to the application").

Add:

(1) Getting messages from message queues can also call the PeekMessage function, which is the following function prototype:

BOOL PeekMessage (
 lpmsg lpmsg,/     /message Information
 HWND hwnd,      //Handle to Window
 UINT Wmsgfiltermin,///UINT Wmsgfiltermax,//Last message
 UINT wremovemsg   //Removal options< c14/>);

The first four parameters have the same function as the GetMessage function;

The last parameter specifies how the message is fetched, and if set to Pm_noremove, the message will not be removed from the message queue, and if set to Pm_remove, the message will be removed from the message queue (consistent with the behavior of the GetMessage function)

  (2) The SendMessage and PostMessage functions can be used to send messages.

SendMessage sends the message directly to the window and calls the window procedure of the window to process it, and the function returns after the window process has finished processing the message (SendMessage message is not sent).

The PostMessage function returns the message immediately after it is placed in the message queue associated with the line threads relative that created the window.

PostThreadMessage function, which is used to send messages to threads.

For thread messages, the HWND member in the MSG structure body is null.

(iv), writing window procedure functions: For processing messages sent to a window

Lresult CALLBACK WindowProc (  //Window procedure function name can be arbitrarily taken, such as: Winazeproc, but the function declaration and definition to be consistent;
 HWND hwnd,   //Handle to Window
 UINT umsg,   //Messages Identifier message code
 WPARAM WPARAM,//First message parameter two added value of the messaging code LPARAM LPARAM  ///second message parameter
);

Hint: the system calls the window procedure function, not the name, through the address (pointer) of the window procedure function.

Writing window procedure functions lresult CALLBACK Winazeproc (HWND hwnd,//Handle to Window UINT umsg,//Mess Age identifier WPARAM WPARAM,//A/I parameter LPARAM LPARAM//second message para
    meter) {switch (umsg) {case WM_CHAR://Convert to CHAR szchar[20 by calling TranslateMessage function);
    sprintf (Szchar, "Char code is%d", wParam);
    MessageBox (hwnd, Szchar, "char", 0);
  Break
    Case Wm_lbuttondown:messagebox (hwnd, "Mouse clicked!", "message", 0);
    HDC HDC;    HDC = GetDC (hwnd);
                Use HDC to save the handle returned by the GETDC function to the DC associated with a particular window. GetDC () cannot invoke TextOut in response to WM_PAINT messages (hdc, 0, 50, "The Programmer's Home!", strlen ("The Programmer's House!").  ") );  TextOut uses the resulting DC handle to output a line of text ReleaseDC (HWND, HDC) at a specified location (0,50);
  Release HDC break; Case WM_PAINT://When part of the window customer service area becomes "invalid", the system sends a WM_PAINT message notifying the application that the client area is invalid when the window//window was first created, and when the UpdateWindow function is invoked, it is sent wm_ Paint the message to the window process, refresh the window//when the window from scratch, change the size, minimize the restore, when the window is obscured by other windows, the client area will become invalid, when the system will give the applicationSends a WM_PAINT message that notifies the application to redraw//hint: whether a redraw occurs when the window is changed, depending on whether the style member in the WNDCLASS structure has the Cs_hredraw and Cs_vredraw flags HDC HDC;    Paintstruct PS;  PS is used to receive the information drawn HDC = BeginPaint (hwnd, &AMP;PS); 
    BeginPaint only in response to WM_PAINT messages is called TextOut (HDC, 0, 0, "http://www.sunxin.org", strlen ("http://www.sunxin.org"));
    EndPaint (hwnd, &AMP;PS);
  Break Case Wm_close:if (Idyes = = MessageBox (hwnd, "Do you really Quit?")
    "," message ", Mb_yesno)) {DestroyWindow (HWND);
  } break;
    Case Wm_destroy:postquitmessage (0);
  Break Default:return DefWindowProc (hwnd, umsg, WParam, LParam);
DefWindowProc invokes the default window procedure, providing default processing for other messages that the application does not handle.
For most messages, the application can call the DefWindowProc function directly for processing.
  When you write a window procedure, the call to the DefWindowProc function is placed in the default statement, and the return value of the function is used as the return value of the window procedure function.
return 0;

 }

Tip: to output text in a window or to display graphics, you need to use the Device Description table (Device context).

Device Description Table (DC for short):

A DC is a structure that contains information about devices (physical output devices, such as displays, device drives), and all graphics operations are done using DCS on the Windows platform.

30th, 31 lines of code: when calling BeginPaint, if the background of the client area has not been erased, then BeginPaint will send WM_ERASEBKGND message to the window, The system erases the background using the brush specified by the Hbrbackground member of the WNDCLASS structure. If we want a graphics clock to be displayed in a window, you should place the drawing of the graph in the code that responds to the WM_PAINT message, such as the location of TextOut ().

第34-48 Line code: The DestroyWindow function sends Wm_destroy messages to the window procedure after the window is destroyed. Note: While the window is destroyed, the application does not exit. Therefore: If you want to control whether the program exits, it should be done in the response code of the WM_CLOSE message.

The response to the WM_CLOSE message is not necessary, and if the application does not respond to the message, the system passes the message to the DefWindowProc function, and the DefWindowProc function uses the DestroyWindow function to respond to the WM_ The close message.

第40-42 Line code: When the DestroyWindow function destroys a window, it sends a WM_DESTROY message to the window procedure and then calls the PostQuitMessage function in the response code of the message. PostQuitMessage a wm_quit message in the message queue of the function entry application and returns. The GetMessage function returns 0 only when a wm_quit message is received, at which point the message loop ends and the program is retired.

to allow the program to exit normally, we must respond to the WM_DESTROY message and call PostQuitMessage in the message response code to post the WM_QUIT message to the application's message queue. The value of the parameter passed to the PostQuitMessage function is used as the wparam parameter of the WM_QUIT message, which is usually used as the return value of the WinMain function.

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.