News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

I don't know where to start with Windows GDI (64-bit)

Started by Honzik2005, January 14, 2025, 06:50:14 AM

Previous topic - Next topic

Honzik2005

I'm new to MASM as well as the Windows API, and I want to find out how to make some very simple 2D graphics in order to make a very simple game. I'm getting the hang of assembly on its own, but I'm having a hard time doing anything related to the Windows API.

Really, all I need to do is open a window, have some way of writing individual pixels (or maybe simple shapes) to certain locations on a back buffer, and then move that back buffer to the front buffer so that the graphics are displayed. That's it - I want to handle everything else. I could be wrong, but from what I can tell, Windows GDI is the simplest way of accomplishing this.

I've been looking for half a week, but I haven't really found anything helpful online. I've found a couple of Windows GDI examples in C, but I don't actually have any experience with C, so I have no idea how to reverse engineer them and translate them to MASM code. It also doesn't help that the examples aren't as simple as they could possibly be, so it's hard for me to figure out what part of the code does what and why.

I tried looking through the Windows GDI documentation, but that hasn't really cleared anything up. Maybe there's some prerequisite knowledge that I'm missing.

I really don't know where to start.

fearless

You can override the handling of the painting in the main window or a window you create yourself. For the main window, something like the following:

WndProc PROC hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

    mov eax, uMsg
    .IF eax == WM_INITDIALOG

    .ELSEIF eax == WM_ERASEBKGND
        mov eax, 1
        ret

    .ELSEIF eax == WM_PAINT
        Invoke MyPaint, hWin
        mov eax, 0
        ret

    ; .
    ; .
    ; .
    ;
    ; Other windows messages as per normal
    ;
    ; .
    ; .
    ; .

    .ELSE
        Invoke DefWindowProc, hWin, uMsg, wParam, lParam
        ret
    .ENDIF
    xor eax, eax
    ret
WndProc ENDP

Then in your MyPaint function you can setup doublebuffering and draw stuff to the window, for example:

MyPaint PROC hWin:DWORD
    LOCAL ps:PAINTSTRUCT
    LOCAL rect:RECT
    LOCAL framedrect:RECT
    LOCAL hdc:HDC
    LOCAL hdcMem:HDC
    LOCAL hBufferBitmap:DWORD
    LOCAL hBufferBitmapOld:DWORD
    LOCAL hBrush:DWORD
    LOCAL hBrushOld:DWORD
   
    Invoke BeginPaint, hWin, Addr ps                           
    mov hdc, eax                                                ; get the dc for the painting

    ;----------------------------------------------------------
    ; Setup Double Buffering
    ;----------------------------------------------------------
    Invoke GetClientRect, hWin, Addr rect                       ; Get dimensions of area to buffer
    Invoke CreateCompatibleDC, hdc                              ; Create memory dc for our buffer
    mov hdcMem, eax
   
    Invoke CreateCompatibleBitmap, hdc, rect.right, rect.bottom ; Create bitmap of size that matches dimensions
    mov hBufferBitmap, eax
    Invoke SelectObject, hdcMem, hBufferBitmap                  ; Select our created buffer bitmap into our memory dc
    mov hBufferBitmapOld, eax                                   ; Save old buffer bitmap
   
    ;==========================================================
    ; Start of our painting here, all the stuff before is just
    ; the setup of the doublebuffer etc. The example shows
    ; painting the background a color, and framing a rectangle.
    ;==========================================================
   
    ;----------------------------------------------------------
    ; Paint background of window/control
    ;----------------------------------------------------------
    Invoke GetStockObject, DC_BRUSH                             ; Get system DC Brush
    mov hBrush, eax                                             ; Save brush handle
    Invoke SelectObject, hdcMem, hBrush                         ; Switch it into hdcMem
    mov hBrushOld, eax                                          ; Save old brush handle
    Invoke SetDCBrushColor, hdcMem, 09EE0DBh ; RGB(219,224,158) ; Set color for FillRect
    Invoke FillRect, hdcMem, Addr rect, hBrush                  ; Fill the rectangle
    Invoke SelectObject, hdcMem, hBrushOld                      ; Switch back old brush handle
    Invoke DeleteObject, hBrush                                 ; Delete brush
   
    ;----------------------------------------------------------
    ; Paint a framed rectangle (outlined only)
    ;----------------------------------------------------------
    Invoke CopyRect, Addr framedrect, Addr rect                 ; Make a copy of rect
   
    add framedrect.left, 40                                     ; Adjust framedrect so
    sub framedrect.right, 40                                    ; that it fits inside
    add framedrect.top, 40                                      ; the main window rect
    sub framedrect.bottom, 40
   
    Invoke GetStockObject, DC_BRUSH                             ; Get system DC Brush
    mov hBrush, eax                                             ; Save brush handle
    Invoke SelectObject, hdcMem, hBrush                         ; Switch it into hdcMem
    mov hBrushOld, eax                                          ; Save old brush handle
    Invoke SetDCBrushColor, hdcMem, 04908B0h ; RGB(176,8,73)    ; Set color for FrameRect
    Invoke FrameRect, hdcMem, Addr framedrect, hBrush           ; Frame the rectangle
    Invoke SelectObject, hdcMem, hBrushOld                      ; Switch back old brush handle
    Invoke DeleteObject, hBrush                                 ; Delete brush

    ;==========================================================
    ; End of our painting, rest is just copying buffer back
    ; and tidying up.
    ;==========================================================

    ;----------------------------------------------------------
    ; Copy back to main hdc from hdcMem
    ;----------------------------------------------------------
    Invoke BitBlt, hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY

    ;----------------------------------------------------------
    ; Finish Double Buffering & Cleanup
    ;----------------------------------------------------------   
    Invoke SelectObject, hdcMem, hBufferBitmapOld               ; Switch back to old buffer bitmap before deleting
    Invoke DeleteObject, hBufferBitmap                          ; Delete bitmap used for double buffering
    Invoke DeleteDC, hdcMem                                     ; Delete double buffer hdc
   
    Invoke EndPaint, hWin, Addr ps
    mov eax, 0

    ret
MyPaint ENDP



Honzik2005

Thanks so much! I'm going to see if I can get this to work

TimoVJL

Also if WNDCLASS wc.hbrBackground = 0 , window will be hollow without background painting ?
May the source be with you