flat assembler
Message board for the users of flat assembler.
Index
> Windows > Why this code does not work? |
Author |
|
A$M 11 Sep 2013, 18:32
Hello!
I made this code that should paint a pixel somewhere in the window, but it is not working. Code: format PE GUI 4.0 entry start include "win32a.inc" section '.text' code readable executable start: ;mov [wc.lpfnWndProc], WindowProc invoke GetModuleHandle, 0 mov [wc.hInstance], eax invoke LoadIcon, 0, IDI_APPLICATION mov [wc.hIcon], eax mov [wc.hIconSm], eax invoke LoadCursor, 0, IDC_CROSS mov [wc.hCursor], eax invoke GetStockObject, BLACK_BRUSH mov [wc.hbrBackground], eax invoke RegisterClassEx, wc, 0 invoke CreateWindowEx, 0, _class, _title, WS_OVERLAPPEDWINDOW+WS_VISIBLE, 100, 100, 500, 500, 0, 0, [wc.hInstance], 0 test eax, eax jz winerror ;invoke ShowWindow, [wc.hInstance], [nCmdShow] msg_loop: invoke GetMessage, wMsg, 0, 0, 0 cmp eax,1 jb exit jne msg_loop invoke TranslateMessage, wMsg invoke DispatchMessage, wMsg jmp msg_loop winerror: invoke MessageBox, 0, WinError, 0, MB_ICONERROR+MB_OK exit: mov eax, [wMsg.wParam] invoke ExitProcess, [wMsg.wParam] proc WindowProc uses ebx esi edi, hWnd, uMsg, wParam, lParam mov eax, [uMsg] cmp eax, WM_CREATE je wmCreate cmp eax, WM_TIMER je wmTimer cmp eax, WM_PAINT je wmPaint cmp eax, WM_CLOSE je wmClose cmp eax, WM_DESTROY je wmDestroy invoke DefWindowProcA, [hWnd], [uMsg], [wParam], [lParam] ret wmCreate: invoke SetTimer, [hWnd], 1, 20, 0 ret wmTimer: invoke InvalidateRect, [hWnd], 0, 0 ret wmPaint: invoke BeginPaint, [hWnd], psPaint mov [hDC], eax invoke CreateCompatibleDC, [hDC] mov [memDC], eax invoke CreateDIBSection, [hDC], BITMAPINFO, 0, pDIBSCR, 0, 0 mov [hDIBSCR], eax invoke SelectObject, [hDC], [hDIBSCR] mov [hOldDIB], eax invoke CreateCompatibleDC, [hDC] mov [hBackDC], eax invoke CreateCompatibleBitmap, [hDC], 640, 480 mov [bufBMP], eax invoke SelectObject, [hBackDC], [bufBMP] mov [hOldBmp], eax mov edi, [pDIBSCR] mov dword[edi+320*240*4], 0FFFFFFh invoke BitBlt, [hBackDC], 0, 0, 640, 480, [memDC], 0, 0, SRCCOPY invoke BitBlt, [hDC], 0, 0, 640, 480, [hBackDC], 0, 0, SRCCOPY invoke SelectObject, [hBackDC], [hOldBmp] invoke DeleteObject, [bufBMP] invoke DeleteDC, [hBackDC] invoke SelectObject, [memDC], [hOldDIB] invoke DeleteObject, [hDIBSCR] invoke DeleteDC, [memDC] ; invoke Ellipse, [hDC], 10, 10, 200, 200 invoke EndPaint, [hWnd], psPaint ret wmClose: invoke DestroyWindow, [hWnd] ret wmDestroy: invoke PostQuitMessage, WM_QUIT ret endp section '.data' data readable writeable wc WNDCLASSEX wcend-wc, 0, WindowProc, 0, 0, 0, 0, 0, 0, 0, _class, 0 wcend: _class db "MAIN",0 _title db "Teste de janela",0 WinError db "Não foi possível criar a janela",0 BITMAPINFO BITMAPINFOHEADER sizeof.BITMAPINFOHEADER,\ ; biSize 640,\ ; biWidth 480,\ ; biHeight 1,\ ; biPlanes 32,\ ; biBitCount 0,\ ; biCompression 0,\ ; biSizeImage 0, \ ; biXPelsPerMeter 0, \ ; biYPelsPerMeter 0, \ ; biClrUsed 0 ; biClrImportant section '.bss' data readable writeable wMsg MSG psPaint PAINTSTRUCT hDC dd ? memDC dd ? pDIBSCR dd ? hDIBSCR dd ? hOldDIB dd ? hBackDC dd ? bufBMP dd ? hOldBmp dd ? section '.idata' import data readable writeable library kernel32, "KERNEL32.DLL",\ user32, "USER32.DLL",\ gdi32, "GDI32.DLL" include "api\kernel32.inc" include "api\user32.inc" include "api\gdi32.inc" ;section '.rsrc' resource data readable I made it from this code (http://board.flatassembler.net/download.php?id=6195), with some changes. But it does not work. Does anyone know why? |
|||
11 Sep 2013, 18:32 |
|
HaHaAnonymous 11 Sep 2013, 20:52
[ Post removed by author. ]
Last edited by HaHaAnonymous on 28 Feb 2015, 19:57; edited 1 time in total |
|||
11 Sep 2013, 20:52 |
|
A$M 12 Sep 2013, 14:46
AsmGuru62 wrote: A$M: Well... In fact, we can ignore this code. I want to learn how to make graphics in windows in the same way as would be done in DOS. Example: Code: mov [0A0000h+160+100*320], 15 ; White pixel at 160, 100 Using GDI, how could I get them? Ps.: SetPixel isn't very slow? |
|||
12 Sep 2013, 14:46 |
|
AsmGuru62 12 Sep 2013, 16:03
I see...
SetPixel is indeed slow, so if you want to use to draw a lot of pixels -- then try to draw (using SetPixel) in memory and then BitBlt on screen. In DOS to draw a line you must use pixels and Brezenham logic, but in Windows -- there is an API to draw a line. In fact, API has everything you need to draw: polygons, circles (ellipses), etc. If your output to screen is too loaded - a lot of objects to be painted, use memory DC as you did in that code and then after drawing on memory DC -- BitBlt it to a screen DC. Tell me if you want an example of something to be painted and I will try to make a code sample. |
|||
12 Sep 2013, 16:03 |
|
A$M 13 Sep 2013, 21:09
My new code:
Code: format PE GUI 4.0 entry start include "win32a.inc" section '.text' code readable executable start: invoke GetModuleHandle, 0 mov [wc.hInstance], eax invoke LoadIcon, 0, IDI_APPLICATION mov [wc.hIcon], eax mov [wc.hIconSm], eax invoke LoadCursor, 0, IDC_CROSS mov [wc.hCursor], eax invoke GetStockObject, BLACK_BRUSH mov [wc.hbrBackground], eax invoke RegisterClassEx, wc, 0 invoke CreateWindowEx, 0, _class, _title, WS_OVERLAPPED+WS_SYSMENU+WS_VISIBLE, 100, 100, 640, 480, 0, 0, [wc.hInstance], 0 test eax, eax jz winerror msg_loop: invoke GetMessage, wMsg, 0, 0, 0 cmp eax, 1 jb exit jne msg_loop invoke TranslateMessage, wMsg invoke DispatchMessage, wMsg jmp msg_loop winerror: invoke MessageBox, 0, WinError, 0, MB_ICONERROR+MB_OK exit: mov eax, [wMsg.wParam] invoke ExitProcess, [wMsg.wParam] proc WindowProc uses ebx esi edi, hWnd, uMsg, wParam, lParam mov eax, [uMsg] cmp eax, WM_CREATE je wmCreate cmp eax, WM_TIMER je wmTimer cmp eax, WM_PAINT je wmPaint cmp eax, WM_CLOSE je wmClose cmp eax, WM_DESTROY je wmDestroy invoke DefWindowProcA, [hWnd], [uMsg], [wParam], [lParam] ret wmCreate: invoke SetTimer, [hWnd], 1, 20, 0 invoke GetDC, [hWnd] mov [hDC], eax invoke CreateCompatibleDC, [hDC] ; DC de memória mov [hMemDC], eax invoke CreateDIBSection, [hDC], BITMAPINFO, 0, pDIBSCR, 0, 0 ; Tela mov [hDIBSCR], eax invoke SelectObject, [hMemDC], [hDIBSCR] ret wmTimer: mov eax, [color] cmp eax, 0FFFFFFh jne @f mov [color], 080h @@: add [color], 010101h invoke InvalidateRect, [hWnd], 0, 0 ret wmPaint: invoke BeginPaint, [hWnd], psPaint mov [hDC], eax mov edi, [pDIBSCR] mov ecx, 640*480 mov eax, [color] rep stosd invoke BitBlt, [hDC], 0, 0, 640, 480, [hMemDC], 0, 0, SRCCOPY invoke EndPaint, [hWnd], psPaint ret wmClose: invoke SelectObject, [hMemDC], [hDIBSCR] mov [oDIBSCR], eax invoke DeleteObject, [oDIBSCR] invoke DeleteDC, [hMemDC] invoke DestroyWindow, [hWnd] ret wmDestroy: invoke PostQuitMessage, WM_QUIT ret endp section '.data' data readable writeable wc WNDCLASSEX wcend-wc, 0, WindowProc, 0, 0, 0, 0, 0, 0, 0, _class, 0 wcend: _class db "MAIN",0 _title db "Teste de janela",0 WinError db "Não foi possível criar a janela",0 color dd 0 BITMAPINFO BITMAPINFOHEADER sizeof.BITMAPINFOHEADER,\ ; biSize 640,\ ; biWidth 480,\ ; biHeight 1,\ ; biPlanes 32,\ ; biBitCount 0,\ ; biCompression 0,\ ; biSizeImage 0, \ ; biXPelsPerMeter 0, \ ; biYPelsPerMeter 0, \ ; biClrUsed 0 ; biClrImportant section '.bss' data readable writeable wMsg MSG psPaint PAINTSTRUCT hDC dd ? hMemDC dd ? pDIBSCR dd ? hDIBSCR dd ? oDIBSCR dd ? hBackDC dd ? section '.idata' import data readable writeable library kernel32, "KERNEL32.DLL",\ user32, "USER32.DLL",\ gdi32, "GDI32.DLL" include "api\kernel32.inc" include "api\user32.inc" include "api\gdi32.inc" ;section '.rsrc' resource data readable |
|||
13 Sep 2013, 21:09 |
|
AsmGuru62 14 Sep 2013, 00:37
Are you creating a game?
If so, you need the thread -- timer is not a good solution. In order to draw in windows -- no need for the DIB section. Just draw into memory DC for fast output: 1. CreateCompatibleDC() 2. CreateCompatibleBitmap() 3. SelectObject() from step #2 into DC from step #1 4. Draw everything on DC from step #1 5. BitBlt() from DC from step #1 into screen DC 6. Deselect all back and delete DC and bitmap For speed you can cache DC and BMP, so you do not need to re-create each time. |
|||
14 Sep 2013, 00:37 |
|
A$M 14 Sep 2013, 15:39
AsmGuru62 wrote: Are you creating a game? 1. How to create a thread? 2. So how can I draw directly on the memory DC? Ps.: Yes, I'm creating a game. |
|||
14 Sep 2013, 15:39 |
|
HaHaAnonymous 14 Sep 2013, 16:54
[ Post removed by author. ]
Last edited by HaHaAnonymous on 28 Feb 2015, 19:56; edited 1 time in total |
|||
14 Sep 2013, 16:54 |
|
AsmGuru62 15 Sep 2013, 00:34
The drawings in memory DC are done as usual -- using functions, like:
FillRect FrameRect Ellipse MoveTo + LineTo Polygon or something like that. Then, when the frame is complete (in memory) -- use BitBlt() to transfer it from memory DC to a screen DC. It works well, because in most cases BitBlt() is accelerated by a graphics card you have. If your game is complex, like 3D modeling - then OpenGL or DirectX maybe better to use than Win API. I posted a simple game a while ago: http://board.flatassembler.net/topic.php?t=15028 It has a bug however, which I never fixed. If you hold space bar key for too long - it crashes. |
|||
15 Sep 2013, 00:34 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.