ICZelion TUT4

zhaozj2021-02-11  216

Tutorial 4: Painting with text

Theory:. Text in Windows is a type of GUI object Each character is composed of numerous pixels (dots) that are lumped together into a distinct pattern That's why it's called "painting" instead of "writing" Normally, you paint text in.. your own client area (actually, you can paint outside client area but that's another story). Putting text on screen in Windows is drastically different from DOS. in DOS, you can think of the screen in 80x25 dimension. But in Windows, the screen are shared by several programs. Some rules must be enforced to avoid programs writing over each other's screen. Windows ensures this by limiting painting area of ​​each window to its own client area only. The size of client area of ​​a window is also not constant. The user can change the size. So you must determine The Dimensions of Your OWN Client Area Dynamical.

Before you can paint something on the client area, you must ask for permission from Windows. That's right, you do not have absolute control of the screen as you were in DOS anymore. You must ask Windows for permission to paint your own client area . Windows will determine the size of your client area, font, colors and other GDI attributes and sends a handle to device context back to your program. You can then use the device context as a passport to painting on your client area.

What is a device context? It's just a data structure maintained internally by Windows. A device context is associated with a particular device, such as a printer or video display. For a video display, a device context is usually associated with a particular window on .

Some of the values ​​in the device context are graphic attributes such as colors, font etc. These are default values ​​which you can change at will. They exist to help reduce the load from having to specify these attributes in every GDI function calls.You can Think of a Device Context as a default environment prepared for you by windows. You can override some default settings later if you so wish.

.

Call beginpaint in response to wm_paint message.

Call getdc in response to other messages.

Call createdc to create your OWN Device Context

One thing you must remember, after you're through with the device context handle, you must release it during the processing of a single message. Do not obtain the handle in response to one message and release it in response to another.

Windows posts WM_PAINT messages to a window to notify that it's now time to repaint its client area. Windows does not save the content of client area of ​​a window. Instead, when a situation occurs that warrants a repaint of client area (such as when a window was covered by another and is just uncovered), Windows puts WM_PAINT message in that window's message queue. It's the responsibility of that window to repaint its own client area. You must gather all information about how to repaint your client area in the WM_PAINT section Of Your Window Procedure, So The Window ProCudure Can Repaint The Client Area When WM_Paint Message Arrives.

Another concept you must come to terms with is the invalid rectangle. Windows defines an invalid rectangle as the smallest rectangular area in the client area that needs to be repainted. When Windows detects an invalid rectangle in the client area of ​​a window, it posts WM_PAINT message to that window. in response to WM_PAINT message, the window can obtain a paintstruct structure which contains, among others, the coordinate of the invalid rectangle. you call BeginPaint in response to WM_PAINT message to validate the invalid rectangle. If you do not process WM_PAINT message, at the very least you must call DefWindowProc or ValidateRect to validate the invalid rectangle else Windows will repeatedly send you WM_PAINT message.Below are the steps you should perform in response to a WM_PAINT message:

Get a Handle to Device Context with beginpaint.

Paint The Client Area.

Release The Handle To Device Context with endpaint

Note that you do not have to explicitly validate the invalid rectangle. It's automatically done by the BeginPaint call. Between BeginPaint-Endpaint pair, you can call any GDI functions to paint your client area. Nearly all of them require the handle to device context As a parameter.

Content: WE WILL WRITE A Program That Displays a Text String "WIN32 Assembly IS Great and Easy!" In the center of the client area.

.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 , lParam Ret .ndif xor EAX, EAX RET WNDPROC ENDS: The Majority of The Code Is The Same As The Example In Tutorial 3. I'll Explain Only The Important Changes.

Local HDC: HDC Local PS: PaintStruct local Rect: Rect

These are local variables that are used by GDI functions in our WM_PAINT section. Hdc is used to store the handle to device context returned from BeginPaint call. Ps is a PAINTSTRUCT structure. Normally you do not use the values ​​in ps. It's passed to Beginpaint Function and Windows Fills It With Appropriate Values. You Then Pass Ps To Endpaint Function When You Finish Painting The Client Area. Rect Is A Rect Structure Defined As Follows:

Rect struct

LEFT Long?

Top long?

Right long?

Bottom Long?

Rect ends

Left and top are the coordinates of the upper left corner of a rectangle Right and bottom are the coordinates of the lower right corner One thing to remember:. The origin of the xy axes is at the upper left corner of the client area So the. Point y = 10 is belew the point y = 0.

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 psIn response to WM_PAINT message, you call BeginPaint with handle to the window you want to paint and an uninitialized PAINTSTRUCT structure as parameters. After successful call, eax contains the handle to device context. Next you call GetClientRect to retrieve the dimension of the client area. The dimension is returned in Rect Variable Which You Pass to DrawText As One of Its Parameters. DrawText's Syntax IS:

DrawText Proto HDC: HDC, LPSTRING: DWORD, NCOUNT: DWORD, LPRECT: DWORD, UFORMAT: DWORD

DrawText is a high-level text output API function. It handles some gory details such as word wrap, centering etc. so you could concentrate on the string you want to paint. Its low-level brother, TextOut, will be examined in the next tutorial. DrawText formats a text string to fit within the bounds of a rectangle. It uses the currently selected font, color and background (in the device context) to draw the text.Lines are wrapped to fit within the bounds of the rectangle. It Returns The Height of The Output Text in Device Units, IN Our Case, Pixels. Let's See it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it it has parameters:

HDC Handle to Device Context

LPString The pointer to the reason. The string must be null-terminated else You Would Have to Specify ITS Length in The next parameter, ncount.

Ncount The Number of Characters to Output. If The String is Null-Terminated, Ncount Must Be -1. Otherwise Ncount Must Contain The Numr of Characters in The String You Want To Draw.

lpRect The pointer to the rectangle (a structure of type RECT) you want to draw the string in. Note that this rectangle is also a clipping rectangle, that is, you could not draw the string outside this rectangle.uFormat The value that specifies how The string is displayed in the rectangle. We use three values ​​combined by "OR" Operator:

DT_SINGLINE SPECIFIES A SINGLE LINE OF TEXT DT_CENTER CENTERS The Text Horizontally. Dt_vcenter centers the text value. Must be used with dt_singeline.

After You Finish Painting The Client Area, You Must Call Endpaint Function To Release The Handle To Device Context.

That's it. We can Summarize the salient point:

. You call BeginPaint-EndPaint pair in response to WM_PAINT message Do anything you like with the client area between the calls to BeginPaint and EndPaint If you want to repaint your client area in response to other messages, you have two choices.:

Use GetDC-ReleaseDC pair and do your painting between these calls Call InvalidateRect or UpdateWindow to invalidate the entire client area, forcing Windows to put WM_PAINT message in the message queue of your window and do your painting in WM_PAINT section

转载请注明原文地址:https://www.9cbs.com/read-4676.html

New Post(0)