----- A friend passing by, if you find an error or have good suggestions, please leave a message below. Thank you! -----
The device description table is so important that we have to learn about it here. This section contains a small amount of content. I believe you will soon be able to read it. Let 'go!
Get device description table handle
Review: When you want to draw on a graphic output device (such as a screen or printer), you must first obtain a device description table (or DC) handle. When sending a handle to a program, Windows gives you the permission to use the device. Then you use this handle as a parameter in the GDI function to identify the device on which you want to draw. If a device description table handle is obtained when processing a message, release it (or delete it) before exiting the window function ). Once the handle is released, it is no longer valid.
Windows provides several methods to obtain the device description table handle, as shown below.
Method 1:
This is the most common method to obtain and release the device description table handle, that is, to use the beginpaint and endpaint functions when processing the wm_paint message. These two functions require the address of the window handle of the program and the variable of the paintstruct structure as parameters. Windows programmers usually name this structure variable PS and define it during the Window Process:
Paintstruct pS;
When processing the wm_paint message, the window process first calls beginpaint. Generally, in the beginpaint function call, if the background of the invalid region in the customer zone has not been erased, Windows will erase the background. (It uses the paint brush specified in the hbrbackground member variable of the registered window wndclass structure to erase the background. we mentioned the previous comment 1)
The beginpaint call makes the entire customer zone valid and returns a device description table handle. This return value is usually stored in a variable called HDC. This function is also filled in the PS structure field (you can recall the previous comment 1 ).
The device description table handle is defined in the window as follows:
HDC; // define the device description table handle variable
Then, the program can use GDI functions such as textout, which requires the device to describe the table handle. The device description table handle is required to display text and graphics in the customer area of the window, but the device description table handle returned from beginpaint cannot be drawn outside the customer area. Call endpaint to release the device description table handle.
Generally, the form of processing the wm_paint message is as follows:
Casewm_paint:
HDC = beginpaint (hwnd, & PS );
[Other program lines]
Endpaint (hwnd, & PS );
Return 0;
Let's emphasize it again (don't blame me): The beginpaint call makes the entire customer zone valid (to prevent wm_paint messages from being sent all the time, see the appendix) and fills in the PS structure fields, the handle of the returned device description table. Use this handle to draw only within the area specified by the rcpaint field in the ps structure. The endpaint call can release the handle of the device description table. The two functions must be used in pairs. Generally, they are only used to process wm_paint messages.
When processing a non-wm_paint message, Windows programs can obtain the device description table handle using the following methods. Of course, the following function calls will not make the invalid region in the customer zone valid.
Method 2:
hdc = GetDC (hwnd) ;
[other program lines]
ReleaseDC (hwnd, hdc) ;
After the getdc function is called, the device description table handle corresponding to the customer zone of the window specified by the hwnd parameter is returned. It can be seen that the basic difference between getdc call and beginpaint is that the handles returned from getdc can be drawn across the entire customer zone. If the hwnd parameter is set to null, the function returns the device description table handle of the entire desktop. When you no longer need the device environment, you need to call the releasedc function to release the device description table.
Method 3:
HDC = getwindowdc (hwnd );
[other program lines]
ReleaseDC (hwnd, hdc) ;
Getwindowdc returns the device description table handle that can be drawn in the entire window (including the customer area and the title bar, menu, scroll bar, frame, and other non-customer areas), but this function is rarely used.
Method 4:
HDC = createdc (lpszdriver, lpszdevice, lpszoutput, lpdata );
[other program lines]
DeleteDC (hdc) ;
The device content obtained by beginpaint, getdc, and getwindowdc is related to a specific window (hwnd) on the display. Createdc is a more common function for obtaining the device description table handle. It can even obtain the non-Display output device description table handle. When the device description table is no longer requiredOnlyCall the deletedc function to delete it.
Of course, there are still many functions to get the device description table. Let's briefly introduce them here. We will discuss other similar functions later.
Properties of the device description table--We mentioned this last time.
The device description table contains many current "attributes" that determine how the GDI function works on the device. These attributes allow the parameters passed to the GDI function to only contain the start coordinate or size information, it does not need to contain all other information required for Windows to display objects on devices. For example, when we call textout, we only need to provide the device description table handle, start coordinate, text, and text length in the function. You do not need to specify the font, text color, background color behind the text, and Character spacing, because these attributes are part of the device description table. When you want to change these attributes, you can call a function that can change the attributes in the device description table (for example, set the text color to red ), later, you can use the changed attributes for the textout call of the device description table (for example, you can output a red font ).
I will list the following tables for your convenience.
Attribute |
Default Value |
Related functions |
Background Color |
White |
Getbkcolor |
Setbkcolor |
Background Mode |
Opaque |
Getbkmode |
Setbkmode |
Bitmap |
None |
Createbitmap |
Createbitmapindirect |
Createcompatiblebitmap |
SelectObject |
Paint Brush |
White_brush |
Createbrushindirect |
Createdibpatternbrush |
Createhatchbrush |
Createpatternbrush |
Createsolidbrush |
SelectObject |
Starting position of the image brush |
(0, 0) |
Getbrushorg |
Setbrushorg |
Unrealizeobject |
Cropping domain |
Display surface |
Excludecliprect |
Intersetcliprect |
Offsetcliprgn |
Selectclippath |
SelectObject |
Selectcliprgn |
Color palette |
Default_palette |
Createpalette |
Realizepatte |
Selectpalette |
Drawing Method |
R2_copypen |
Getrop2 |
Setrop2 |
Font |
System_font |
Createfont |
Createfontindirect |
SelectObject |
Character Spacing |
0 |
Gettextcharacterextra |
Settextcharacterextra |
Ing method |
Mm_text |
Getmapmode |
Setmapmode |
Paint Brush |
Black_pen |
Createpen |
Createpenindirect |
SelectObject |
Polygon filling mode |
Alternate |
Getpolyfillmode |
Setpolyfilemode |
Scaling Mode |
Blackonwhite |
Setstretchbltmode |
Getstretchbltmode |
Text color |
Black |
Gettextcolor |
Settextcolor |
View range |
(1, 1) |
Getviewportextex |
Setviewportextex |
Scaleviewportextex |
View Origin |
(0, 0) |
Getviewportorgex |
|
|
Setviewportorgex |
Window range |
(1, 1) |
Getwindowextex |
Setmediawextex |
Scaleappswextex |
Window Origin |
(0, 0) |
Getw.worgex |
Offsetworgex |
Setw.worgex |
Generally, a function starting with get is used to obtain the attribute value. Generally, a function starting with set is used to set the attribute value. If you have a function that is not clear about it, check it by yourself.
Save device description table
Generally, when you call getdc or beginpaint, Windows uses the default value to create a new device description table. When you call releasedc or endpaint to release the property, will be lost. If your program needs to use a non-default device description table attribute, you must initialize the device content each time you obtain the device description table handle:
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
[initialize device context attributes]
[paint client area of windows]
EndPaint (hwnd, &ps) ;
return 0 ;
Although this method is quite satisfactory in general, you may want to save the changes to the properties of the device description table in the program after releasing the device description table, so that they can still work when getdc and beginpaint are called the next time. To this end, you can include the cs_owndc flag as part of the window class when designing the window class:
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC ;
Now, each window created based on this window class will have its own device description table, which exists until the window is deleted. If the cs_owndc style is used, you only need to initialize the device description table once. You can complete this operation during wm_create message processing:
case WM_CREATE:
hdc = GetDC (hwnd) ;
[initialize device context attributes]
ReleaseDC (hwnd, hdc) ;
These attributes are valid until they are changed.
Cs_owndc StyleOnlyThe device content obtained by getdc and beginpaint is affected, and the device description table obtained by other functions is not affected. With cs_owndc, you should release the device description table before exiting the window.
In some cases, you may want to change the properties of some device description tables, use the changed properties for drawing, and restore the original properties of the device description table. To simplify this process, you can use the following call to save the status of the device description table:
int idSaved = SaveDC (hdc) ;
Now, you can change some attributes and call the following when you want to return to the device content that existed before the savedc call:
RestoreDC (hdc, idSaved) ;
You can call savedc several times before calling restoredc.
Most programmers use savedc and restoredc in different ways. However, more like the push and pop commands in assembly language, when you call savedc, you do not need to save the return value:
SaveDC (hdc) ;
Then, you can change some attributes and call savedc again. To restore the device content to a saved status, call:
RestoreDC (hdc, -1) ;
This restores the device description table to the State recently saved by the savedc function.
Appendix
TIPS:
To plot outside the updated rectangle when processing the wm_paint message, you can use the following function before calling beginpaint:
InvalidateRect (hwnd, NULL, TRUE) ;
It makes the entire display area invalid and erased the background. However, if the last parameter is set to false, the background is not erased and the original content is retained.
This is usually the most convenient way for Windows programs to simply re-draw the entire customer zone whenever they receive the wm_paint message without considering the rcpaint structure. For example, if a circle is included in the display output of the customer area, but only a part of the circle falls into an invalid rectangle, it only draws the part of the circle in the invalid rectangle. This is meaningless for drawing the entire circle. Note: When you use the device description table handle returned from beginpaint, Windows will not draw any part outside the rcpaint rectangle. Use the above function before calling beginpaint to make the invalid rectangle in the rcpaint structure into the entire customer zone, so you don't have to draw the circle.
When processing the wm_paint message, you must call beginpaint and endpaint in pairs. If the window process does not process the wm_paint message, it must pass the wm_paint message to the defwindowproc (default Window Process) in windows ). Defwindowproc:
Case wm_paint:
Beginpaint (hwnd, & PS );
Endpaint (hwnd, & PS );
Return 0;
There are no statements between the beginpaint and endpaint calls, only to make the previously invalid region valid. However, the following method is incorrect:
Case wm_paint:
Return 0; // wrong !!!
In Windows, A wm_paint message is put into the message queue because part of the customer zone is invalid. If beginpaint and endpaint (or validaterect) are not called, Windows will not make the region valid. If it remains invalid, Windows will send another wm_paint message and keep sending it.