GdipDrawLine无法显示任何内容。用Olly调试器逐步调试时,发现每个函数都成功执行且没有错误
我想用汇编语言(NASM)让GdipDrawLine能工作。用Olly调试器逐步执行代码时,EAX的每条指令都显示0,表示状态码为OK,但屏幕仍然空白。GDI+函数是在响应WM_PAINT时被调用,除了GdiplusStartup,它是在Winmain的 CreateWindowEx之后立即调用。
我的系统是AMD Ryzen 5 5600G
Radeon Graphics 3.90 gh
16.0 GB RAM
64位操作系统,基于x86的处理器
以下是完整代码:
;GDIPlus.asm ; GDI+ / DrawLine
;Assemble with:
;nasm -f win32 GDIPlus.asm -o GDIPlus.obj
;Link with:
;golink.exe /entry:start GDIPlus.obj kernel32.dll user32.dll gdiplus.dll
%include '\nasm32\inc\win32\windows.inc'
%include '\nasm32\inc\win32\kernel32.inc'
%include '\nasm32\inc\win32\user32.inc'
%include '\nasm32\inc\nasm32.inc'
%include '\nasm32\inc\win32\gdiplus.inc'
[section .data]
;STRUCS
wcx times WNDCLASSEX_size db 0
msg times MSG_size db 0
ps times PAINTSTRUCT_size dd 0
;GDI+ Variables
gdiplusStartupInput dd 1, 0, 0, 0
penColor dd 0xFF0000FF ; Alpha=255, Red=0, Green=0, Blue=255
penWidth dd 2.0
gdiplusToken dd 0
graphicsPtr dd 0
penPtr dd 0
x1 dd 10.0
y1 dd 10.0
x2 dd 100.0
y2 dd 200.0
;Handles
hDC dd 0 ; Handle to the Device Context
hInstance dd 0
hWnd dd 0
;Various labels
szTitle db 'GDIPlus :GDI+ /DrawLine',0x0
szClass db 'GDIPlus',0x0
[section .text]
start:
proc GDIPlus
invoke GetModuleHandleA, dword NULL
mov [hInstance], eax
invoke WinMain,dword [hInstance],dword NULL,dword NULL,dword SW_SHOWNORMAL
invoke ExitProcess,dword NULL
ret
endproc ;GDIPlus
proc WinMain ,hInst,hPinst,CmdLn,dwShow
;Load WNDCLASSEX
push dword WNDCLASSEX_size
pop dword [wcx + WNDCLASSEX.cbSize]
push dword argv(hInst)
pop dword [wcx + WNDCLASSEX.hInstance]
push dword szClass
pop dword [wcx + WNDCLASSEX.lpszClassName]
push dword WndProc
pop dword [wcx + WNDCLASSEX.lpfnWndProc]
push dword COLOR_BTNFACE +1
pop dword [wcx + WNDCLASSEX.hbrBackground]
push dword CS_VREDRAW +CS_HREDRAW
pop dword [wcx + WNDCLASSEX.style]
;Register the window class
invoke RegisterClassExA, wcx
;Load window
invoke CreateWindowExA,\
WS_EX_OVERLAPPEDWINDOW,\
szClass,\
szTitle,\
WS_OVERLAPPEDWINDOW +WS_VISIBLE ,\
10, 10, 1200, 700,\
NULL,\
NULL,\
[wcx + WNDCLASSEX.hInstance],\
NULL
mov [hWnd], eax
;GDIPlus Startup
invoke GdiplusStartup, gdiplusToken, gdiplusStartupInput, NULL
;Message Pump
MsgGet:
invoke GetMessageA, dword msg, dword NULL, dword NULL, dword NULL
cmp eax,0
jnz MsgProcess
jmp MsgEnd
MsgProcess:
invoke TranslateMessage, dword msg
invoke DispatchMessageA, dword msg
jmp MsgGet
MsgEnd:
ret
endproc ;WinMain
;========================================================== WNDPROC
proc WndProc, hWin, uMsg, wParam, lParam
IsDestroy?:
cmp dword argv(uMsg), WM_DESTROY
jnz IsKey?
jmp wpExit
IsKey?:
cmp dword argv(uMsg), WM_KEYDOWN
jz wpIsEsc?
IsPaint?:
cmp dword argv(uMsg), WM_PAINT
jnz DefWndProc
invoke GDIPaint, dword argv(hWin)
ret
;Key pressed
wpIsEsc?:
cmp dword argv(wParam), VK_ESCAPE
jz near wpEsc
ret
;Escape key hit
wpEsc:
invoke SendMessageA, argv(hWin),WM_CLOSE,NULL,NULL
xor eax,eax
ret
DefWndProc:
invoke DefWindowProcA, dword argv(hWin), dword argv(uMsg), dword argv(wParam), dword argv(lParam)
ret
;Exit procecure
wpExit:
invoke GdipDeleteGraphics, dword [graphicsPtr]
invoke GdipDeletePen, dword [penPtr]
invoke GdiplusShutdown, dword [gdiplusToken]
invoke PostQuitMessage,dword NULL
xor eax,eax
ret
endproc ;WndProc
;----------------------------------
proc GDIPaint, gdiphWin
;Get hDC
invoke BeginPaint, dword argv(gdiphWin), ps
mov dword [hDC],eax
;GDI+ instructions
invoke GdipCreateFromHDC, dword [hDC],dword graphicsPtr
invoke GdipSetPageUnit, dword [graphicsPtr], 2
invoke GdipCreatePen1,dword [penColor], dword [penWidth], 6, penPtr
invoke GdipDrawLine, dword [graphicsPtr],dword [penPtr], dword [x1], dword [y1], dword [x2], dword [y2]
invoke EndPaint, dword argv(gdiphWin), ps
ret 4
解决方案
问题出在GdipSetPageUnit和 GdipCreatePen的 GpUnit参数上。基本的Windows代码似乎没有问题。
我认为问题已经解决。以下修改后的代码将显示一条长250毫米的水平线。
Notes:
The only code I'll upload here is the new and modified GDI+ code.
.data
pagescaleFloat dd 1.0
;These points draw a 250 mm line on the screen
x1 dd 10.0
y1 dd 100.0
x2 dd 260.0
y2 dd 100.0
;---------------------------
.text
;GDIPlus Startup. (Right after CreateWindowEx
invoke GdiplusStartup, gdiplusToken, gdiplusStartupInput, NULL
. . .
. . .
wpExit:
invoke GdipDeleteGraphics, dword [graphicsPtr]
invoke GdipDeletePen, dword [penPtr]
invoke GdiplusShutdown, dword [gdiplusToken]
;-----------------------------------------------------
proc GDIPaint, gdiphWin
;Get hDC
invoke BeginPaint, dword argv(gdiphWin), ps
mov dword [hDC],eax
;GDI+ instructions
invoke GdipCreateFromHDC, dword [hDC],dword graphicsPtr
invoke GdipSetPageUnit, dword [graphicsPtr], 6 ;(GpUnit =6 =mm)
invoke GdipSetPageScale, dword [graphicsPtr], dword [pagescaleFloat]
invoke GdipCreatePen1,dword [penColor], dword [penWidth], 2, penPtr ;GpUnit =2 =pixel
invoke GdipDrawLine, dword argv(graphicsPtr),dword argv(penPtr), dword [x1], dword [y1], dword [x2], dword [y2]
invoke EndPaint, dword argv(gdiphWin), ps
ret 4
endproc ;GDIPaint
离开键盘
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。