(Translation) Win32ASM instance -7

zhaozj2021-02-16  42

7.0 - Drawing The Tiles

The Tile Control IS Already Made, Now it's time for the tile. The Tile. The Tile. The Tied Can Be One of these

The tile control has been created, and it is time to draw the drawing block. The image of the tile can be one of these images:

Numbered Tiles (Just A Matrix of Numbers)

The demo bitmap (a resource)

A Bitmap the User Chooses

Numbered tile (just digital matrix)

Demo bitmap (a resource)

User selected bitmap

For Now We Will Use The Numbred Tiles, The Bitmap Stuff Will Be Added Later. Furthermore, There Are 4 Color Schemes.

Now, we will use the numbered tile, the contents of the bitmap will be added later. In addition, there are 4 colors.

7.1 - How it works how it works

We'll use device contexts many times A device context is a set of graphic objects that affect the output These graphic objects can be pens, bitmaps, brushes, palette etc. The device contexts we use are..:

We will use the Device Context multiple times. A Device Context is a collection of graphics objects that affect the output. These objects can be Pen, Bitmap, Brushes, Palette, etc. The device context we use is:

Device Contexts (DCS) of Windows (The Bitmap Object In There DCS IS What You Actually See of The Control)

BACK Buffer DC. All The Drawing Will First Be Done ON A So Called Back Buffer. This Prevents Flickering As Drawing Directly To A Control Will Show The Process of Drawing As Well.

Image DC. This DC Contains The Tile Image Currently Used (Numbered Tiles / Demo Bitmap / User Bitmap).

Device Context (DC) of the window (image in these DCs is the control you actually see)

Back Buffer DC. All painting works in a so-called back buffer in advance. This overcomes difficulties in the blinking of the direct painting controls and display the drawing process.

Image DC. This DC contains image of the currently used (number of pieces, demonstration pictures, user pictures)

First the bitmap the user chooses, (the numbered tiles, which are drawn at runtime, the demo bitmap or a user bitmap), is put in the ImageDC. Then the 3D effect of the tiles (highlites and shadows) are drawn on the bitmap in the DC Now remember this:. The imageDC will not change from here, only if the user selects another tile type The drawing is done tile by tile on the back buffer For each tile, the tile is extracted from the ImageDC, then.. First, the user selected the image (the number of numbered pictures, or user pictures plotted at runtime) is placed in the image DC. The 3D effect of the tile is then painted on the picture. Remember this now: In this, the image DC will not change. Only when the user selects another tile type. Painting work is done in a block diagram in the back buffer. For each tile, the tile is expanded from the image DC and then placed in the current location of the tile. An array will save the location of these tiles.

7.2 - Creating The graphic Objects Creating an image object

A New Procedure Is Introduces, InitBitmaps:

Introducing a new process, initbitmap:

InitBitmaps PROTO STDCALL: DWORD [in your .data?] BackBufferDC dd hBackBuffer dd ImageDC dd hImage dd hBackgroundColor dd hTileColor dd hFont dd TextColor dd [in your .data] FontFace db "Arial", 0 [???????? In Your .code]; ============================================ ====================================; init bitmaps; ========== ============================================================================================================================================================================================================= ==================== InitBitmaps proc hWnd: DWORD; Create DC's for backbuffer and current image invoke CreateCompatibleDC, NULL mov BackBufferDC, eax invoke CreateCompatibleDC, NULL mov ImageDC, eax; Create bitmap for backbuffer: invoke GetDC, hWnd push eax invoke CreateCompatibleBitmap, eax, 200 20,200 20 mov hBackBuffer, eax pop eax invoke ReleaseDC, hWnd, eax invoke SelectObject, BackBufferDC, hBackBuffer;

Create Arial font for the numbers invoke CreateFont, -30, NULL, NULL, NULL, FW_EXTRABOLD, / FALSE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, ADDR FontFace mov hFont, eax; Select font in Image DC invoke SelectObject, ImageDC, hFont invoke CreateSolidBrush, 0FF8000h mov hBackgroundColor, eax invoke CreateSolidBrush, 0FF8080h mov hTileColor, eax mov TextColor, 0800000hretInitBitmaps endpLet's examine the procedure step by step:

Let's see this process step by step:

Invoke CreateCompatibledc, Null Mov Backbufferdc, EAX Invoke CreateCompatibledc, Null Mov Imagedc, EAX

CreateCompatibleDC creates a new DC that is compatible with a given window. If NULL is given as parameter (window handle), it is compatible with the default window. One DC is created for the backbuffer, the handle is stored in BackBufferDC. The other is For the Image DC, Stored In Imagedc.

CreateCompatibleDC creates a new DC compatible with a given window. If NULL is given as a parameter (window handle), it is compatible with the default window. The handle of the DC created for Back Buffer is saved in the BackBufferDC. The other is the image DC, stored in the imagedc.

; Create bitmap for backbuffer: invoke GetDC, hWnd push eax invoke CreateCompatibleBitmap, eax, 200 20,200 20 mov hBackBuffer, eax pop eax invoke ReleaseDC, hWnd, eax invoke SelectObject, BackBufferDC, hBackBuffer

CreateCompatibleBitmap creates a new bitmap object that is compatible with a given DC. First we get the DC of the main window with GetDC. The handle is pushed onto the stack to save it for ReleaseDC. CreateCompatibleBitmap is then called, with the main window DC as DC, and 220x220 as bitmap size. The extra 20 pixels are for the margins. The bitmap handle is saved in hBackBuffer, the window DC handle is popped of the stack again and released (ReleaseDC should always be used with GetDC). Finally, SelectObject Selects a Graphic Object In A DC. Here, The BitMap Just Created Is Put in The Backbuffer Dc.createCompAMPATIBEBITMAP Creates a photo object that is a given DC compatible picture. First we use GetDC to get the DC of the main window. This handle is saved in the ReleaseDC press stack. Then use the main window DC and 220 × 220 as the picture size to call CreateCompATIBLEBITMAP. Additional 20 pixels are used for borders. The picture handler is stored in HBackBuffer, and the window DC handle is then popped out and then releases (ReleaseDC is always used with getDC) Finally, selectObject selects a picture object in the DC. Here, the Bitmap just created is placed in BackbufferDC.

; Create Arial font for the numbers invoke CreateFont, -30, NULL, NULL, NULL, FW_EXTRABOLD, / FALSE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, ADDR FontFace mov hFont, eax; Select font in Image DC Invoke SelectObject, Imagedc, HFONT

To Draw The Numbers on The Tiles, We NEED A FONT. CREATEFONT CREATES Such A Font. Look It Up Your Reference, Fontface Is The Name of The Font, "Arial". -30 is a size for the font. The Handle for THE The font is saved in hfont and dam..............

To draw numbers on the tile, we want to font. CreateFont creates such a font. Find it in your reference. FontFace is the font name, "arial", - 30 is the size of the font. The font's handle is stored in the HFONT and then the font is selected by imagedc. Therefore, we can use this font in imagedc.

invoke CreateSolidBrush, 00FFFFFFh mov hBackgroundColor, eax invoke CreateSolidBrush, 00FF0000h mov hTileColor, eax mov TextColor, 000000hFinally, a few brush handles are made, they are not selected in any DC right now, but they will be later. CreateSolidBrush creates a brush with a Certain Color, You Can Use the Handle to Draw Things (Lines etc) with the brush. TextColor is Not a brush, IT's Just A Color Value (We don't need a brush for the text color, "ONLY THE Color Value).

Finally, the handle of a brush is created, and they are not selected by any DC, but will be later. CreateSolidbrush creates a brush with a certain color, you can use this handle to draw something (such as straight line). TextColor is not a brush, it is just a color value (we don't have a brush because the text is required, just color value)

Note: The Image Bitmap IS Not Created Yet, The DC IS Already Available, But As The User Can Choose The Type of Bitmap, This Bitmap is Made When The User Selects a Type, The IT I SELECTED IN THE DC.

Note: The image image is still not created, and the DC already exists. But users can choose the image type. The picture is created when the user selects the type and then is selected in the DC.

A Function to Free All these Handles is Necessary Too:

A function for releasing all of these handles is also necessary:

DeleteBitmaps proto stdcall; ============================================== ==================================; Delete Bitmaps; ============ ============================================================================================================================================================================================================= ================== DeleteBitmaps proc invoke DeleteDC, BackBufferDC invoke DeleteDC, ImageDC invoke DeleteObject, hImage invoke DeleteObject, hBackBuffer invoke DeleteObject, hFont invoke DeleteObject, hBackgroundColor invoke DeleteObject, hTileColorretDeleteBitmaps endpThen both Functions Should Be Called:

Then call two functions:

.... if eax == wm_create invoke initcontrols, hwnd; <<< Insert here.elseif eax == wm_destroy invoke deleteBitmaps; <<<< Other one here invoke postquitmessage, null ...

On Creation of the Main Window, The Bitmaps and DCS Are Initialized, Before Destroying, The Bitmaps and DCS Are Deleted Again.

During the creation of the main window, the pictures and DCs are initialized. The pictures and DCs are again deleted before the window is destroyed.

7.3 - TILE MODE Tile Mode

Create a New Procedure, SetBitmap:

Create a new process, setBitmap:

[in mosaic.inc] iMageType_Standard EQU 0IMAGETYPE_NUMBERS EQU 1IMAGETYPE_BITMAP EQU 2 [IN .DATA?] CURIMAGETYPE DD?; CURRENT Image TYPE

[in .code] setBitmap proto stdcall: dword,: dword; ==================================== ============================================; set bitmap; == ============================================================================================================================================================================================================= ============================ setBitmap Proc HWnd: DWORD, IMAGETYPE: DWORD MOV EAX, ImageType .IF EAX == ImageType_NumBers; - Delete Old Image --- Invoke deleteObject, Himage; --- Get DC --- Invoke Getdc, HWND PUSH EAX; --- Create New Bitmap for the Numbers Bitmap --- Invoke CreateCompablebitMap, Eax, 200, 200 MOV HIMAGE , EAX POP EAX; --- Release DC --- Invoke ReleaseDC, HWnd, Eax; --- Select New Bitmap in DC --- Invoke SelectObject, Imagedc, Himage; --- Draw Numbers on The Bitmap --- Invoke DrawNumBers; --- Create The 3D Effect On The Bitmap --- Invoke Createtiles .ndif; --- set the new image type --- Mov e AX, Imagtype Mov CurimageType, EaxRetSetBitmap Endp

The SetBitmap procedure selects the type of image to use for the tiles The procedure takes 2 parameters:. HWnd, the handle of the main window, and ImageType, which can be one of these constants:. IMAGETYPE_STANDARD, IMAGETYPE_NUMBERS, IMAGETYPE_BITMAP These constants are defined in the include file. Right now, the procedure only reacts to IMAGETYPE_NUMBERS, we will implement the other two later. When the numbers image type is chosen, the old image (hImage) is deleted, and a new one is created with CreateCompatibleBitmap. Then two functions are called, DrawNumbers and CreateTiles, which are defined in the code below. DrawNumbers just draws an array of numbers on the new bitmap. CreateTiles draws the 3D effect on the bitmap. The CreateTiles procedure will be used for the other two image types The TOO.SETBITMAP process selects an image type for the tile. Process Belts 2 parameters, HWND main window handle and picture type. The picture type can be one of these constants: imagetype_standard, imagetype_numbers, iMagTyPE_bitmap. These constants are defined in the included file. Currently, the process reacts only to ImageTyPe_Numbers, and we will implement two other. When the number picture type is selected, the old image is deleted, and the new creation is created by CreateCompableBitmap. The two functions are then called, DrawNumBers and CreateTiles, which are defined in the code below. Draw NumBers just draws numbers on a new picture. CreateTiles draws 3D effect on the picture. The CreateTile process will also be used in other two image types.

Getcoordinates Proto stdcall: DWordDrawNumBers Proto stdcall.datanumberformat DB "% lu", 0Rect200 Rect <0,0,200,200> .data? Buffer DB 200 DUP (?). Code; =============== ============================================================================================================================================================================================================= ===============; Draw NumBers; =============================== ========================================================== DrawNumBers proc uses ebx ediLOCAL TempRect: RECT; --- Set the textcolor of imageDC to textColor --- invoke SetTextColor, imageDC, textColor; --- Fill the imageDC with the tile color brush --- invoke FillRect, imageDC, ADDR Rect200, Htilecolor; --- set the background mode to transparent (for the text) --- invoke setbkmode, imagedc, transparent; --- loop through all the number --- xor ebx, ebx .while ebx <16 MOV EAX, EBX Inc Eax Invoke Getcoordinates, Eax Mov DX, AX; DX = ROW SHR Eax, 16; AX = Column and EDX, 0FFFFH; Make Sure That EDX =

DX Imul EDX, EDX, 50;} Multipy Edx AS Well AS EAX WITH 50 Imul Eax, 50;} Mov TempRect.Top, EDX ADD EAX, 50 Add Edx, 50 MOV TempRect.Right, EAX MOV TempRect.bottom, edx mov eax, ebx inc eax invoke wsprintf, ADDR Buffer, ADDR NumberFormat, eax invoke DrawText, ImageDC, ADDR Buffer, -1, ADDR TempRect, / DT_CENTER or DT_SINGLELINE or DT_VCENTER inc ebx .ENDWretDrawNumbers endp; === ============================================================================================================================================================================================================= ===========================; getCoordinates; ================================================== ============================================================================================================================================================================================================= ========== getCoordinates Proc DWTILE: DWORD MOV EAX, DWTILE DEC EAX CDQ MOV ECX, 4 Div ECX; EAX = quotient = row; edx = remain = column shl Edx, 16 Add Eax, EdxretgetCoordinates ENDP

TWO New Procedures here, getcoordinates is a little processure That Will Be Used Several Times in The Program. Its Uses A 0-Based INDEX of The Tiles (Tile 0, Tile 1, Tile 2) etc. And returns the row of the tile 0,1,2,3) in The Low Word of Eax, The Column of The Tile (0, 1, 2, 3) in The High Word of Eax. The Calculation IS Quite Simple. Divide The Tile Index by 4, The Tile Index by 4, THE Remainder Will Be The Column, The SHL Instruction Shifts The Colomn In The High Word (Shift 16 Bits Left), Andadd Adds The Row. There are two processes, getCoordinates is in the program. A small process used multiple times. It uses 0 starting tunnel index (Figure 0, Figure 1, Figure 2), etc., and returns the row of the tile (0, 1, 2, 3) in the low words of Eax, high in Eax The words are returned to the longitudinal lines (0, 1, 2, 3) where the image is located. The calculation is very simple, remove the index of the tile, the remainder is the number of lines where the disc is the number of pieces. The SHL instruction moves the number of rows in the high character (left shift 16 bits), while add plus exclusive number.

The DrawnumBers Procedure Works Like this:

The working principle of the DrawNumBers process is as follows:

Set textcolor to the value of the TextColor variableFill the complete bitmap with the tilecolor brush (rect200 is a RECT structure that defines the area of ​​200x200 pixels starting at (0,0)) Set the background mode to TRANSPARENT to prevent an ugly background around the TEXT.

Set the value of the text color to the TextColor variable. Filling the full picture with the brush color of the tablet color (Rect 200 is a structure defining the 200 x 200 pixel area starting from (0, 0)) Set the background mode to transparent to prevent empty color of the grown background.

The Tile Loop:

TILE cycle

Loop from 0 to 15 {- GetCoordinates (currentloopvalue) - Extract row and column from return value multiply the row and the column with 50 (this gives the image coordinates of the tile) - Fill a RECT structure (TempRect) with the coordinates of the tile -. Use wsprintf to convert the tile number into text (NumberFormat is the format the number should be outputted in, buffer is a temporary buffer) -. Use DrawText to draw the number at the right coordinates} from 0 to 15 starts loop {

- Get the coordinates (current loop value) - to solve the values ​​of the rows and columns from the return value. Multiplining the number of rows and columns by 50 (this gives image coordinates of the tile) - Fill in the RECT structure (temporary structure) with the graphic coordinates - translate the number of pieces to text using WSPrint. (NumberFormat is a given world, Buffer is a temporary cache) - draws the figures properly using DrawText.

Createtiles Draws The Button-Style 3D Effect On The Tiles by Drawing Black & White Lines At The Right Places:

CreateTiles draws 3D effects on the tiles by a line that will be black and white in the appropriate place.

Createtiles proto stdcall; ============================================== ==================================; create tiles; ============= ============================================================================================================================================================================================================= ================== CreateTiles Proc Uses EBX ESI EDI Invoke GetStockObject, Black_pen Invoke SelectObject, Imagedc, Eax; Dark Lines, Vertical. X = 50k - 1 (k = 1, 2, 3, 4); EBX = K; ESI = x xor EBX, EBX INC EBX; EBX IS 1 Now .While EBX <5; (EBX = 1, 2, 3, 4) MOV EAX, 50 MUL EBX MOV ESI , Esi, ESI, 0, NULL INVOKE LINETO, IMAGETC, ESI, 199 Inc EBX .Endw; Dark Lines, Horizontal. Y = 50k - 1 (k = 1, 2, 3, 4); EBX = K; ESI = y xor EBX, EBX INC EBX; EBX IS 1 Now .While EBX <5; (EBX =

1,2,3,4) mov eax, 50 mul ebx mov esi, eax dec esi invoke MoveToEx, ImageDC, 0, esi, NULL invoke LineTo, ImageDC, 199, esi inc ebx .ENDW invoke GetStockObject, WHITE_PEN invoke SelectObject, ImageDC , EAX; Light Lines, Vertical. X = 50K (k = 0, 1, 2, 3); EBX = K; ESI = XOR EBX, EBX .While EBX <4; (EBX = 0, 1, 2, 3 ) MOV EAX, 50 MUL EBX MOV ESI, EAX INVOKE MOVETOEX, ImageDC, ESI, 0, NULL INVOKE LINETO, ImageDC, ESI, 199 Inc EBX .Endw; Light Lines, Horizontal. Y = 50K (k = 0, 1, 2 , 3); EBX = K; ESI = y xor EBX, EBX; EBX IS 1 Now .While EBX <4; (EBX = 0, 1, 2, 3) MOV EAX, 50 MUL EBX MOV ESI, EAX INVOKE MOVETOEX, Imagedc, 0, ESI, NULL INVOKE LINETO, ImageDC, 199, ESI INC EBX .Endw Retcreatetiles EndpThis Procedure Is Quite Easy To Understand. It Draws 4 Sets of Lines. Each Line IS D rawn by first getting a brush with GetStockObject (retrieves a standard brush color from windows). This brush is selected in the imagedc. Then the current point is moved to the startpoint of the line with MoveToEx, and the line is drawn with LineTo.

This process is easy to understand. It draws 4 lines. Each line is first obtained by getStockObject (getting standard brush color from the window). This brush is selected in ImageDC and then moves from MoveToex to the starting point of the line, while the line is drawn by LineTo.

7.4 - Drawing Painting

The procudure below will be used in the future too, but the code of it is temporary right now, it just draws the image DC on the static control to show if your code worked. Furthermore, some additional procedures are introduced to initialize everything correctly.

The following process will also be used later. But its code is now correct. It's just drawing imagedc on a static control to display whether your code is working. In addition, the additional process is used to initialize each piece:

DrawProc Proto stdcall: DWORD,: DWORDINITGAME PROTO stdcall: dword [in .code]; ================================ ========================================================; Draw Numbers; ============================================================================================================================================================================================== ========================================= DrawProc Proc Uses EBX EDI ESI HWND: DWORD, HDC: DWORD INVOKE BITBLT, HDC, 9, 9, 220, 220, imagedc, 0, 0, srcopyRetdrawProc Endp; ================================= ===============================================; initgame =============================================================================================================================================================================================================

======================================== Initgame Proc HWnd: DWORD INVOKE setBitmap, hwnd, iMageType_numbersretinitgame endp [in the wm_create handler of WndProc, below 'invoke InitBitmaps, hWnd'] invoke InitGame, hWnd [in the messagehandler in WndProc, between the other ELSEIFs] .ELSEIF eax == WM_DRAWITEM mov eax, wParam .IF eax == CID_STATIC push ebx mov ebx, lParam assume ebx: ptr DRAWITEMSTRUCT invoke DrawProc, hWnd, [ebx] .hdc assume ebx: nothing pop ebx xor eax, eax inc eax .ELSE xor eax, eax .ENDIFThe DrawProc and InitGame are fairly easy to understand BitBlt copies a part of a bitmap from one DC. To another. Here The Complete Bitmap in imagedc is copied to the dc of the static control window.

DrawProc and Initgame are quite easy to understand. Bitblt copies some pictures from a DC to another. Here, the complete picture in ImageDC is copied to the DC of the static control window.

The WM_DRAWITEM message requires some more explanation:.. WM_DRAWITEM is sent to the main window when one of the owner-drawn controls needs to be drawn An owner-drawn control is a control that is drawn by the program instead of windows When this message is SENT, WPARAM Contains the ID of the control trian == CID_STATIC FINDS OUT IT IT NEEDS TO BE DRAWN. IF NOT (.ELSE), 0 Is Returned from WndProc (xor Eax, Eax). 0 Tells Windows That The Message IS Not Handled by The Program. LParam Is A Pointer to A DrawItemstructure.

WM_DRAWITEM messages require more explanations: When an Owner-Drawn control needs to be drawn, WM_DRAWITEM is sent to the main window. A Owner-Drawn control is a control drawn by a program instead of Windows. When the message is sent, the WPARAM contains the ID of the control that needs to be drawn. Here, .IF EAX == CID_STATIC identifies whether it is a static control (Figure window) that needs to be drawn. If not (.ELSE), WndProc returns 0 (XOR EAX, EAX). 0 Tell Windows This message is not processed. IParam is a pointer pointing to DrawItemstruct. MOV EBX, LPARAM Assume EBX: PTR DrawItemstruct Invoke DrawProc, HWnd, [EBX] .hdc Assume EBX: Nothing

. First, lParam is put in ebx Now ebx is a pointer to the DRAWITEMSTRUCT structure The assume statement gives masm more information about the register assume ebx:.. Ptr DRAWITEMSTRUCT tells masm that ebx is a pointer to a DRAWITEMSTRUCT structure Now you can use. the structure members directly on ebx. hdc is one of these members, it contains the handle to the device context of the window. The control will show whatever there is on that DC. This DC is passed to DrawProc. Do not forget to tell masm to assume nothing for ebx (assume ebx: nothing), otherwise masm thinks ebx is a pointer to DRAWITEMSTRUCT throughout the whole program Very important is that you should save ebx in your procedures (that's why the push ebx / pop ebx instructions are included. ). Windows assumes the values ​​of the ebx, esi and edi registers do not change when your window procedure is called by windows (this applies to all callback functions in windows, always save ebx, esi & edi).

First, iParam is placed in EBX. Now EBX is a pointer to the DrawItemstruct structure. The Assume statement tells Masm for more information on registers. Assume EBX: PTR DrawItemstruct tells Masm EBX is a pointer to the DrawItemstruct structure. Now you can use the structural members in EBX. The control will tell you what is in that DC. This DC is passed to DrawProc. Don't forget to tell MASM Assume Nothing fo EBX (Assume EBX: Nothing), otherwise MASM will think EBX throughout the program is a pointer to DrawItemStruct. It is very important that you should save EBX during your process (this is why the PUSH EBX / POP EBX instruction). Windows assumes that when your window is called by Windows, the value of EBX, ESI and EDI registers will not change (this is like this for all callback functions in Windows, always saving EBX, ESI and EDI) 7.5 - DONE

The Current Project Files Are Here: Mosaic4.zip

Current project file here: mosaic4.zip

IF you assemble the program and run it, you shouth see this:

If you assemble the program and run it, you will see:

As you can see, The Tiles Are Drawn Correctly.

As you can see, the tile is painted correctly.

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

New Post(0)