flat assembler
Message board for the users of flat assembler.
![]() Goto page 1, 2, 3 Next |
Author |
|
MHajduk 28 Mar 2013, 23:46
I'd like to present here a simple example of how to use Windows 'GradientFill' function to fill the application window background with gradient. The program is as simple as it is possible and may be treated as a ready-to-use windows application template, anyway to avoid possible flickering while resize there is added some kind of necessary buffering.
![]() http://www.youtube.com/watch?v=2P-y8T34DVw I've decided to post this example here because the gradient fill examples posted on this forum represent mainly low-level approach with custom drawing procedures (uart777 graphic examples, 0.1 (written with C) and ATV examples). There was literally one example by Vasilev Vjacheslav using the 'GradientFill' function but the clue is hidden among too many things to be useful as a simple example for everybody (especially beginners). Here you have a source code of my program: Code: ; ; A simple program written with FASM that shows how to fill an application window ; background with color gradient using the 'GradientFill' function. ; ; Program uses buffering to avoid possible flickering during the application window ; resize. ; ; (C) Mikolaj Hajduk, 28.03 - 06.04.2013. ; format PE GUI 4.0 entry start ; Include a header file containing necessary macros. ; include 'win32wx.inc' ; Use UTF-8 encoding if you want to have your strings displayed always the same ; way despite of local settings of the user system and if your application has to ; be multilingual. ; include 'ENCODING\utf8.inc' ; A definition of the constant describing the program version (encoded date of ; the last changes). ; PROG_VERSION equ '2013.04.06.0' ; Symbolic constants used as equivalents of the button dimensions. ; BTN_WIDTH = 150 BTN_HEIGHT = 40 ; A definition of the structure specifying indexes of two vertices in the array ; of TRIVERTEX structures used by GradientFill function. Chosen vertices determine ; the upper-left and lower-right boundaries of the rectangle filled with gradient. ; struct GRADIENT_RECT UpperLeft dd ? LowerRight dd ? ends ; Constants specifying possible gradient fill modes. ; GRADIENT_FILL_RECT_H = 0x0 ; Horizontal gradient. GRADIENT_FILL_RECT_V = 0x1 ; Vertical gradient. ; A constant used to define private messages within the scope of the application. ; WM_APP = 0x8000 ; A code of the application specific message used to change gradient colors ; from default to custom ones. ; WM_SETGRADIENT = WM_APP ; The data section. ; section '.data' data readable writeable HwndMain dd 0 ; The handle of the main application window. HwndBis dd 0 ; The handle of the additional resizable application ; window. hFont dd 0 ; The handle of the font used to display strings ; inside window controls. ; An arbitrarily chosen class name of the created window. ; ClassName du 'GradientFillExample', 0 ; A string displayed in the application window title bar. ; WindowCaption du 'Gradient fill example v.', PROG_VERSION, 0 ; An instance of the WNDCLASSEX structure containing information about ; the created window class. ; wc WNDCLASSEX sizeof.WNDCLASSEX, 0, WindowProc, 0,\ \ 8,\ ; The number of extra bytes allocated \ ; following every class instance. \ ; Here we need two double words for \ ; a button handle (first dword) and \ ; a 32-bit pointer to the array of the \ ; TRIVERTEX structure instances defining \ ; colors of actual gradient. \ NULL, NULL, NULL, NULL, NULL,\ \ ClassName, NULL ; An instance of the MSG structure used to store information about ; messages from the thread message queue. ; msg MSG ; The name of the used font. 'Tahoma' is the proper choice for applications ; that display strings denoted in the scripts other than Latin (supports ; most Unicode chars). ; FontName du 'Tahoma', 0 ; A constant used in INITCOMMONCONTROLSEX as a flag indicating that ; all standard common control classes have to be loaded from the DLL. ; ICC_STANDARD_CLASSES = 0x4000 ; An instance of the structure carrying information used to load common ; control classes. ; icex INITCOMMONCONTROLSEX sizeof.INITCOMMONCONTROLSEX, ICC_STANDARD_CLASSES align 4 ; A custom array of instances of the TRIVERTEX structure containing information ; about colors associated with upper-left and lower-right corners of the window ; application client area. ; ; Upper-left ; x y R G B Alpha ; --------------------------------------------- CustomVertices TRIVERTEX 0, 0, 07D00h, 0AA00h, 0C300h, 0 TRIVERTEX 0, 0, 07D00h, 0FF00h, 04400h, 0 ; Default array of instances of the TRIVERTEX structure containing information ; about colors associated with upper-left and lower-right corners of the window ; application client area. ; ; Upper-left ; x y R G B Alpha ; --------------------------------------------- DefaultVertices TRIVERTEX 0, 0, 07D00h, 0AA00h, 0C300h, 0 TRIVERTEX 0, 0, 0FF00h, 02A00h, 04400h, 0 ; An instance of the 'GRADIENT_RECT' structure determining indexes ; of the array of 'TRIVERTEX' structures used by 'GradientFill' function ; to fill an area with gradient. ; Mesh GRADIENT_RECT 0, 1 ; The code section. ; section '.code' code readable executable start: ; Ensure that the common control DLL (Comctl32.dll) is loaded ; and register chosen common control classes. ; invoke InitCommonControlsEx, icex stdcall ErrorRoutine, exit ; Retrieve a handle of the application file. ; invoke GetModuleHandle, 0 stdcall ErrorRoutine, exit mov [wc.hInstance], eax ; As an application icon use one of the predefined icons. ; invoke LoadIcon, 0, IDI_APPLICATION stdcall ErrorRoutine, exit mov [wc.hIcon], eax ; A cursor associated with the application is a standard, arrow ; shaped one. ; invoke LoadCursor, 0, IDC_ARROW stdcall ErrorRoutine, exit mov [wc.hCursor], eax ; Registering the application window class in the system. ; invoke RegisterClassEx, wc stdcall ErrorRoutine16, exit ; Create the main application window. ; invoke CreateWindowEx, 0, ClassName, WindowCaption, WS_VISIBLE + WS_OVERLAPPEDWINDOW +\ \ WS_CLIPCHILDREN,\ ; Exclude child windows from redrawing when \ ; the drawing occurs within the parent, i.e. \ ; main application window area. \ 128, 128, 350, 192, NULL, NULL, [wc.hInstance], NULL stdcall ErrorRoutine, exit mov [HwndMain], eax ; Create an additional resizable application window. ; invoke CreateWindowEx, 0, ClassName, WindowCaption, WS_VISIBLE + WS_SIZEBOX +\ \ WS_CLIPCHILDREN,\ ; Exclude child windows from redrawing when \ ; the drawing occurs within the parent, i.e. \ ; main application window area. \ 300, 300, 350, 192, NULL, NULL, [wc.hInstance], NULL stdcall ErrorRoutine, exit mov [HwndBis], eax ; Create a font that will be used to display all strings inside ; the application window controls. ; invoke CreateFont, 16, 0, 0, 0, 0, FALSE, FALSE, FALSE,\ DEFAULT_CHARSET, OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS,\ DEFAULT_QUALITY, FIXED_PITCH + FF_DONTCARE, FontName stdcall ErrorRoutine, cleanup mov [hFont], eax ; Set the created font to the main and additional application windows. ; invoke SendMessage, [HwndMain], WM_SETFONT, eax, TRUE invoke SendMessage, [HwndBis], WM_SETFONT, [hFont], TRUE ; Change the default gradient to the custom one in the additional ; application window. ; invoke SendMessage, [HwndMain], WM_SETGRADIENT, CustomVertices, 0 ; A loop where all messages referring to the application window have been ; processed. ; msg_loop: ; Retrieve a message from the application message queue. ; invoke GetMessage, msg, NULL, 0, 0 ; Exit when the 'WM_QUIT' message has been retrieved. ; test eax, eax jz cleanup ; Display a proper error message when something has gone wrong ; (eax = -1). ; inc eax stdcall ErrorRoutine, cleanup ; Translate virtual-key strokes into character messages. ; invoke TranslateMessage, msg ; Dispatch the retrieved message to the window procedure. ; invoke DispatchMessage, msg jmp msg_loop ; Release all handles and allocated resources before exit. ; cleanup: ; Delete the font used to display strings in the application ; window controls. ; cmp [hFont], 0 je exit invoke DeleteObject, [hFont] ; Quit the application. ; exit: invoke ExitProcess, [msg.wParam] ; The error handling routine that organizes the program flow when any of ; API functions returns zero value. ; ErrorRoutine16: ; Zeroize bits of the eax register from the 16th to the 31st one. ; Done to assure that the eax register won't contain any "garbage" ; after calling API functions returning 16-bit result. ; and eax, 0xFFFF ErrorRoutine: ; Check value stored in the eax register. If it's nonzero then ; return to the address following the place the error procedure ; has been called. ; test eax, eax jz @f retn 4 ; Check value of the last error that has occurred. ; @@: invoke GetLastError test eax, eax jnz @f ; If there was no error, i.e. the 'GetLastError' function returned ; 'ERROR_SUCCESS', we return to the place when the 'ErrorRoutine' ; procedure was called and remove the 'ReturnTo' address stored on ; the stack before the procedure call. ; retn 4 @@: ; If there was an error, we display a message box with a human readable ; description of the error, remove the address of the procedure caller ; and return to the 'ReturnTo' address. ; stdcall ShowLastError, NULL, eax add esp, 4 retn ; The main application window procedure. Here we specify how to react ; on the events occurring inside the window. ; proc WindowProc, hwnd, wmsg, wparam, lparam locals .Button dd 0 ; The handle of the button. .hVertices dd 0 ; A 32-bit pointer to the array of the TRIVERTEX ; structure instances used to define gradient ; colors. .hDC dd 0 ; The handle of the application window DC. .hMemDC dd 0 ; The handle of the additional DC (buffer). .hMemBM dd 0 ; The handle of the bitmap used for the ; window redraw operations. .Rect RECT ; An instance of the RECT structure used ; to store the coordinates of the upper-left ; and the lower-right corners of the window ; client area. endl push ebx ; Depending on the message type perform proper actions. ; cmp [wmsg], WM_CREATE je .wmcreate ; Retrieve the handle of the button from the window extra memory and store ; it in the local variable '.Button'. ; invoke GetWindowLong, [hwnd], 0 stdcall ErrorRoutine, .wmdestroy mov [.Button], eax ; Retrieve the pointer to the array of the TRIVERTEX structure instances ; and store it in the local variable '.hVertices'. ; invoke GetWindowLong, [hwnd], 4 stdcall ErrorRoutine, .wmdestroy mov [.hVertices], eax cmp [wmsg], WM_SIZE je .wmsize cmp [wmsg], WM_PAINT je .wmpaint cmp [wmsg], WM_SETFONT je .wmsetfont cmp [wmsg], WM_SETGRADIENT je .wmsetgradient cmp [wmsg], WM_DESTROY je .wmdestroy ; Ensure that all messages not processed by the application ; window procedure will be processed by default window procedure. ; .defwndproc: invoke DefWindowProc, [hwnd], [wmsg], [wparam], [lparam] jmp .finish ; Actions performed when the application window has been created. ; .wmcreate: ; Create an exemplary button. ; invoke CreateWindowEx, 0, 'BUTTON', 'Button',\ WS_VISIBLE + WS_CHILD,\ 0, 0, 0, 0, [hwnd], 0, [wc.hInstance], NULL stdcall ErrorRoutine, .wmdestroy mov [.Button], eax ; Store the handles created button handle and pointer to the array ; of the TRIVERTEX structure instances in the reserved window extra ; memory. It's necessary because these values must be available ; during the next call of the 'WindowProc' procedure. ; invoke SetLastError, 0 invoke SetWindowLong, [hwnd], 0, [.Button] stdcall ErrorRoutine, .wmdestroy invoke SetLastError, 0 invoke SetWindowLong, [hwnd], 4, DefaultVertices stdcall ErrorRoutine, .wmdestroy ; Window procedure should return 0 when processes the 'WM_CREATE' ; message. ; jmp .return0 ; Actions performed when the application window has changed its sizes. ; .wmsize: ; Retrieve the coordinates of the application window client area. ; The result of the procedure 'GetClientRect' is stored in the ; instance of the RECT structure. The coordinates of the upper-left ; corner of the client area rectangle are always equal to (0, 0), ; so the most important are coordinates of the lower-right corner ; as a containing the whole information. ; lea eax, [.Rect] invoke GetClientRect, [hwnd], eax stdcall ErrorRoutine, .finish ; Put the width of the client area to the eax register, subtract ; the width of the button and divide the result by 2 to obtain ; the new x coordinate of the upper-left corner of the button. ; mov eax, [.Rect.right] sub eax, BTN_WIDTH shr eax, 1 ; Put the height of the client area to the ebx register, subtract ; the height of the button and divide the result by 2 to obtain ; the new y coordinate of the upper-left corner of the button. ; mov ebx, [.Rect.bottom] sub ebx, BTN_HEIGHT shr ebx, 1 ; Move the button to the calculated position. ; invoke MoveWindow, [.Button], eax, ebx, BTN_WIDTH, BTN_HEIGHT, TRUE stdcall ErrorRoutine, .finish ; Window procedure should return 0 when processes the 'WM_SIZE' ; message. ; jmp .return0 ; Actions performed when a portion of the application window needs to be redrawn. ; .wmpaint: ; Retrieve a handle to a device context of the client area of the ; application window. ; invoke GetDC, [hwnd] stdcall ErrorRoutine, .finish mov [.hDC], eax ; Retrieve the coordinates of the application window client area. ; lea eax, [.Rect] invoke GetClientRect, [hwnd], eax stdcall ErrorRoutine, .wmpaintcleanup ; ; Sequence of actions performed in order to buffer all redraw operations. ; ; Create an additional, memory device context compatible with DC of the ; client area of our application window. ; invoke CreateCompatibleDC, [.hDC] stdcall ErrorRoutine, .wmpaintcleanup mov [.hMemDC], eax ; Create a bitmap used to hold the result of the window redraw, assigned ; to the DC of the application window. ; invoke CreateCompatibleBitmap, [.hDC], [.Rect.right], [.Rect.bottom] stdcall ErrorRoutine, .wmpaintcleanup mov [.hMemBM], eax ; Change the default bitmap used in additional DC by the one created above. ; invoke SelectObject, [.hMemDC], [.hMemBM] stdcall ErrorRoutine, .wmpaintcleanup ; Actualization of the coordinates of the structure pointed by '.hVertices' ; with actual coordinates of the lower-right corner of the client area (fields ; corresponding to the upper-left corner don't need to be actualized as they ; are always equal to 0). ; mov ebx, [.hVertices] add ebx, sizeof.TRIVERTEX ; We refer to the second instance of the ; TRIVERTEX structure in the array pointed ; by '.hVertices'. mov eax, [.Rect.right] mov [ebx], eax ; Lower-right x coordinate. mov eax, [.Rect.bottom] mov [ebx + 4], eax ; Lower-right y coordinate. ; Fill the application window background with gradient. ; invoke GradientFill, [.hMemDC],\ ; The handle of the additional device \ ; context where we perform all drawing \ ; operations. \ [.hVertices],\ ; The pointer to the array of 'TRIVERTEX' \ ; structures that define vertices of the \ ; area filled with gradient. \ 2,\ ; Number of vertices in the array mentioned \ ; above. \ Mesh,\ ; A pointer to an array of the 'GRADIENT_RECTANGLE' \ ; structures (specify the way we interpret the \ ; vertices contained in the 'TRIVERTEX' structures \ ; array). \ 1,\ ; The number of rectangles in the array \ ; mentioned above. \ GRADIENT_FILL_RECT_V ; The gradient fill mode (here: vertical). stdcall ErrorRoutine, .wmpaintcleanup ; Copy data of the newly drawn background from the source device context ; (buffer) to the destination device context (DC associated with the client ; area of our application window). ; invoke BitBlt, [.hDC],\ ; The handle of the destination DC. \ 0, 0,\ ; The coordinates of the upper-left corner \ ; of the destination DC. \ [.Rect.right],\ ; The width and height of the destination [.Rect.bottom],\ ; device context. \ [.hMemDC],\ ; The handle of the source DC (memory buffer). \ 0, 0,\ ; The coordinates of the upper-left corner \ ; of the source DC. \ SRCCOPY ; A raster-operation code (ordinary copy). stdcall ErrorRoutine, .wmpaintcleanup ; Release all handles and resources used during painting. ; .wmpaintcleanup: ; Delete the additional unneeded device context. ; cmp [.hMemDC], 0 je .hMemBMdelete invoke DeleteDC, [.hMemDC] ; Release resources occupied by the bitmap associated with the ; application DC. ; .hMemBMdelete: cmp [.hMemBM], 0 je .hDCrelease invoke DeleteObject, [.hMemBM] ; Release the application window device context retrieved by the ; 'GetDC' function call. ; .hDCrelease: cmp [.hDC], 0 je .wmdestroy invoke ReleaseDC, [hwnd], [.hDC] xor eax, eax jmp .defwndproc ; Actions performed when the window procedure receives the 'WM_SETFONT' ; message. Here we forward the 'WM_SETFONT' message to all controls ; located inside the window. ; .wmsetfont: ; Set the new font to the button instead the current one. ; invoke SendMessage, [.Button], WM_SETFONT, [wparam], TRUE jmp .finish ; Actions performed when the window procedure receives the custom ; 'WM_SETGRADIENT' message. We change the pointer to the array of ; TRIVERTEX structure instances to the new one passed through 'wparam' ; parameter of the window procedure. ; .wmsetgradient: invoke SetLastError, 0 invoke SetWindowLong, [hwnd], 4, [wparam] stdcall ErrorRoutine, .finish jmp .finish ; Operations performed when the application window is to be destroyed. ; This is a regular cleanup after receiving the 'WM_DESTROY' message: here ; we delete objects and resources allocated during the application window ; creation. We don't need to destroy all controls (child windows) manually ; because it will be done automatically. ; .wmdestroy: ; Post the 'WM_QUIT' message to the application message queue. ; invoke PostQuitMessage, 0 .return0: xor eax, eax .finish: pop ebx ret endp ; A simple procedure that displays a message box containing a human readable ; description of the last error. ; proc ShowLastError, hwnd, LastErr locals Buffer dd ? endl lea eax, [Buffer] invoke FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, [LastErr],\ LANG_NEUTRAL, eax, 0, 0 invoke MessageBox, [hwnd], [Buffer], NULL, MB_ICONERROR + MB_OK invoke LocalFree, [Buffer] ret endp ; The import section. ; section ".idata" import data readable writeable library kernel32, "KERNEL32.DLL",\ user32, "USER32.DLL",\ gdi32, "GDI32.DLL",\ comctl32, "COMCTL32.DLL",\ msimg32, "MSIMG32.DLL" import kernel32,\ ExitProcess, "ExitProcess",\ FormatMessage, "FormatMessageW",\ GetLastError, "GetLastError",\ GetModuleHandle, "GetModuleHandleW",\ LocalFree, "LocalFree",\ SetLastError, "SetLastError" import user32,\ CreateWindowEx, "CreateWindowExW",\ DefWindowProc, "DefWindowProcW",\ DispatchMessage, "DispatchMessageW",\ GetClientRect, "GetClientRect",\ GetDC, "GetDC",\ GetMessage, "GetMessageW",\ GetWindowLong, "GetWindowLongW",\ LoadCursor, "LoadCursorW",\ LoadIcon, "LoadIconW",\ MessageBox, "MessageBoxW",\ MoveWindow, "MoveWindow",\ PostQuitMessage, "PostQuitMessage",\ RegisterClassEx, "RegisterClassExW",\ ReleaseDC, "ReleaseDC",\ SendMessage, "SendMessageW",\ SetWindowLong, "SetWindowLongW",\ TranslateMessage, "TranslateMessage" import gdi32,\ BitBlt, "BitBlt",\ CreateCompatibleBitmap, "CreateCompatibleBitmap",\ CreateCompatibleDC, "CreateCompatibleDC",\ CreateFont, "CreateFontW",\ DeleteDC, "DeleteDC",\ DeleteObject, "DeleteObject",\ SelectObject, "SelectObject" import comctl32,\ InitCommonControlsEx, "InitCommonControlsEx" import msimg32,\ GradientFill, "GradientFill" ; The section of the program resources. Here we specify information about the ; application (description, author, version) and the application manifest ; informing Windows which version of the common controls program should use ; giving it a modern visual style instead of the classical Win9x "boxy" style. ; section '.rsrc' resource data readable RT_MANIFEST = 24 ID_MANIFEST = 1 directory RT_VERSION, versions,\ RT_MANIFEST, manifest resource versions,\ 1, LANG_NEUTRAL, version resource manifest,\ ID_MANIFEST, LANG_NEUTRAL, man versioninfo version, VOS__WINDOWS32, VFT_APP, VFT2_UNKNOWN, LANG_ENGLISH + SUBLANG_DEFAULT, 0,\ 'FileDescription', 'Gradient fill example',\ 'LegalCopyright', '(C) Mikolaj Hajduk, 2013',\ 'FileVersion', PROG_VERSION,\ 'ProductVersion', PROG_VERSION,\ 'OriginalFilename', 'GradientFill.exe' ; Content of the manifest included as an application resource. ; resdata man db '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">' db '<assemblyIdentity ' db 'version="', PROG_VERSION, '" ' db 'processorArchitecture="X86" ' db 'name="MikolajHajduk.GradientFill" ' db 'type="win32"' db '/>' db '<description>Gradient fill example.</description>' db '<dependency>' db '<dependentAssembly>' db '<assemblyIdentity ' db 'type="win32" ' db 'name="Microsoft.Windows.Common-Controls" ' db 'version="6.0.0.0" ' db 'processorArchitecture="X86" ' db 'publicKeyToken="6595b64144ccf1df" ' db 'language="*"' db '/>' db '</dependentAssembly>' db '</dependency>' db '</assembly>' endres ![]() [EDIT]New version of the program. Main changes:
Last edited by MHajduk on 07 Apr 2013, 21:37; edited 9 times in total |
|||
![]() |
|
MHajduk 29 Mar 2013, 00:10
It would complicate a bit the procedure of the error handling, because we should handle each error differently. I may rethink it, of course, but not now - I am too tired.
![]() |
|||
![]() |
|
revolution 29 Mar 2013, 00:19
Perhaps something like this:
|
|||
![]() |
|
MHajduk 29 Mar 2013, 00:23
revolution wrote: Perhaps something like this: ![]() |
|||
![]() |
|
bitRAKE 29 Mar 2013, 03:43
I've always preferred handling WM_ERASEBKGND when a background color is not specified in the class. Mainly because it has a valid DC. I haven't been able to find any concrete information on which method is better.
(I must have some gradient fill code in the archives. IIRC, it filled the buffer directly, but lacks the flexiblity of your example.) ![]() |
|||
![]() |
|
AsmGuru62 29 Mar 2013, 14:09
bitRAKE:
But then you paint your window twice: 1. WM_ERASEBKGND - draw the background 2. WM_PAINT - draw the data on painted background. Two messages. Another way is to return 1 from WM_ERASEBKGND and paint both background and data in response to WM_PAINT message. |
|||
![]() |
|
bitRAKE 29 Mar 2013, 21:30
AsmGuru62, that is how I understand it as well. Sometimes I don't have a WM_PAINT, or everything can be done from WM_ERASEBKGND - which has already been setup by Windows. (Because Windows is responsible for painting some of the window.)
|
|||
![]() |
|
MHajduk 29 Mar 2013, 23:48
bitRAKE wrote: (I must have some gradient fill code in the archives. IIRC, it filled the buffer directly, but lacks the flexiblity of your example.) ![]() |
|||
![]() |
|
bitRAKE 30 Mar 2013, 02:00
Code: GradFill PROC USES ebx esi edi, _HWnd_:DWORD LOCAL Color1:DWORD, Color2:DWORD LOCAL dx1:DWORD, dx2:DWORD, dx3:DWORD LOCAL TmpRect:RECT LOCAL DC:DWORD, FullLength:DWORD invoke GetClientRect, _HWnd_, ADDR TmpRect sub TmpRect.right, 2 sub TmpRect.bottom, 2 ;calc width of rectangle mov ebx,TmpRect.right sub ebx,TmpRect.left mov FullLength,ebx jz @F ;prepare tmprect mov eax,TmpRect.left inc eax mov TmpRect.right,eax invoke GetWindowLongA,_HWnd_,PWL_GRADDC mov DC,eax invoke GetWindowLongA,_HWnd_,PWL_BARCOLOR1 mov Color1,eax invoke GetWindowLongA,_HWnd_,PWL_BARCOLOR2 mov Color2,eax mov ecx, Color2 mov edi, Color1 sal ecx, 7 sal edi, 7 mov eax, ecx mov ebx, edi and eax, 0FF000000h / 2 and ebx, 0FF000000h / 2 sub eax, ebx cdq idiv FullLength mov dx1, eax mov eax, ecx mov esi, edi and eax, 0FF0000h / 2 and esi, 0FF0000h / 2 sub eax, esi cdq idiv FullLength mov dx2, eax mov eax, ecx and eax, 0FF00h / 2 and edi, 0FF00h / 2 sub eax, edi cdq idiv FullLength mov dx3, eax mov eax, Color1 lp: ;fill tmprect invoke CreateSolidBrush,eax push eax invoke FillRect,DC,ADDR TmpRect,eax ; ADDR destroys EAX! call DeleteObject ;update tmprect inc TmpRect.left inc TmpRect.right add ebx,dx1 add esi,dx2 mov edx,ebx mov eax,esi and edx,0FF000000h / 2 and eax,0FF0000h / 2 add edi,dx3 or edx,eax mov eax,edi and eax,0FF00h / 2 or eax,edx shr eax, 7 dec FullLength jne lp @@: ret GradFill ENDP |
|||
![]() |
|
hanjin 30 Mar 2013, 05:15
Hi. MHajduk!!
![]() undefined symbol 'WindowProc.wmsize' I'm using fasmw 1.71.07 . |
|||
![]() |
|
uart777 30 Mar 2013, 06:24
MHajduk: Good style. Thanks for the example.
bitRAKE: Why so many divisions and OS-specifics? My draw.fade function draws directly to memory (like text operations) and uses fixed point arithmetic: Code: ; draw gradual fade from color a to b. ; o/rient: 'h'=horizontal, 'v'=vertical function draw.fade, o, box, c1, c2 locals x, y, w, h, i, n,\ r, g, b, r2, g2, b2,\ nr, ng, nb, first, last let eax=[box],\ [x]=[?box.x+eax], [y]=[?box.y+eax],\ [w]=[?box.w+eax], [h]=[?box.h+eax] ; orientation... .if [o]='h' let eax=[x], [first]=eax, ecx=[w] .else let eax=[y], [first]=eax, ecx=[h] .end let [n]=ecx, eax+ecx, [last]=eax ; extract r/g/b components let eax=&[r], ecx=&[g], edx=&[b] get.rgb [c1], eax, ecx, edx let eax=&[r2], ecx=&[g2], edx=&[b2] get.rgb [c2], eax, ecx, edx ; scale by 256 (2^ Or disassembly if you prefer: Code: draw.fade: push ebp mov ebp,esp sub esp,44h mov eax,[ebp+0Ch] push [eax] pop [ebp-44h] push [eax+4] pop [ebp-40h] push [eax+8] pop [ebp-3Ch] push [eax+0Ch] pop [ebp-38h] cmp [ebp+8],68h jne 0040314D mov eax,[ebp-44h] mov [ebp-8],eax mov ecx,[ebp-3Ch] jmp 00403156 mov eax,[ebp-40h] mov [ebp-8],eax mov ecx,[ebp-38h] mov [ebp-30h],ecx add eax,ecx mov [ebp-4],eax lea eax,[ebp-2Ch] lea ecx,[ebp-28h] lea edx,[ebp-24h] push edx push ecx push eax push [ebp+10h] call 00402A2A lea eax,[ebp-20h] lea ecx,[ebp-1Ch] lea edx,[ebp-18h] push edx push ecx push eax push [ebp+14h] call 00402A2A shl [ebp-2Ch],8 shl [ebp-28h],8 shl [ebp-24h],8 mov ecx,[ebp-30h] cmp ecx,0 je 004031C9 mov eax,[ebp-20h] shl eax,8 sub eax,[ebp-2Ch] cdq idiv eax,ecx mov [ebp-14h],eax mov eax,[ebp-1Ch] shl eax,8 sub eax,[ebp-28h] cdq idiv eax,ecx mov [ebp-10h],eax mov eax,[ebp-18h] shl eax,8 sub eax,[ebp-24h] cdq idiv eax,ecx mov [ebp-0Ch],eax jmp 004031ED mov eax,[ebp-20h] shl eax,8 sub eax,[ebp-2Ch] mov [ebp-14h],eax mov eax,[ebp-1Ch] shl eax,8 sub eax,[ebp-28h] mov [ebp-10h],eax mov eax,[ebp-18h] shl eax,8 sub eax,[ebp-24h] mov [ebp-0Ch],eax push [ebp-8] pop [ebp-34h] mov ecx,[ebp-34h] cmp ecx,[ebp-4] jge 00403256 mov eax,[ebp-2Ch] sar eax,8 mov ecx,[ebp-28h] sar ecx,8 mov edx,[ebp-24h] sar edx,8 push edx push ecx push eax call 00402A0E cmp dword [ebp+8],68h jne 0040322E push eax push [ebp-38h] push [ebp-40h] push [ebp-34h] push 76h call 00402FD5 jmp 0040323F push eax push [ebp-3Ch] push [ebp-34h] push [ebp-44h] push 68h call 00402FD5 mov eax,[ebp-14h] add [ebp-2Ch],eax mov ecx,[ebp-10h] add [ebp-28h],ecx mov edx,[ebp-0Ch] add [ebp-24h],edx inc [ebp-34h] jmp 004031F3 mov esp,ebp pop ebp ret 10h |
|||
![]() |
|
bitRAKE 30 Mar 2013, 08:10
uart777 wrote: bitRAKE: Why so many divisions and OS-specifics? My draw.fade function draws directly to memory (like text operations) and uses fixed point arithmetic: ![]() It was written for Windows, yes. ![]() Have you seen SpAsm/RosAsm? It had a condensed syntax like your code. Although, there doesn't appear to be a website - the wayback machine has a copy of his web site. Or I probably still have an archive of very early versions of SpAsm. There are very dense syntax language like J or K - think they call it data centric languages. |
|||
![]() |
|
uart777 30 Mar 2013, 09:10
bitRAKE: Ok, you're right
![]() My language is not based on RosASM in any way. Last edited by uart777 on 05 Apr 2013, 03:13; edited 1 time in total |
|||
![]() |
|
uart777 30 Mar 2013, 10:01
MHajduk: What the hell is this?!
![]() Code: invoke LoadIcon, 0, IDI_APPLICATION test eax, eax jz error mov [wc.hIcon], eax Code: try [wc.hIcon]=LoadIcon 0, IDI_APPLICATION ; BOOM! That's what's up, NIGGA!!! ![]() |
|||
![]() |
|
MHajduk 30 Mar 2013, 10:54
hanjin wrote: Hi. MHajduk!! The main reason of this is you're using not fully tested releases of fasm (those listed on the lower part of the 'Download' page http://flatassembler.net/download.php of this site). As the description says: Tomasz Grysztar wrote: The packages listed below are the latest development snapshot. Note that these versions may not yet be thorougfully tested. ![]() I recommend to use always the stable releases to avoid potential frustrating problems. ![]() |
|||
![]() |
|
MHajduk 30 Mar 2013, 10:59
uart777 wrote: MHajduk: What the hell is this?! ![]() ![]() |
|||
![]() |
|
hopcode 30 Mar 2013, 14:57
RosAsm ?
http://code.google.com/p/rosasm2052f/ i cannot find at the moment some other recent photo-material from Betov, and i dont know whether Betov is the author there on google. i read that code some year ago on that repository. it is worth saving a local copy now with wget. Cheers, ![]() _________________ ⠓⠕⠏⠉⠕⠙⠑ |
|||
![]() |
|
MHajduk 30 Mar 2013, 15:41
Accordingly to revolution's suggestions referring to the emergency cleanup after an error handling I've introduced some changes (additions) to the code. The changed parts you may see below (the entire actual code has been posted in the first post):
Code: (...) ; Actions performed when a portion of the application window needs to be redrawn. ; .wmpaint: ; Assure that handles of objects used in this part of the application ; window procedure are equal to zero (useful during an emergency cleanup ; when an error occurs). ; mov [.hdc], 0 mov [.memDC], 0 mov [.memBM], 0 (...) ; If anything has gone wrong then display a message box with a proper ; error message. ; .failed: stdcall ShowLastError, [hwnd] ; Emergency cleanup operations when something has gone wrong during the ; 'WM_PAINT' message processing. Before deleting objects and removing ; resources associated with them we have to check if their handles are ; valid (i.e. nonzero), because there is a possibility that some of these ; objects may be uninitialized. ; .cleanup: ; Delete the additional unneeded device context. ; cmp [.memDC], 0 je .memBMdelete invoke DeleteDC, [.memDC] test eax, eax jz .failed ; Release resources occupied by the bitmap associated with the ; application DC. ; .memBMdelete: cmp [.memBM], 0 je .hdcrelease invoke DeleteObject, [.memBM] test eax, eax jz .failed ; Release the application window device context retrieved by the ; 'GetDC' function call. ; .hdcrelease: cmp [.hdc], 0 je .wmdestroy invoke ReleaseDC, [hwnd], [.hdc] test eax, eax jz .failed ; Operations performed when the application window is to be destroyed. ; This is a regular cleanup after receiving the 'WM_DESTROY' message: here ; we delete objects and resources allocated during the application window ; creation. We don't need to destroy all controls (child windows) manually ; because it will be done automatically. ; ; These operations are also performed when application failed, so it is ; also a part of emergency cleanup part above, so we have to check all ; handles to be nonzero before proceeding. ; .wmdestroy: ; Delete the font used to display strings in the application ; window controls. ; cmp [.hFont], 0 je .quit invoke DeleteObject, [.hFont] test eax, eax jz .failed ; Post the 'WM_QUIT' message to the application message queue. ; .quit: invoke PostQuitMessage, 0 xor eax, eax (...) MSDN wrote: If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated child or owned windows when it destroys the parent or owner window. The function first destroys child or owned windows, and then it destroys the parent or owner window. |
|||
![]() |
|
revolution 30 Mar 2013, 17:27
Well there is still a problem if the cleanup code gets an error. Perhaps you can save and update an error code but still making sure you release all handles, even when something fails.
Although I personally think that for painting there is no need to bother jumping to ".failed". The OS can't paint for you anyway so when you return failed the OS will simply ignore your return code and move to the next item in the message queue. Just power through and release everything regardless of any returned error. |
|||
![]() |
|
Goto page 1, 2, 3 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.