News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

double buffer graphics

Started by Sarel, February 24, 2009, 06:41:25 PM

Previous topic - Next topic

Sarel

I am trying to draw on a memory Device Context before I will copy the picture to the Main DC to avoid flicker.
If I use the Main DC as the drawing surface it works. Now i want to add a hidden drawing surface but it fails. The 2 commented out parts is how I think it should work.

The timerer procedure updates the pointer to the frame to use and paint the tree, mask and Man to the main DC. Unfortunately a complete zip file is 1.3 MB in size (Not allowed)

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib            ; calls to functions in user32.lib and kernel32.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\gdi32.inc
includelib \masm32\lib\gdi32.lib 

include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib
include \masm32\include\debug.inc
includelib \masm32\lib\debug.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
Timer1Proc proto :DWORD,:DWORD,:DWORD,:DWORD

IDB_SwordManColor equ 20 ;Bitmap 22 frames 210 x 158
IDB_SwordManMask  equ 21 ;Bitmap 22 frames
IDB_Tree       equ 22 ;Bitmap 640 x 480
IDT_1 equ 1000



.DATA                     ; initialized data
ClassName  db "SimpleWinClass",0         ; the name of our window class
AppName    db "Sword man",0       ; the name of our window
btnClass   db "BUTTON",0
ButtonText db "Druk my",0
align 4
FrameStart dword 0

.DATA?                                   ; Uninitialized data
hInstance            HINSTANCE ?         ; Instance handle of our program
CommandLine          LPSTR ?
hDC                  HWND ?
hSwordManColor       HGDIOBJ  ?
hSwordManMask        HGDIOBJ  ?
hTree                HGDIOBJ  ?
hMemDrawBitmap       HGDIOBJ  ?          ;This buffer will be copied to the main screen         
hMemSwordManColorDC  HDC ?
hMemSwordManMaskDC   HDC ?
hMemTreeDC           HDC ?
hMemDrawDC           HDC ?


.CODE                                   ; Here begins our code
start:
invoke GetModuleHandle, NULL            ; get the instance handle of our program.
                                        ; Under Win32, hmodule==hinstance mov hInstance,eax
mov hInstance,eax
invoke GetCommandLine                   ; get the command line. You don't have to call this function IF
                                        ; your program doesn't process the command line.
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT        ; call the main function
invoke ExitProcess, eax                 ; quit our program. The exit code is returned in eax from WinMain.



WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX                        ; create local variables on stack
    LOCAL msg:MSG
    LOCAL hwnd:HWND

    mov   wc.cbSize,SIZEOF WNDCLASSEX          ; fill values in members of wc
    mov   wc.style, CS_HREDRAW or CS_VREDRAW or CS_OWNDC
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_WINDOW+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc              ; register our window class
    invoke CreateWindowEx,NULL,\
                ADDR ClassName,\
                ADDR AppName,\
                WS_OVERLAPPEDWINDOW,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                640,\
                480,\
                NULL,\
                NULL,\
                hInst,\
                NULL
    mov   hwnd,eax
    invoke ShowWindow, hwnd,CmdShow              ; display our window on desktop
    invoke UpdateWindow, hwnd                    ; refresh the client area

    .WHILE TRUE                                  ; Enter message loop
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
   .ENDW
    mov     eax,msg.wParam                        ; return exit code in eax
    ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   LOCAL ps:PAINTSTRUCT
   LOCAL rect:RECT


    .IF uMsg==WM_DESTROY                              ; if the user closes our window
        invoke PostQuitMessage,NULL                   ; quit our application
        invoke DeleteObject,hSwordManColor
        invoke DeleteObject,hSwordManMask
        invoke DeleteDC,hMemSwordManColorDC
        invoke DeleteDC,hMemSwordManMaskDC
        invoke DeleteDC,hMemTreeDC
        invoke DeleteObject,hMemDrawBitmap
        invoke DeleteDC,hMemDrawDC
        invoke KillTimer,hWnd,IDT_1
       
        invoke ReleaseDC,hWnd,hDC

    .ELSEIF uMsg==WM_CREATE
        invoke LoadBitmap,hInstance,IDB_SwordManColor
        mov hSwordManColor,eax
        invoke CreateCompatibleDC,hDC
        mov hMemSwordManColorDC,eax
        invoke SelectObject,hMemSwordManColorDC,hSwordManColor

        invoke LoadBitmap,hInstance,IDB_SwordManMask
        mov hSwordManMask,eax
        invoke CreateCompatibleDC,hDC
        mov hMemSwordManMaskDC,eax
        invoke SelectObject,hMemSwordManMaskDC,hSwordManMask

        invoke LoadBitmap,hInstance,IDB_Tree
        mov hTree,eax
        invoke CreateCompatibleDC,hDC
        mov hMemTreeDC,eax
        invoke SelectObject,hMemTreeDC,hTree

comment #
        invoke CreateCompatibleDC,hDC                  ;Create a 1x1 pixel device context
        mov hMemDrawDC,eax
        invoke CreateCompatibleBitmap,hDC,640,480      ;Create a memory bitmap compatible with the main DC
        mov hMemDrawBitmap,eax
        invoke SelectObject,hMemDrawDC,hMemDrawBitmap  ;Select the empty bitmap into the memory DC
#

        invoke SetTimer,hWnd,IDT_1,100,addr Timer1Proc
       
        invoke GetDC,hWnd
        mov hDC,eax
       
   
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam  ; Default message processing
        ret
    .ENDIF
    xor eax,eax
    ret
WndProc endp

;-------------------------------------------------------------------------
Timer1Proc proc hWindow:HWND,uMessage:UINT,TimerID:UINT,Time:DWORD

    LOCAL rect:RECT

    mov edx,FrameStart ;This part move the current frame pointer to the next frame
    add edx,210
    mov FrameStart,edx
    cmp edx,4410 ;21*210
    jb @f
    mov FrameStart,0
  @@:
 
comment #
    invoke BitBlt,hMemDrawDC,0,0,640,480,hMemTreeDC,0,0,SRCCOPY ;Put the tree into the memory DC
    invoke BitBlt,hMemDrawDC,100,100,210,158,hMemSwordManMaskDC,FrameStart,0,SRCAND ;copy the mask
    invoke BitBlt,hMemDrawDC,100,100,210,158,hMemSwordManColorDC,FrameStart,0,SRCPAINT ;copy the color data
    invoke BitBlt,hDC,0,0,640,480,hMemDrawDC,0,0,SRCCOPY ;copy from the memory DC to the main DC
#
    invoke BitBlt,hDC,0,0,640,480,hMemTreeDC,0,0,SRCCOPY
    invoke BitBlt,hDC,100,100,210,158,hMemSwordManMaskDC,FrameStart,0,SRCAND
    invoke BitBlt,hDC,100,100,210,158,hMemSwordManColorDC,FrameStart,0,SRCPAINT


 
    ;invoke GetClientRect, hWindow,addr rect
    ;invoke InvalidateRect,hWindow,addr rect,TRUE
    ;invoke UpdateWindow,hWindow
    ret

Timer1Proc endp



end start


Added code tags


Jimg

The only thing I see immediately, is that you have to get the handle of hdc before you create the compatible dc, just move the getdc above the first reference to hdc.

Sarel

 :bg
Thanks Jimg. The problem is solved. I moved the GetDC to the start of the WM_CEATE section and its fine. It took me three nights with no results.