Does anyone can help to understand why this code fails :(. The weird problem is that in my pc only fails when the window gets maximized :redface:. Thanks for any reply. .exe attached. It would be so nice to be able to debug the wndproc :(. Is this even possible? debug the callbacks functions in windows api :redface:?
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; Created by Felipe at 2018-04-03
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.686
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\gdi32.lib
.data
align 1
class_name byte "main window class",0
wnd_name byte "JUST TESTING",0
.data?
align 4
hinstance dword ?
hwindow dword ?
hdevicec dword ?
.code
align 4
start:
push ebp
mov ebp,esp
push NULL ; Get a handle for the program instance.
call GetModuleHandle
mov hinstance,eax
sub esp,76 ; WNDCLASSEX and MSG.
mov dword ptr[ebp-48],48 ; The size of the structure.
mov dword ptr[ebp-44],CS_HREDRAW or CS_VREDRAW ; The style of the class.
mov [ebp-40],wndproc
mov dword ptr[ebp-36],0 ; No extra
mov dword ptr[ebp-32],0 ; bytes.
mov eax,hinstance
mov [ebp-28],eax
push 500 ; The smile icon.
push hinstance
call LoadIcon
mov [ebp-24],eax ; hIcon.
push 600 ; The smile cursor.
push hinstance
call LoadCursor
mov [ebp-20],eax ; hCursor.
push WHITE_BRUSH ; Typical background color for a window.
call GetStockObject ; Get the handle of the brush.
mov [ebp-16],eax ; hBrush.
mov dword ptr[ebp-12],NULL ; No menu.
mov [ebp-8],offset class_name
mov dword ptr[ebp-4],NULL ; Use the same app icon for the small one.
lea eax,[ebp-48] ; WNDCLASSEX.
push eax
call RegisterClassEx
push NULL ; No value passed to the window.
push hinstance
push NULL ; No menu.
push NULL ; No parent of the window.
push CW_USEDEFAULT ; Default height.
push CW_USEDEFAULT ; Default width.
push CW_USEDEFAULT ; Default position
push CW_USEDEFAULT ; of the window.
push WS_OVERLAPPEDWINDOW ; Typical main window style.
push offset wnd_name ; Name of the main window.
push offset class_name
push WS_EX_OVERLAPPEDWINDOW ; Some extension of the style.
call CreateWindowEx
mov hwindow,eax
push SW_SHOWNORMAL ; Displaying the window for the first time.
push eax
call ShowWindow
push hwindow
call UpdateWindow ; Update the client area.
lea esi,[ebp-76] ; MSG.
align 4
msgloop:
push 0 ; Retrieve all
push 0 ; available messages.
push NULL ; Messages of any window of this thread.
push esi
call GetMessage
cmp eax,0
je end_program
push esi
call TranslateMessage ; Translate keyboard to messages.
push esi
call DispatchMessage ; Dispatch messages to wndproc.
jmp msgloop ; Loop until get the WM_QUIT message.
align 4
end_program:
mov eax,[ebp-68] ; wParam (exit code).
mov esp,ebp
pop ebp
push eax
call ExitProcess ; End the program.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
align 4
wndproc: ; The window procedure for the main window class.
push ebp
mov ebp,esp
sub esp,80 ; RECT AND PAINTSTRUC.
cmp dword ptr[ebp+12],WM_PAINT ; The client area was invalid.
jne check_destroy
push esi ; Intel ABI.
push edi
push ebx
lea esi,[ebp-80] ; RECT.
push esi
push hwindow
call GetClientRect ; Get the coordinates of the client area of the window.
lea esi,[ebp-64] ; PAINTSTRUCT.
push esi
push hwindow
call BeginPaint ; So, it must be painted again.
mov hdevicec,eax
lea esi,[ebp-80] ; RECT.
mov edi,[esi] ; First column.
mov ebx,[esi+4] ; First row.
align
test_pixar:
push 000000ffh ; Red.
push ebx ; Row.
push edi ; Column.
push hdevicec
call SetPixel ; Setting pixels, oh yeah!
inc edi ; Next column.
cmp edi,dword ptr[esi+8] ; Last column of this row?
jna test_pixar ; No, so keep filling the row.
mov edi,[esi] ; First column.
inc ebx ; Next row.
cmp ebx,[esi+12] ; Last row?
jna test_pixar ; No, so keep painting.
lea esi,[ebp-64] ; PAINTSTRUCT.
push esi
push hwindow
call EndPaint
xor eax,eax
pop ebx ; Intel ABI.
pop edi
pop esi
mov esp,ebp
pop ebp
ret 16
align 4
check_destroy:
cmp dword ptr[ebp+12],WM_DESTROY
jne do_the_default
push 0 ; Exit code (wParam in WM_QUIT).
call PostQuitMessage ; Notify to windows that this is the end of the application.
xor eax,eax
mov esp,ebp
pop ebp
ret 16
align 4
do_the_default:
push dword ptr[ebp+20] ; lParam.
push dword ptr[ebp+16] ; wParam.
push dword ptr[ebp+12] ; The message.
push dword ptr[ebp+8] ; Handle of the window.
call DefWindowProc ; Default processing for all the other messages.
mov esp,ebp
pop ebp
ret 16
end start
If it can be of any help, when i write the max row number hard coded to 800, it works well in full screen. But with greater numbers like 850 and 900 it fails again. :idea:
mov edi,[esi] ; First column.
inc ebx ; Next row.
cmp ebx,800 ; Last row?
jna test_pixar ; No, so keep painting.
Maybe SetPixel only works with screen of 1024x768? :redface:
Also by fails i mean that does not behave properly. It start to paint but doesn't come to the last row, in the title bar says: "this program doesn't respond" and then start again to paint from the top. This repeats, probably forever. :idea:
The amount of memory allocated for video may be limited to the size of 'full screen'. Trying to access memory outside that allocation may result in failure of your program.
In the following code portion, try modifying the hilighted blue instructions with the red ones and see what happens.
inc edi ; Next column.
cmp edi,dword ptr[esi+8] ; Last column of this row?
jna test_pixar ; No, so keep filling the row.
jb test_pixar ; No, so keep filling the row.
mov edi,[esi] ; First column.
inc ebx ; Next row.
cmp ebx,[esi+12] ; Last row?
jna test_pixar ; No, so keep painting
jb test_pixar ; No, so keep painting
I played a lot with the conditions of the loop before, and the same problem. I have done again what you suggested and happens the same. My screen resolution is of 1280x1024 :idea:. Thanks. :icon14:
Quote from: felipe on April 04, 2018, 10:02:30 AMIt would be so nice to be able to debug the wndproc :(. Is this even possible? debug the callbacks functions in windows api :redface:?
; include \masm32\include\masm32rt.inc
include \masm32\MasmBasic\MasmBasic.inc
...
WndProc proc uses esi edi ebx hWnd, uMsg, wParam:WPARAM, lParam:LPARAM
inc msgCount
NoDebMsg CATSTR NoDebMsg, <, WM_ENTERIDLE> ; don't show this message
deb 4, "msg", chg:msgCount ; this console deb will only be shown if chg:xxx has changed; needs OPT_Susy Console
Typical output:
msg 1 WM_NULL
msg 2 WM_GETMINMAXINFO
msg 3 WM_NCCREATE
msg 4 WM_NCCALCSIZE
msg 5 WM_CREATE
msg 6 WM_WINDOWPOSCHANGING
msg 7 WM_NCCALCSIZE
msg 8 WM_WINDOWPOSCHANGED
msg 9 WM_MOVE
msg 10 WM_SIZE
msg 11 WM_PARENTNOTIFY
msg 12 WM_WINDOWPOSCHANGING
msg 13 WM_ACTIVATEAPP
msg 14 WM_NCACTIVATE
msg 15 WM_ACTIVATE
msg 16 WM_IME_SETCONTEXT
msg 17 WM_IME_NOTIFY
msg 18 WM_SETFOCUS
msg 19 WM_KILLFOCUS
msg 20 WM_IME_SETCONTEXT
msg 21 WM_COMMAND: code 0, ID 1
msg 22 WM_SHOWWINDOW
msg 23 WM_WINDOWPOSCHANGING
Once you know for which message your program hangs, you can debug it inside the respective handler, either with Olly or similar, or with a simple deb 4 message:
mov ebx, rv(CreateMenu) ; create the main menu
deb 4, "create menu", wParam, lParam, eax, $Err$()
Output:
create menu
wParam 0
lParam 1637212
eax 197920829
$Err$() Operazione completata.__
I suspect it's your WM_PAINT handler. The deb macro accepts all kind of variables; if you want to see a pointer as text, prepend a $, e.g. $Err$() or $edi, etc; $$edi would show Unicode text.
Your code actually works but is really a whole lot of computation inside wndproc, freezing all the other messages, namely WM_SIZE.
My display is 1920x1080
yes - SetPixel is slow, so it will require some processing time
but, what i am not seeing is code to handle WM_CREATE and WM_CLOSE
i don't recall what the default process is for those two messages are, but i always handle them
WndProc PROC hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_CREATE
mov edx,hWnd
mov hwndMain,edx
xor eax,eax
.elseif eax==WM_CLOSE
INVOKE DestroyWindow,hWnd
xor eax,eax
.elseif eax==WM_DESTROY
INVOKE PostQuitMessage,NULL
xor eax,eax
.else
INVOKE DefWindowProc,hWnd,uMsg,wParam,lParam
.endif
ret
WndProc ENDP
add your WM_PAINT handler to that, and see how it goes
for testing, just do the first 10 rows and 10 columns :biggrin:
once you know that's all working correctly, try for full window
there are faster ways to do this.....
create a red brush
PatBlt the red brush into a memory DC + CompatibleBitmap
BitBlt from the memory DC to the screen DC using the update region in the PAINTSTRUCT
Quote from: aw27 on April 04, 2018, 04:43:50 PM
Your code actually works but is really a whole lot of computation inside wndproc, freezing all the other messages, namely WM_SIZE.
My display is 1920x1080
What did you expect by calling a Windows procedure over 2,000,000 times to simply change the content of a single memory dword on each occasion.
If you are looking for speed, do it yourself without all that SetPixel procedure overhead. It would be at least 20x faster.
Fantastic code Felipe!
Remember me fakirs :biggrin:
You must see in Rossler atractors thread how to change pixel value :t
@dedndave:i did that and still doesn't work. But with less rows work fine.
@raymond: That's interesting.Probably i was thinking something like: "ok windows should do whatever we told if we use the api." Is good to know than is not all too much high level, even with windows.
@HSE: i knew that this function is old (even gdi dosn't appear in the win api page of microsoft, only appears gdi+ as deprecated). But i was experimenting for first time with such a function. I will try to learn how to use directX. Soon as i can i will load some game, or something like that.
@jj: Don't know if i will use that, but seems like debugging those procedures is not easy or trivial. Now i see why in a recent thread about debugging (i think) someones talk about using message boxes (probably to show variables).
Thanks to all. :icon14:
Aside note: Have you ever drink too much beer for a single night? :greensml:
I use an ancient technique for testing results in a callback like a WndProc, I use the title bar, status bar or anything that does not lock up the display so you can see what a value is from inside the WndProc. Ain't subtle but it works fine. I rarely use a debugger these days as the technique I use is fast and simple. The other factor is I don't like the crippleware that debuggers are these days, I started with Microsoft Codeview debuggers and later use SoftIce and these later things work like toys in comparison.
Quote from: felipe on April 05, 2018, 10:53:17 AM@jj: Don't know if i will use that, but seems like debugging those procedures is not easy or trivial. Now i see why in a recent thread about debugging (i think) someones talk about using message boxes (probably to show variables).
It is easy and trivial, and message boxes are a pain in the a**. All you need is a console and a good debug macro. I do that all the time.
To prevent locking events when debugging in realtime, I write to a memory buffer ( often a circulair buffer ) with or without timestamps. This is very handy when debugging realtime Audio & Graphics routines.