Fourth lesson drawing text
In this lesson, we will learn how to "draw" strings on the window of the window. We will also learn the concept of "equipment environment".
theory:
The text in Windows is a GUI (Graphical User Interface) object. Each character is actually composed of many pixel points, which is displayed in a stroke, which will appear. This is why I say "draw" characters, not writing characters. Usually you are "drawing" strings in your application's client area (although you can also "draw" outside the customer area). The "Draw" string method under Windows is completely different under DOS. Under DOS, you can imagine the screen into a plane of 85 x 25, and Windows has several applications on the screen, so you The specification must be strictly followed. Windows does this by limiting every application in his client area. Of course, the size of the customer area is variable, you can adjust it at any time.
Before you "Draw" strings in the customer area, you must get the size of your client area from Windows, you can't "draw" anywhere in the screen as you want to do with your heart, you must get Windows before you want to draw. Allowed, then Windows will tell you the size of the client, font, colors, and other GUI objects. You can use these to "draw" in the customer area.
What is "equipment environment" (DC)? It is actually a data structure maintained inside Windows. A "device environment" and a specific device are connected. Like printers and displays. For the monitor, the "device environment" is connected to one specific window.
Some properties and drawings in the Equipment Environment, like: colors, fonts, etc. You can change those default values at any time, and save the default is for convenience. You can imagine the "Device Environment" as a drawing environment that Windows prepared for you, and you can change some default properties as needed.
When the application needs to draw, you must get a handle of a "device environment". There are usually several ways.
Use Call BeginPaint in the WM_PAINT message to build your own DC in other messages.
You must keep in mind that you must release the Device Environment handle after processing a single message. Do not get the "Device Environment" handle in a message processing, and in another message processing is released.
We handle the client area when Windows sends a WM_PAINT message. Windows does not save the content of the client area. It is used by the method "heavy painting" mechanism (such as the client area just covered by another application), Windows WM_PAINT messages will be placed in the message queue of the application. The client area of the redraw window is your own responsibility. What you have to do is how to draw what is drawn and how to draw.
Another concept you must understand is "invalid area". Windows is called "invalid area" on a square area that is redrawed with a minimum need to red. When Windows discovers a "invalid area", it sends a WM_PAINT message to the application. During the WM_PAINT process, the window first gets a structure of the drawing, including the coordinate position of the invalid area, and the like. You can make the "invalid zone" valid by calling BeginPaint, if you do not process the WM_PAINT message, at least call the default window handling function DefWindowProc, or call ValidateRect to make the "invalid area" valid. Otherwise your application will receive an endless WM_PAINT message.
Below is the step of response to the message:
Acquired "Equipment Environment" handle to draw a client area to release the device environment handle
Note that you don't have to explicitly make the "invalid zone" valid, this action is automatically completed by BeginPaint. You can call all draw functions between BeginPaint and Endpain. Almost all GDI functions require the handle of the "Equipment Environment" as a parameter. content:
We will write an app that will display a line in the center of the customer area "Win32 Assembly IS Great and Easy!"
.386 .Model flat, Stdcall Option Casemap: NONE
Winmain Proto: DWORD,: DWORD,: DWORD,: DWORD
INCLUDE /MASM32/INCLUDE/Windows.inc include /masm32/include/user32.inc includelib /masm32/lib/user32.lib include /masm32/include/kernel32.inc includelib /masm32/lib/kernel32.lib
.Data classname DB "SimpleWinclass", 0 Appname DB "Our First Window", 0 OurtExt DB "Win32 Assembly Is Great and Easy!", 0
.DATA? Hinstance Hinstance? Commandline LPSTR?
. Code Start: Invoke GetModuleHandle, Null Mov Hinstance, Eax Invoke Getcommandline Mov Commandline, Eax Invoke Winmain, Hinstance, Null, CommandLine, SW_SHOWDEFAULT INVOKE EXITPROCESS, EAX
WinMain proc hInst: HINSTANCE, hPrevInst: HINSTANCE, CmdLine: LPSTR, CmdShow: DWORD LOCAL wc: WNDCLASSEX LOCAL msg: MSG LOCAL hwnd: HWND mov wc.cbSize, SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra, NULL mov wc.cbWndExtra, NULL push hInst pop wc.hInstance mov wc.hbrBackground, COLOR_WINDOW 1 mov wc.lpszMenuName, NULL mov wc.lpszClassName, OFFSET ClassName invoke LoadIcon, NULL, IDI_APPLICATION mov wc.hIcon , eax mov wc.hIconSm, eax invoke LoadCursor, NULL, IDC_ARROW mov wc.hCursor, eax invoke RegisterClassEx, addr wc invoke CreateWindowEx, NULL, aDDR ClassName, aDDR AppName, / WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, / CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, / HINST, NULL MOV HWND, EAX INVOKE ShowWindow, Hwnd, SW_SHOWNORMAL INVOKE UPDATEWINDOW, HWND .WHILE TRUE INVOKE GETM Essage, Addr MSG, NULL, 0, 0.Break .if (! EAX) Invoke TranslateMessage, Addr Msg Invoke DispatchMessage, Addr Msg .Endw Mov EAX, MSG.WParam Ret Winmain Endp
WndProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM LOCAL hdc: HDC LOCAL ps: PAINTSTRUCT LOCAL rect: RECT .IF uMsg == WM_DESTROY invoke PostQuitMessage, NULL .ELSEIF uMsg == WM_PAINT invoke BeginPaint, hWnd, ADDR ps mov hdc, eax invoke GetClientRect, hWnd, ADDR rect invoke DrawText, hdc, ADDR OurText, -1, ADDR rect, / DT_SINGLELINE or DT_CENTER or DT_VCENTER invoke EndPaint, hWnd, ADDR ps .ELSE invoke DefWindowProc, hWnd, uMsg, wParam Analysis: LPARAM RET .Endif XOR EAX, EAX RET WNDPROC ENDP End Start Analysis:
The most code here, and the same in the third lesson. I only explain some of these different places.
Local HDC: HDClocal PS: PaintstructLocal Rect: Rect
These local variables are called by the GDI function in the WM_PAINT message. HDC is used to store the "Device Environment" handle returned by BeginPaint. PS is a variable of a PaintStruct data type. You will usually use many of them, which is passed to becompaint by Windows, and then post it to endpaint after the end draws. RECT is a RECT structure type parameter, which is defined as follows:
Rect struct left long? Top long? Right long? Bottom Long? Rect ends
LEFT and TOP are coordinates in the upper left corner of squares. Right and Bottom are coordinates in the right corner of the square. The coordinates of the upper left corner of the client area are x = 0, y = 0, so that the coordinate point of x = 0, Y = 10 is below it.
invoke BeginPaint, hWnd, ADDR psmov hdc, eaxinvoke GetClientRect, hWnd, ADDR rectinvoke DrawText, hdc, ADDR OurText, -1, ADDR rect, / DT_SINGLELINE or DT_CENTER or DT_VCENTERinvoke EndPaint, hWnd, ADDR ps
When processing the WM_PAINT message, you call the BeginPAint function to pass it to a window handle and an unaprised PaintStruct type parameter. Returns the handle of the "Device Environment" in EAX after successful call. Next time, the getClientRect is called to get the size of the client area, and the size is placed in the RECT and then passes it to DrawText. DrawText's grammar is as follows:
DrawText Proto HDC: HDC, LPSTRING: DWORD, NCOUNT: DWORD, LPRECT: DWORD, UFORMAT: DWORDDRAWTEXT is a high-level call function. It can automatically handle such a shortcomings, put the text in the middle of the client area. So you only concentrate "draw" strings. We will explain a layer of function Textout in the next lesson, which formats a text string in a square area. It uses the currently selected font, color and background colors. It handles the wrap to accommodate the square area. It returns the height of the text of the device logical unit metrics, and our measure unit here is a pixel point. Let's take a look at the parameters of this function:
HDC: Handle of the "Equipment Environment". LPSTRING: The text string to display, the text string either at the end of NULL, either pointing out in ncount. NCOUNT: The length of the text to output. If the end is ended in NULL, this parameter must be -1. LPRECT: Pointing to the square area of the text string, the square must be a cropped zone, that is, characters that exceed the area will not be displayed. UFORMAT: Specifies how to display. We can use OR to put the following flags or to a piece:
DT_SINGLINE: Whether a single line is displayed. DT_Center: Whether it is horizontal. DT_VCENTER: Whether it is vertical.
After the drawing, you must call the endpaint to release the handle of the Device Environment. Ok, now we summarize the "drawing" text strings as follows:
BeginPaint and endpaint must be called at the beginning and end; all draw functions are called between BeginPaint and EndPain; if you redeeted the client area in other message processing, you can have two options: (1) Use getdc and releasedc Instead of BeginPaint and Endpaint; (2) call invalidateRect or UpdateWindow to make the customer area invalid, this will force Windows to put the WM_Paint into the application message queue, so that the customer district re-painted.