GdipDrawLine无法显示任何内容。用Olly调试器逐步调试时,发现每个函数都成功执行且没有错误

编程语言 2026-07-10

我想用汇编语言(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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章