News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Window background

Started by clamicun, May 31, 2017, 03:15:13 AM

Previous topic - Next topic

clamicun

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

hutch--

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.

jj2007

<oops, Hutch gave already the correct answer; please delete my post>

clamicun

Hutch,
why must I ? ?
It works perfektly.
Only the picture vanishes on minimize.

clamicun

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.

clamicun

well
have I insulted someone ?  hutch or jj .
noone gives me a hint, why I MUST use WM_PAINT, if it works without.

avcaballero

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

hutch--

 :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.

jj2007

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.

clamicun

"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

hutch--

How to use a STATIC control for a background image.

hutch--

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.

clamicun

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.

jj2007

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)

hutch--

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 !