Probably a silly question for someone who knows.
I load a bitmap as window background.
I would like to know why this background vanishes if I minimize the program.
It returns with the created background.
mov wc.hbrBackground, 1
What to do ?
;==========
include \masm32\MasmBasic\MasmBasic.inc
include \masm32\include\gdiplus.inc
includelib \masm32\lib\gdiplus.lib
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD ;Main Window
Change_Bkgr PROTO :DWORD
.data?
hInstance dd ?
main_hwnd dd ?
.data
IDM_0 equ 499
IDM_1 equ 500
IDM_2 equ 501
iCurrentMode UINT HALFTONE ;???
ClassName db "cmc",0
AppName db "Background",0
imagepath1 db "jpg1.jpg",0
imagepath2 db "jpg2.jpg",0
UnicodeFileName db MAX_PATH-1 dup(?)
StartupInfo GdiplusStartupInput <?>
.code
start:
INVOKE GetModuleHandle,NULL
mov hInstance,eax
INVOKE WinMain, hInstance,NULL,eax,SW_SHOWDEFAULT
INVOKE ExitProcess,eax
;----------
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, offset WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
m2m wc.hInstance,hInst
mov wc.hbrBackground, 1
mov wc.lpszMenuName,701
mov wc.lpszClassName,offset ClassName
INVOKE LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
INVOKE RegisterClassEx, addr wc
;---------- [Center the window] ----------
INVOKE GetSystemMetrics, SM_CXSCREEN
sub eax,640
shr eax, 1
push eax
INVOKE GetSystemMetrics, SM_CYSCREEN
sub eax,440
shr eax, 1
pop ebx
INVOKE CreateWindowEx,WS_EX_OVERLAPPEDWINDOW,offset ClassName,\
offset AppName,WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX,\
ebx,eax,640,440,NULL,NULL,hInst,NULL
mov main_hwnd,eax
INVOKE ShowWindow, main_hwnd,SW_SHOWNORMAL
INVOKE UpdateWindow, main_hwnd
.while TRUE
INVOKE GetMessage, addr msg,NULL,0,0
.BREAK .IF (!eax)
INVOKE TranslateMessage, addr msg
INVOKE DispatchMessage, addr msg
.endw
mov eax,msg.wParam
ret
WinMain endp
;================================
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.if uMsg==WM_CLOSE
INVOKE ExitProcess,0
.elseif uMsg == WM_CREATE
.elseif uMsg == WM_COMMAND
mov eax,wParam
.if eax==IDM_0
INVOKE ExitProcess,0
.elseif eax==IDM_1
INVOKE Change_Bkgr,offset imagepath1
.elseif eax==IDM_2
INVOKE Change_Bkgr,offset imagepath2
.endif
.elseif uMsg == WM_SIZE
.else
INVOKE DefWindowProc,hWnd,uMsg,wParam,lParam
.endif
ret
WndProc endp
;===========
Change_Bkgr proc picin:DWORD
LOCAL hdc:HDC
LOCAL hMemDC:HDC
LOCAL bm:BITMAP
LOCAL token:DWORD
LOCAL hBitmap:DWORD
LOCAL BmpImage:DWORD
mov eax,offset StartupInfo
mov GdiplusStartupInput.GdiplusVersion[eax],1
INVOKE GdiplusStartup,addr token,offset StartupInfo,0
invoke MultiByteToWideChar,CP_ACP,0,picin,-1,offset UnicodeFileName,MAX_PATH-1
INVOKE GdipCreateBitmapFromFile,offset UnicodeFileName,addr BmpImage
.if eax != 0
ret
.endif
INVOKE GetDC,main_hwnd
mov hdc,eax
INVOKE GdipCreateHBITMAPFromBitmap,BmpImage,addr hBitmap,0
INVOKE CreateCompatibleDC,hdc
mov hMemDC,eax
INVOKE SelectObject,eax,hBitmap
INVOKE GetObject,hBitmap,sizeof(BITMAP),addr bm
lea edx,bm
mov eax,iCurrentMode
INVOKE SetStretchBltMode,hdc,eax
INVOKE StretchBlt,hdc,0,0,630,418,hMemDC,0,0,BITMAP.bmWidth[edx],BITMAP.bmHeight[edx],SRCCOPY
INVOKE DeleteDC,hMemDC
INVOKE DeleteDC,hdc
ret
Change_Bkgr endp
;==============================
end start
You must use the WM_PAINT message to display a bitmap. Alternately you can use a static control with the bitmap style which is a lot easier to do.
<oops, Hutch gave already the correct answer; please delete my post>
Hutch,
why must I ? ?
It works perfektly.
Only the picture vanishes on minimize.
jj,
it is not the wright answer.
Ihis is from my application, where the user can load a personal backgroundwindow.
The standard is a bitmap.bmp which is loaded from resource.
I notice when I use WM_PAINt to load pictures they are "more stable" that is stay in the window on minimize.
well
have I insulted someone ? hutch or jj .
noone gives me a hint, why I MUST use WM_PAINT, if it works without.
When the client area is invalidated?
When the window is created for the first time
When the window is resized
When the function InvalidateRect is executed
There are any other situations where W7 seems to work better than in previous versions that woths to take in account, like: when the window is minimized, when other window overlaps ours, etc
:biggrin:
> noone gives me a hint, why I MUST use WM_PAINT, if it works without.
If it worked without, you would not be asking the question. Standard windows technique is to use the WM_PAINT message and draw the bitmap from there. The reason why its done this way is because any change in the window forces a redraw of the client area back to the background set in the WNDCLASSEX for CreateWindowEx().
The other and easier way is to use a STATIC control that has the bitmap style set when it's created and load the image once with STM_SETIMAGE. This does not need to be run from the WM_PAINT message as once you load it, it stays there until the app closes OR you set another image to the STATIC control.
Quote from: clamicun on June 02, 2017, 12:39:46 AMhave I insulted someone ? hutch or jj
No, definitely not, don't worry :P
It's just that the answer "use WM_PAINT" is the right one, but it took me years to accept that, so you are in
good bad company :biggrin:
Spend an hour reading a good book on WM_PAINT, it's a good investment. Petzold, for example.
"If it worked without, you would not be asking the question"
hutch,
excuse me. I didnt say,that it doesnt work. It works without WM_PAINT (check it out if you want to and have the time)
I only asked why the bitmap vanishes, when minimize is clicked and then restore.
And it restores exactely what you say:
"the background set in the WNDCLASSEX for CreateWindowEx()."
I will checkout the hint "STATIC control".
Many thanks
How to use a STATIC control for a background image.
You need to comprehend how Windows works. By default it maintains the background set in the WNDCLASSEX. It is simple to blit an image onto the screen but any change will erase it and the default background will fill the space again. This is why you must write WM_PAINT code that keeps it on the screen even when its minimised resized or overlapped by another window. Windows does not work the way you want, it works the way Windows works.
hutch,
thanks
I got you. But ...
I am trying to find a way, that the "new background" is going to be restored after restore.
For example to load the bitmap again when wParam in WM_SIZE is 0.
Quote from: clamicun on June 02, 2017, 07:23:59 AMI am trying to find a way, that the "new background" is going to be restored after restore.
"The way" is called "WM_PAINT handler":
CASE WM_PAINT
sub esp, PAINTSTRUCT ; simple way to create a structure on the stack
invoke BeginPaint, hWnd, esp
xchg eax, esi
PtDC equ esi
RGB 255, 0, 0
invoke SetTextColor, PtDC, eax
RGB 144, 255, 144
invoke SetBkColor, PtDC, eax
invoke TextOut, PtDC, 9, 9, chr$(" Menu clicked: "), 23
invoke TextOut, PtDC, 109, 9, str$(lastMenu), 3
invoke EndPaint, hWnd, esp
add esp, PAINTSTRUCT
No MasmBasic - it's pure Masm32 from \Masm32\MasmBasic\Res\MiniWinMasm32.asc 8)
Q & A format.
Q. Why do I get the feeling I wasted my time answering this question and writing an example showing how its done ?
A. That's easy, because I wasted my time answering this question and writing an example showing how its done !
hutch,
easy to answer.
Because me stupido didnt open your zipfile thinking it was the one I uploaded.
But my was chg_background.zip
Very sorry about that.
ok.
Now I understand what you meant with "Static control".
Its uncomplicated.
But seems , its working only with .bmp and thats not what I wanted, because the user can pick his own background.
The next trick is to use GDI+ to load the JPG/PNG/whatever image and convert it to BMP so you can use the standard Windows controls. I have it done in 64 bit but not 32 bit.
hutch thank you,
that's exactely what my little example does (gdi+)
Bom dia jj,
"It's just that the answer "use WM_PAINT" is the right one, but it took me years to accept that, so you are in good bad company
Spend an hour reading a good book on WM_PAINT"
I did too.
I MUST use WM_PAINT...
Here again is an example to not use WM_PAINT.
no_wmpaint.zip
Nice! Move the window with the photo slightly out of the desktop, then move it back. As written earlier, it took me years to accept WM_PAINT, so you still have a lot of time to try without ;)
jj,
obviously I don't understand the basics of WM_PAINT.
ok. I write this into my WndProc.
.elseif uMsg == WM_PAINT
INVOKE BeginPaint,main_hwnd,addr ps
mov hdc,eax
;do something ? IDM_1, IDM_2 ,IDM_3
INVOKE EndPaint,main_hwnd,addr ps
Now I have various commands in WM_COMMAND. IDM_1, IDM_2
What I have to do, to make WM_PAINT react to the command ?
Between BeginPaint and EndPaint, you typically BitBlt a bitmap to the DC that BeginPaint gave to you. Really, Petzold or the Iczelion tutorials should give you everything you need.
yes, I know
.elseif uMsg == WM_PAINT
INVOKE BeginPaint,main_hwnd,addr ps
mov hdc,eax
INVOKE Change_Bkgr,offset imagepath2,400,300,0,0
INVOKE EndPaint,main_hwnd,addr ps
The window starts with imagepath2 foto.
But I want that only after I clicked on a IDM_
And what about the other commands ?
What I do to use WM_PAINT on various tasks ?
The iczelion example I sure do know.
Does the same ... one job on startup.
ok. this migt have to do with m "problem"
If you want to repaint your client area in response to other messages, you have two choices:
Use GetDC-ReleaseDC pair and do your painting between these calls
Call InvalidateRect or UpdateWindow to invalidate the entire client area, forcing Windows to put WM_PAINT message in the message queue of your window and do your painting in WM_PAINT section