News:

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

Copy control with BitBlt not working..

Started by hotrod, January 15, 2010, 01:33:23 PM

Previous topic - Next topic

hotrod

BitBlt is new to me and having a little problem. Why do I get a black rectangle and how can it be corrected. Thanks...
      
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   LOCAL ps: PAINTSTRUCT
   LOCAL hdc: HDC
   LOCAL hMemDC:HDC
   LOCAL rect: RECT
   
   .if uMsg==WM_CREATE
invoke CreateWindowEx, NULL, SADD("STATIC"), NULL,\
WS_CHILD + WS_VISIBLE + WS_BORDER, 10, 10, 30, 30, \
hWnd, 1, hInstance, NULL
mov hStc, eax
mov eax, TRUE
ret

   .elseif uMsg==WM_PAINT
invoke BeginPaint, hWnd, addr ps
mov hdc, eax

invoke GetDC, hStc
invoke CreateCompatibleDC, eax
mov hMemDC, eax
invoke CreateCompatibleBitmap, hdc, 30, 30
mov hBitmap, eax

invoke SelectObject, hMemDC, hBitmap
invoke GetClientRect, hWnd, addr rect
invoke BitBlt, hdc, 50, 10, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY
invoke DeleteDC, hMemDC
invoke EndPaint, hWnd, addr ps
ret


qWord

Quote from: hotrod on January 15, 2010, 01:33:23 PM
Why do I get a black rectangle and how can it be corrected
The memory DC isn't filled, so that you copy a black rectangle.
You have simply to use the DC returned by  GetDC(hStc)/GetWindowDC(hStc) as source-DC:

invoke Get[Client/Window]Rect, hStc, addr rect
invoke Get[Window]DC,hStc
push eax
invoke BitBlt, hdc, 50, 10, rect.right, rect.bottom, eax, 0, 0, SRCCOPY
pop eax
invoke ReleaseDC,hStc,eax

Also you must use the WS_CLIPCHILDREN-style for the parent window - otherwise you get an rectangle filled with parent's backgroundcolor (BeginPaint erase the background).

EDIT: the code was not correct - now it is ;)
FPU in a trice: SmplMath
It's that simple!

hotrod

Thanks qWord, but no success - still black. Here is what I now have.

Main window:

INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW + WS_CLIPCHILDREN,400, 200, 300, 200, NULL,NULL,hInst,NULL

Paint:

invoke BeginPaint, hWnd, addr ps
mov hdc, eax

invoke GetDC, hStc
invoke CreateCompatibleDC, eax
mov hMemDC, eax
invoke CreateCompatibleBitmap, hdc, 30, 30
mov hBitmap, eax
invoke SelectObject, hMemDC, hBitmap

;**************************************************************************
invoke GetClientRect, hStc, addr rect
invoke GetDC,hStc
push eax
invoke BitBlt, hdc, 50, 10, rect.right, rect.bottom, eax, 0, 0, SRCCOPY
pop eax
invoke ReleaseDC,hStc,eax
;**************************************************************************

invoke DeleteDC, hMemDC
invoke EndPaint, hWnd, addr ps

TNick

My friend,

you have to draw something in hMemDC. So that, when you copy the content of it, you will see something.
have a ...

Paint_Event     PROC    hWnd:DWORD
        LOCAL   PS:PAINTSTRUCT
        LOCAL   hDC_Dsk:DWORD
        LOCAL   hDC_Tmp:DWORD,hBTM_Tmp:DWORD
        LOCAL   hTmp_Pen:DWORD,hTmp_Brs:DWORD
       
        INVOKE  BeginPaint,     hWnd, ADDR PS
       
        ; create a dc compatible with the desktop
        INVOKE  GetDC,          NULL
        mov     hDC_Dsk,        eax
        INVOKE  CreateCompatibleDC,     eax
        mov     hDC_Tmp,        eax
        INVOKE  CreateCompatibleBitmap, hDC_Dsk,30,30
        INVOKE  SelectObject,   hDC_Tmp,eax
        mov     hBTM_Tmp,       eax
        INVOKE  ReleaseDC,      NULL,hDC_Dsk
       
        ; prepare the dc
        INVOKE  GetStockObject, DC_BRUSH
        INVOKE  SelectObject,   hDC_Tmp,eax
        mov     hTmp_Brs,       eax
        INVOKE  GetStockObject, DC_PEN
        INVOKE  SelectObject,   hDC_Tmp,eax
        mov     hTmp_Pen,       eax
        INVOKE  SetDCPenColor,  hDC_Tmp,004080FFh
        INVOKE  SetDCBrushColor,hDC_Tmp,00400080h
       
        ; do some painting inside that dc
        INVOKE  Rectangle,      hDC_Tmp,0,0,30,30
       
        ; copy the content of hDC_Tmp inside
        INVOKE  BitBlt,         PS.hdc,50,10,30,30,hDC_Tmp,0,0,SRCCOPY
       
        ; release resources
        INVOKE  SelectObject,   hDC_Tmp,hTmp_Pen
        INVOKE  SelectObject,   hDC_Tmp,hTmp_Brs
        INVOKE  SelectObject,   hDC_Tmp,hBTM_Tmp
        INVOKE  DeleteObject,   eax
        INVOKE  DeleteDC,       hDC_Tmp
       
       
        INVOKE  EndPaint,       hWnd, ADDR PS.hdc
       
        ret
Paint_Event     ENDP

however, you could do all this inside the dc returned by BeginPaint. No need to create a compatible dc.

... a little more thinking ... :boohoo:

oh, you think that
invoke GetDC, hStc
invoke CreateCompatibleDC, eax
mov hMemDC, eax
invoke CreateCompatibleBitmap, hdc, 30, 30
mov hBitmap, eax
invoke SelectObject, hMemDC, hBitmap

will get to you the content of the STATIC window? No, no, no!  :naughty:
If you just want to copy the content of the DC for the static replace the above sequence with
invoke GetDC, hStc
and use returned handle in BitBlt call.

Nick

hotrod

Nick, translated you input to this. Don't know what is going on, but so far nothing has worked.

invoke BeginPaint, hWnd, addr ps
mov hdc, eax
invoke GetDC, hStc
mov stcDC, eax
invoke BitBlt, hdc, 50, 10, rect.right, rect.bottom, stcDC, 0, 0, SRCCOPY
invoke ReleaseDC, hStc, stcDC
invoke DeleteDC, hMemDC
invoke EndPaint, hWnd, addr ps
ret

qWord

here an example that works for me:

include masm32rt.inc

.data
    ClassName   db "SomeClass",0
.data?
    hMainWnd    dd ?
    hInstance   dd ?
    hStc        dd ?
    msg         MSG <>
    wc          WNDCLASSEX <>
.code
start:
    mov hInstance,rv(GetModuleHandle,NULL)
    mov wc.hInstance,eax
    mov wc.cbSize,SIZEOF WNDCLASSEX
    mov wc.style,CS_HREDRAW or CS_VREDRAW
    mov wc.lpfnWndProc,OFFSET WndProc
    mov wc.hbrBackground,rv(CreateSolidBrush,0FFFFFFh)
    mov wc.lpszClassName,OFFSET ClassName
    mov wc.hIcon,rv(LoadIcon,NULL,IDI_APPLICATION)
    mov wc.hIconSm,eax
    mov wc.hCursor,rv(LoadCursor,NULL,IDC_ARROW)

    invoke RegisterClassEx,OFFSET wc
    invoke CreateWindowEx,NULL\
                         ,OFFSET ClassName\
                         ,SADD("What ever")\
                         ,WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN\
                         ,CW_USEDEFAULT,CW_USEDEFAULT\
                         ,CW_USEDEFAULT,CW_USEDEFAULT\
                         ,NULL\
                         ,NULL\
                         ,hInstance\
                         ,NULL
    mov hMainWnd,eax
    invoke ShowWindow,hMainWnd,SW_SHOWNORMAL
    invoke UpdateWindow,hMainWnd
    invoke InvalidateRect,hMainWnd,0,1                      ; <== !!!

    .while TRUE
        invoke GetMessage,OFFSET msg,NULL,0,0
        .break .if !eax
        invoke TranslateMessage, OFFSET msg
        invoke DispatchMessage, OFFSET msg
    .endw

    invoke ExitProcess,0

WndProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL ps:PAINTSTRUCT
LOCAL rect:RECT
LOCAL hdc:DWORD
    .if uMsg == WM_DESTROY
        invoke PostQuitMessage,NULL
    .elseif uMsg == WM_CREATE
        invoke CreateWindowEx, NULL, SADD("STATIC"), NULL,WS_CHILD or WS_VISIBLE or WS_BORDER, 10, 10, 30, 30,hWnd,0, hInstance, NULL
        mov hStc, eax

    .elseif uMsg == WM_PAINT
        invoke BeginPaint, hWnd, addr ps
        mov hdc,eax
        invoke GetWindowRect, hStc, addr rect
        invoke GetWindowDC,hStc
        push eax
        invoke BitBlt, hdc, 50, 10, rect.right, rect.bottom, eax, 0, 0, SRCCOPY
        pop eax
        invoke ReleaseDC,hStc,eax
        invoke EndPaint, hWnd, addr ps
    .else
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .endif
    xor eax,eax
    ret
WndProc endp
end start

FPU in a trice: SmplMath
It's that simple!

hotrod

Thanks qWord, you have bailed me out. Hopefully I can do the same some day if I get smart enough.

hotrod

qWord, I thought your example was working, but when the window is minimized and returned, it shows the background in the rectangle.

qWord

Is there a special reason why are you copying the content of control? However, here is a solution using the WM_PRINT-message:

    .elseif uMsg == WM_PAINT
        invoke BeginPaint, hWnd, addr ps
        mov hdc,eax
               
        invoke GetWindowRect, hStc, addr rect
        mov hMemDC,rv(CreateCompatibleDC,hdc)
        mov eax,rect.left
        sub rect.right,eax
        mov eax,rect.top
        sub rect.bottom,eax       
        invoke SelectObject,hMemDC,rv(CreateCompatibleBitmap,hdc,rect.right,rect.bottom)
        invoke SendMessage,hStc,WM_PRINT,hMemDC,PRF_NONCLIENT or PRF_CLIENT or PRF_ERASEBKGND
 
        invoke BitBlt, hdc,50,10,rect.right,rect.bottom,hMemDC, 0,0, SRCCOPY
        invoke DeleteDC,hMemDC
        invoke EndPaint, hWnd, addr ps
FPU in a trice: SmplMath
It's that simple!

hotrod

Thanks qWord for being considerate. The deal is that I will have close to 50 statics and I want to make sure that they appear as a unit because of the code envolved. Otherwise, there may be some time lapse during the transfer of data. This way the statics are alread built and ready minimizing program calcualtion delays.