The MASM Forum

General => The Workshop => Topic started by: clamicun on May 31, 2017, 03:15:13 AM

Title: Window background
Post by: clamicun on May 31, 2017, 03:15:13 AM
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
Title: Re: Window background
Post by: hutch-- on May 31, 2017, 03:32:15 AM
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.
Title: Re: Window background
Post by: jj2007 on May 31, 2017, 03:56:01 AM
<oops, Hutch gave already the correct answer; please delete my post>
Title: Re: Window background
Post by: clamicun on May 31, 2017, 05:48:17 AM
Hutch,
why must I ? ?
It works perfektly.
Only the picture vanishes on minimize.
Title: Re: Window background
Post by: clamicun on May 31, 2017, 05:56:36 AM
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.
Title: Re: Window background
Post by: clamicun on June 02, 2017, 12:39:46 AM
well
have I insulted someone ?  hutch or jj .
noone gives me a hint, why I MUST use WM_PAINT, if it works without.
Title: Re: Window background
Post by: avcaballero on June 02, 2017, 01:19:08 AM
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
Title: Re: Window background
Post by: hutch-- on June 02, 2017, 01:44:58 AM
 :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.
Title: Re: Window background
Post by: jj2007 on June 02, 2017, 02:18:50 AM
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.
Title: Re: Window background
Post by: clamicun on June 02, 2017, 05:31:35 AM
"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
Title: Re: Window background
Post by: hutch-- on June 02, 2017, 05:41:50 AM
How to use a STATIC control for a background image.
Title: Re: Window background
Post by: hutch-- on June 02, 2017, 05:53:21 AM
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.
Title: Re: Window background
Post by: clamicun on June 02, 2017, 07:23:59 AM
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.
Title: Re: Window background
Post by: jj2007 on June 02, 2017, 09:09:36 AM
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)
Title: Re: Window background
Post by: hutch-- on June 02, 2017, 11:16:40 AM
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 !
Title: Re: Window background
Post by: clamicun on June 03, 2017, 12:13:17 AM
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.
Title: Re: Window background
Post by: clamicun on June 03, 2017, 12:35:35 AM
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.
Title: Re: Window background
Post by: hutch-- on June 03, 2017, 06:42:21 AM
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.
Title: Re: Window background
Post by: clamicun on June 04, 2017, 06:35:02 AM
hutch thank you,
that's exactely what my little example does (gdi+)
 
Title: Re: Window background
Post by: clamicun on June 04, 2017, 11:40:50 PM
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

Title: Re: Window background
Post by: jj2007 on June 05, 2017, 12:13:04 AM
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 ;)
Title: Re: Window background
Post by: clamicun on June 05, 2017, 12:36:21 AM
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 ?


Title: Re: Window background
Post by: jj2007 on June 05, 2017, 12:47:14 AM
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.
Title: Re: Window background
Post by: clamicun on June 05, 2017, 01:04:45 AM
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