Vista & WinBlitz3D - clipping region problem?!

Blitz3D Forums/Blitz3D Userlibs/Vista & WinBlitz3D - clipping region problem?!

Danny(Posted 2010) [#1]
I use WinBlitz3D to create a windowed application showing a 3D scene; sometimes after I display a floating window (eg. some requester) and then close it - my 3D viewport only renders & updates *inside* the (screen) area that was previously occupied by that floating window!

The surrounding screen area is totally ignored and not 'repainted' - but inside the area I can move my pointer, draw 2D graphics, animate/drag 3D objects around, etc. everything is rendered & shown perfectly fine; but 'only' within that area!

This remains until I do something "drastically" such as move or re-size the application window, switching to another application, or do some other heavy GUI related stuff (eg. open/close another panels, windows or requesters). Sometimes a keystroke is enough to have my runtime viewport be restored to what it should be, but not always.

This only happens on Vista/Windows7, and is extremely difficult to reproduce. It happens (too) often, but not always and behaves very different per computer - and even per boot! Aero / desktop composition does seem to affect this - but not always, so disabling Aero is not the solution either. Besides making me look like a fool - this is a total show stopper ! :((

Having only limited knowledge of the win32api internals, I'm guessing that some clipping-region remains set at the position+size of the last shown (floating) window, in stead of restoring it back to the full-size of the main app window. I've tried tons of crazy stuff to try and force the main window to repaint correctly again but to no avail :(

Has anyone experienced something similar - or might have an idea how to conquer this problem??

FWIW, these are the styles I use on the main application/runtime window:
WS_CAPTION Or WS_MAXIMIZEBOX Or WS_MINIMIZEBOX Or WS_SYSMENU Or WS_THICKFRAME Or WS_CLIPCHILDREN Or WS_CLIPSIBLINGS

These are the styles I use on floating windows:
WS_CHILD or WS_VISIBLE or WS_CAPTION Or WS_POPUP Or WS_SYSMENU
WS_EX_TOOLWINDOW or WS_EX_DLGMODALFRAME

Any help greatly appreciated !!!

Danny


Kev(Posted 2010) [#2]
Hi Danny, ive not loooked at the code for some time, i will pull it out later today and see about a fix.

kev


Danny(Posted 2010) [#3]
That would be amazing Kev, thanks in advance!

D.


Danny(Posted 2010) [#4]
Hi Kev, just wondering if you had any time or luck with this one?

cheers,
Danny


Danny(Posted 2010) [#5]
Does anyone else have an idea how I can force the Blitz's runtime-window to repaint fully - as opposed to only a portion of it?

I'm really desperate to get this showstopper out of the way!

Thanks in advance,

Danny


Danny(Posted 2010) [#6]
Ok, I found out the problem is actually easier to reproduce than I thought it would be..
Check this little program and play with the DOWITHFLIP value at the start. Obviously, this requires WB3D, and you should be able to see the repaint problem manifest in TWO different ways!

Const DOWITHFLIP = True

; TRUE > First the screen will refresh as normal. But after moving or closing the floating window,
;		 the main window will only redraw where the floating window has been!!!
;
; FALSE > the main window will redraw -even though NO flip statement is given!- when you MOVE the floating window;
;			with Aero enabled: it will redraw the enture screen
;			with Aero disabled: it will redraw only the rectangle underneath the floating window (or where it has just been)

;init
Graphics3D 800,600,0,3
SetBuffer BackBuffer()
Cls

;init WinBlitz3D runtimewindow
win1 = WB3D_InitializeGUI(SystemProperty("AppHwnd"),133,154,640,480)
WB3D_SetGadgetText win1, "A Window"
win2 = WB3D_CreateWindow("Move me around the background..",300,200,200,100,win1,-2133917696)
but1 = WB3D_CreateButton("Clear BG", 50,20,100,22,win2,0)
WB3D_ShowGadget win1

If DOWITHFLIP Then WB3D_SetGadgetText win2, "Close me!"

;main loop
While Not KeyDown(1)
	;button clears screen
	If (WB3D_WaitEvent() = $401) And (WB3D_EventSource() = but1)
		Cls
		Flip
	EndIf
	;draw random ovals
	Color Rand(255),Rand(255),Rand(255)
	w = WB3D_GadgetWidth(win1)
	h = WB3D_GadgetHeight(win1)
	Oval Rand(w),Rand(h), Rand(200),Rand(200),Rand(1)

	;!!
	If DOWITHFLIP Then Flip
Wend

;release & exit
WB3D_EndGUI()
EndGraphics()
End


Note that the behavior is very system dependent, but it should behave like this on most Vista & Windows7 installations if I'm not mistaken..

The first problem is the one I experienced most often (with Flip ON) and this is what I've tried to describe in my initial post. I'm looking for a method to kick it back into repainting the entire screen - as opposed to only the small area the floating window has just been...
I've had "luck" with some solutions in some cases (forcing a resize event), but for some reason these don't always work :(

Danny


RemiD(Posted 2015) [#7]
Any solution for this problem ?

I have a similar problem, see : http://www.blitzbasic.com/Community/posts.php?topic=104741


Danny(Posted 2015) [#8]
Hi RemiD,

I haven't Read this entire thread, but it sounds like a nightmare I had a long time back... I found two rough hacks, that seem To force a window into repainting it.

NOTE: This is Not just a Vista problem! It can happen in any windows version - depending on ... many things. Hope these hacks help:
Call them when e.g. you regain focus To your app.

Function WB3D_WindowRepaint(win)
	; ensure window hasn't been closed in the meanwhile (X button)
	If Not WB3D_GadgetExists(win) Then Return 
	If Not WB3D_WindowMaximized(win)
		x = WB3D_GadgetX(win)
		y = WB3D_GadgetY(win)
		w = WB3D_GadgetWidth(win)
		h = WB3D_GadgetHeight(win)
		If y >= 0 Then WB3D_SetGadgetShape(win,x,y,w,h)
	EndIf
End Function


This one is 'more robust' but also produces a visible flicker (!) so I only use this one when e.g. After the window is resized, returning from hibernation, alt-tab, etc.

Const RDW_INVALIDATE = $0001
Const RDW_INTERNALPAINT = $0002
Const RDW_ERASE = $0004
Const RDW_VALIDATE = $0008
Const RDW_NOINTERNALPAINT = $0010
Const RDW_NOERASE = $0020
Const RDW_NOCHILDREN = $0040
Const RDW_ALLCHILDREN = $0080
Const RDW_UPDATENOW = $0100
Const RDW_ERASENOW = $0200
Const RDW_FRAME = $0400
Const RDW_NOFRAME = $0800

Function WB3D_WindowEraseAndRepaint(win)
	; msdn:	 http://msdn.microsoft.com/en-us/library/windows/desktop/dd162911%28v=vs.85%29.aspx
	; forum: http://www.blitzbasic.com/Community/posts.php?topic=32334
	; will cause a flicker! so don't use often! only on e.g. resized windows!
	;#>> Might Mav on Vista ?? check MSDN links above!
	
	; ensure window hasn't been closed in the meanwhile (X button)
	If Not WB3D_GadgetExists(win) Then Return 
	
	api_InvalidateRect(win, 0, 0)
	api_RedrawWindow(win, 0,0, RDW_INVALIDATE +RDW_ALLCHILDREN +RDW_UPDATENOW)
	api_UpdateWindow(win)
	;;--> RenderWorld here !!
	;;RenderFrame()
	Delay(1)
End Function


I really hope this helps,

Danny