Programming windows Fifth Edition Reading Notes Chapter 3 window and messages

Source: Internet
Author: User
Programming windows 5th edition Chapter 3 window and message

1. This chapter describes hellowin, the simplest windows program with windows.

2. window type. Before creating a window (calling createwindow), you must register a window class (registerclass ). The so-called window category indicates the common characteristics of the window. For example, the button window has the same category, such as the cursor and background. The most important thing is the message processing function, these things should be the same. As for the differences in the button window, such as the size and position, we will define them in createwindow. Therefore, the window class abstracts some common things of the window. When multiple windows are createwindow, you can share a window class, that is, you only need to execute registerclass once. The most important thing in the window category is to define the message callback function, that is, the message processing function. Some people may worry about this. Since the message processing function is defined in the window category, if a bunch of windows are created using a window category, are the message processing functions of these windows the same? -- That's right, OK. Now, how can I process the same message in these windows differently? -- Very simple. In the message processing function, there is an hwnd parameter that identifies the sentence handle of the window (that is, what is returned by createwindow). This can be used to differentiate different windows.

3. Let's take a look at the hellowin code in this chapter:

Code: select all
/*------------------------------------------------------------
   HELLOWIN.C -- Displays "Hello, Windows!" in client area
                 Eric Zhang 2007
  ------------------------------------------------------------*/

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("HelloWin") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     hwnd = CreateWindow (szAppName,                  // window class name
                          TEXT ("The Hello Program"), // window caption
                          WS_OVERLAPPEDWINDOW,        // window style
                          CW_USEDEFAULT,              // initial x position
                          CW_USEDEFAULT,              // initial y position
                          CW_USEDEFAULT,              // initial x size
                          CW_USEDEFAULT,              // initial y size
                          NULL,                       // parent window handle
                          NULL,                       // window menu handle
                          hInstance,                  // program instance handle
                          NULL) ;                     // creation parameters
     
     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 ;
     RECT        rect ;
     
     switch (message)
     {
     case WM_CREATE:
          PlaySound (TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
          return 0 ;

     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
         
          GetClientRect (hwnd, &rect) ;
         
          DrawText (hdc, TEXT ("Hello, Windows!"), -1, &rect,
                    DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
          EndPaint (hwnd, &ps) ;
          return 0 ;
         
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

4. hellowin is very simple. It creates a window and writes text in the central position. In addition, a WAV file is played when the window is displayed. Note: To play the wav file, the playsound function is called in the Code. To use this function, remember to link the winmm. Lib file to the project.

5. Now let's look at the code. First, there are many constants in the Code, such as cs_hredraw and wm_paint. These constants do not need to be remembered. You can check the manual when necessary. These constants have specific meanings and some common writing formats:

Appendix 1

In addition, there are some other data types in the code, as shown below:

Attachment 2 Attachment 3

In Attachment 3, all the items are handles that point to different things. In Windows, handles are widely used, just like file descriptors in Linux programming. In Windows, the handle is a 32-bit integer that represents an object. Many Windows functions require a handle so that Windows functions can know who the operation object is.

6. Hungarian labeling. The variable names in the Code basically use the Hungary markup method. In fact, the program in the first chapter has started to use it. Here we make a summary. For more information about writing code in the future, see:

Appendix 4

7. Now let's look at the code. First, we define a function prototype, that is, the prototype of our message processing function. Lresult is the long type. Callback is the same as winapi, that is, _ stdcall. With callback, Windows will call our message processing function in the future to avoid inconsistency of call convention, therefore, this callback is usually required. Among the four parameters of wndproc, the first parameter is the window handle, the second parameter is the message code, and the third and fourth parameters are two parameter, in 32-bit windows, wparam is uint -- unsigned int, and lparam is long. In 16-bit windows, wparam is originally of the word -- unsigned short type. Therefore, in Hungary notation, wparam should be written as uiparam. However, since wparam was originally used in 16-bit windows, it was not modified yet.

8. Then the code is the registration window category. The Registry window class calls registerclass. This function only requires one parameter, namely, the window class structure wndclass. Because this wndclass contains two string member variables, we can recall the content in chapter 2. Naturally, this wndclass has two versions: wndclassa and wndclassw. The string in this wndclass is naturally a T-type string. OK. Let's take a look at the content in this structure:

Style: Specifies the window style. Cs_hredraw | cs_vredraw is written in the Code. This indicates that the window is repainted when it changes horizontally or vertically. This is why the text is still displayed in the middle of the window after the window size is changed. This is because the window is re-painted and the wm_paint message is triggered. In winuser. H, you can find the constants of all Cs headers (indicating window class styles. Observe the values of these constants. In fact, each of them converts a position in the binary number to 1. Therefore, they can be connected with each other by using symbols or symbols.

Lpfnwndproc -- this is the most important. It specifies the message processing function, which is a function pointer.

Cbclsextra, cbwndextra -- reserved space. If necessary, the program can customize this part of content.

Hinstance -- is the instance handle of our program, the first parameter of winmain

Hicon -- specifies the window icon, which appears in the leftmost and taskbar of the window title bar.

Hcursor -- specifies the cursor of the mouse. Here, loadicon and loadcursor. If the first parameter is null, it indicates the icons and mouse cursor predefined by windows. It is specific to the msdn of these two functions. If we want to use our own icons or cursors, we need to set the first parameter to hinstance, that is, the instance handle of our program.

Hbrbackground -- the background of the window. HBr indicates handle to a brush. In Windows, the brush represents the coloring style used to fill a region. Windows has several standard brushes called stock brush ). So we use getstockobject to get a white brush.

Lpszmenuname -- specify the application menu

Lpszclassname -- Name of the window category. The content here should be the same as the first parameter in createwindow. If the window we created wants to use this window category.

9. OK, everything is ready. Call registerclass. Here the Code makes an error processing judgment. This is correct, because registerclass also has a/W versions, if we define the Unicode condition to compile the variable, we will call registerclassw in the future, and Win98 has this function, however, when this function is called, Win98 immediately returns an error (only a small part of Win9x supports Unicode, for example, messageboxw can be used ).

BTW: For error handling, we often call the getlasterror function, which can return the error code of the previous operation failure, the meanings of these error codes can be found in/Platform SDK/Windows base services/debugging and error handling/error codes/system errors-numerical order of msdn.

10. Then we can see the createwindow function. There are comments in the code. Only the second parameter, cw_overlappedwindow, is a collection of constants (defined in winuser. h ):

Code: select all
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     | \
                             WS_CAPTION        | \
                             WS_SYSMENU        | \
                             WS_THICKFRAME     | \
                             WS_MINIMIZEBOX    | \
                             WS_MAXIMIZEBOX)

Used to represent the window form.

11. Then the Code calls showwindow to display the window, and then calls updatewindow. This function will trigger the wm_paint message to initialize the graphics and text in the window.

I tried it myself and found that the wm_paint message is still generated without calling updatewindow, and the window is still displayed normally. I thought that updatewindow was called only for standardization, but later I learned from the next chapter and found that it makes sense to call updatewindow here. The truth is that updatewindow generates the wm_paint message, but the difference is that the wm_paint message generated this time is not a queue message. That is to say, after calling this function, Windows will immediately call our message processing function, updatewindow does not return the message until the message is processed. If you do not use this function, the wm_paint messages generated will only be placed in the message queue. In Windows, wm_paint messages are a message with a low priority, this will cause the interface to be updated in a timely manner-in short, when we need to update the window interface immediately, please use updatewindow, which can be used in many places.

12. then enter the message loop, and use getmessage to retrieve messages from the message queue. Note: in windows, no message is sent to the message queue, and some messages are not sent to the message queue, in this case, Windows directly calls the message processing function. These messages are called non-queued messages. However, we don't need to care about these complicated problems. We just need to know that any message will be processed in our message processing function. The structure of MSG in getmessage is as follows:

Code: select all
typedef struct tagMSG
{
     HWND   hwnd ;
     UINT   message ;
     WPARAM wParam ;
     LPARAM lParam ;
     DWORD  time ;
     POINT  pt ;
} MSG, * PMSG ;

The parameter Meanings of the getmessage function can be viewed in msdn. If the second parameter is null, messages in all windows created by the process are accepted; the third and fourth parameters indicate the min and max values of the message to be filtered. That is to say, the message number within this range will be captured by getmessage. If both values are 0, there is no message filtering. The getmessage function always returns a non-zero number, unless the wm_quit message is obtained.

In the MSG structure, hwnd is the handle to the Message occurrence window, message is the message number, wparam, and lparam is the message parameter. You can obtain the message details here, and time is the occurrence time, PT is the coordinate of the mouse when the message occurs.

13. translatemessage transmits MSG to Windows for some keyboard conversion. This will be discussed in chapter 6. dispatchmessage refers to sending MSG back to Windows, and then windows will call our message processing function (wndproc, the message is manually getmessage by our program and sent again. If a non-queued message does not pass getmessage, Windows calls the message processing function directly.

14. Message loop and message processing. Pay attention to the following points:

1. After dispatchmessage is sent out, the function will not return until the message is processed (the message processing function returns), and getmessage will be executed to retrieve the Next message.

2. the same applies to message processing functions. If other messages are triggered during message processing, the code for triggering messages is also block, until the triggered new message is processed.

3. The message processing function must return 0 unless it is return defwindowproc.

15. The following code is the message processing function, which has the following points:

The wm_create message is generated during the createwindow execution.

For wm_paint message processing, it basically starts from beginpaint and ends with endpaint. Because beginpaint will return an HDC. With this HDC, we can write and draw in the window. In addition, beginpaint will fill in a paintstructure, which will tell us which areas need to be re-painted (invalid ). In beginpaint, if the display area background is not deleted, Windows will delete it. Windows will erase the display area based on the background in the registration window category. If our message processing function does not process wm_paint, defwindowproc simply calls beginpaint and endpaint to make the display area take effect again.

In the corresponding wm_destroy message, we call the postquitmessage function. This function will send the wm_quit message. When the getmessage encounters this message, 0 is returned, and the message loop in winmain ends. Parameter 0 is set to the wparam of the message, so we return msg. wparam in winmain.

Sometimes, defwindowproc will produce other messages after processing the message. For example, if the user executes hellowin and finally clicks the close button, or if the user selects close from the System Menu by keyboard or mouse, defwindowproc processes the keyboard or mouse input, after the user detects that the close option is selected, it sends a wm_syscommand message to the window message processing program. Wndproc sends the message to defwindowproc. Defwindowproc sends a wm_close message to the window message handler to respond. Wndproc sends it to defwindowproc again. Destroywindow calls destroywindow to respond to this wm_close message. Destroywindow causes windows to send a wm_destroy message to the window message handler. Wndproc then calls postquitmessage and puts a wm_quit message into the message queue to respond to the message. This message causes the message in winmain to terminate cyclically and end the program.

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.