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
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 ;)
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
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
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
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
Thanks qWord, you have bailed me out. Hopefully I can do the same some day if I get smart enough.
qWord, I thought your example was working, but when the window is minimized and returned, it shows the background in the rectangle.
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
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.