SplitterGadget with PanelGadget Flickering problem [Resolved]

Just starting out? Need help? Post your questions and find answers here.
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

SplitterGadget with PanelGadget Flickering problem [Resolved]

Post by tatanas »

Hi,

I read a lot of posts about flickering gadgets when resizing window but nothing to fix Panel gadget as child of a splitter gadget.

Here is a sample :

Code: Select all

Enumeration Gadgets
	#Splitter
	#listicon
	#panel
	#str1
	#str2
	#str3
	#str4
EndEnumeration

Procedure BindSplitterV()
	Static SplitterPos
	Protected Position = GetGadgetState(EventGadget())
	If SplitterPos <> Position
		SplitterPos = Position
		;UpdateWindow_(GadgetID(#listicon))
		;UpdateWindow_(GadgetID(#panel))
	EndIf
EndProcedure


OpenWindow(0, 0, 0, 400, 400, "Splitter", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
ListIconGadget(#listicon, 5, 5, 150, 200, "col1", 100)
PanelGadget(#panel, 0, 0, 200, 200)
AddGadgetItem (#panel, -1, "Panel 1")
StringGadget(#str1, 5, 5, 100, 25, "string one")
StringGadget(#str2, 5, 35, 100, 25, "string two")
StringGadget(#str3, 5, 65, 100, 25, "string three")
StringGadget(#str4, 5, 95, 100, 25, "string four")
AddGadgetItem (#panel, -1, "Panel 2")
AddGadgetItem (#panel, -1, "Panel 3")
CloseGadgetList()

SplitterGadget(#Splitter, 5, 5, 390, 390, #listicon, #panel, #PB_Splitter_Vertical)
BindGadgetEvent(#Splitter, @BindSplitterV())

; SetWindowLongPtr_(GadgetID(#Splitter), #GWL_EXSTYLE, GetWindowLongPtr_(GadgetID(#Splitter), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
; SetWindowLongPtr_(GadgetID(#Splitter), #GWL_STYLE, GetWindowLongPtr_(GadgetID(#Splitter), #GWL_STYLE) | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN)

While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
As you can see, the listicon and the columns name of the Panel are flickering when we move the splitter.
Uncommenting
UpdateWindow_(GadgetID(#listicon))
fixes the Listicon.
Uncommenting
UpdateWindow_(GadgetID(#panel))
doesn't fix the Panel.

#WS_EX_COMPOSITED and #WS_CLIPSIBLINGS | WS_CLIPCHILDREN fix the Panel flickering but some drawing problem appears with the StringGadgets.

Is there a way to fix this ?

Thanks for your time.
Last edited by tatanas on Wed May 29, 2024 7:31 am, edited 1 time in total.
Windows 10 Pro x64
PureBasic 6.20 x64
Justin
Addict
Addict
Posts: 956
Joined: Sat Apr 26, 2003 2:49 pm

Re: SplitterGadget with PanelGadget Flickering problem

Post by Justin »

The new two SetWindowLongPtr_() versions get rid of the panel flickering, here, you will have to use

Code: Select all

SetWindowLongPtr_(GadgetItemID(#panel, 0), #GWL_STYLE, GetWindowLongPtr_(GadgetItemID(#panel, 0), #GWL_STYLE) | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN)
On enery panel item.
I don't see any listicon flickering here.

Code: Select all

Enumeration Gadgets
	#Splitter
	#listicon
	#panel
	#str1
	#str2
	#str3
	#str4
EndEnumeration

Procedure BindSplitterV()
	Static SplitterPos
	Protected Position = GetGadgetState(EventGadget())
	If SplitterPos <> Position
		SplitterPos = Position
		;UpdateWindow_(GadgetID(#listicon))
		;UpdateWindow_(GadgetID(#panel))
	EndIf
EndProcedure


OpenWindow(0, 0, 0, 400, 400, "Splitter", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
; SmartWindowRefresh(0, #True)
ListIconGadget(#listicon, 5, 5, 150, 200, "col1", 100)
PanelGadget(#panel, 0, 0, 200, 200)
AddGadgetItem (#panel, -1, "Panel 1")
StringGadget(#str1, 5, 5, 100, 25, "string one")
StringGadget(#str2, 5, 35, 100, 25, "string two")
StringGadget(#str3, 5, 65, 100, 25, "string three")
StringGadget(#str4, 5, 95, 100, 25, "string four")
AddGadgetItem (#panel, -1, "Panel 2")
AddGadgetItem (#panel, -1, "Panel 3")
CloseGadgetList()

SplitterGadget(#Splitter, 5, 5, 390, 390, #listicon, #panel, #PB_Splitter_Vertical)
BindGadgetEvent(#Splitter, @BindSplitterV())

SetWindowLongPtr_(GadgetID(#panel), #GWL_EXSTYLE, GetWindowLongPtr_(GadgetID(#Splitter), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
SetWindowLongPtr_(GadgetItemID(#panel, 0), #GWL_STYLE, GetWindowLongPtr_(GadgetItemID(#panel, 0), #GWL_STYLE) | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN)

While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: SplitterGadget with PanelGadget Flickering problem

Post by tatanas »

Thank you very much. It's working.

Meanwhile, I read some explanations about the Panel Gadget which uses a static control. So I try this code and it's working fine too :

Code: Select all

SetWindowLongPtr_(GadgetID(#panel), #GWL_EXSTYLE, GetWindowLongPtr_(GadgetID(#panel), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
hStatic = FindWindowEx_(GadgetID(#panel), 0, "Static", 0)
SetWindowLong_(hStatic, #GWL_STYLE, GetWindowLong_(hStatic, #GWL_STYLE) | #WS_CLIPCHILDREN)
Windows 10 Pro x64
PureBasic 6.20 x64
Justin
Addict
Addict
Posts: 956
Joined: Sat Apr 26, 2003 2:49 pm

Re: SplitterGadget with PanelGadget Flickering problem [Resolved]

Post by Justin »

That will work too, but they introduced GadgetItemID(#panel, panelItem) for that, i think it's a better option, maybe they will change the static for another control, GadgetItemID() will always work.
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Re: SplitterGadget with PanelGadget Flickering problem

Post by boddhi »

Salut,
tatanas wrote: SetWindowLong_(hStatic, #GWL_STYLE, GetWindowLong_(hStatic, #GWL_STYLE) | #WS_CLIPCHILDREN)[/code]
If you want to ensure compatibility between x32 and x64 systems, always opt for

Code: Select all

SetWindowLongPtr_()
instead of

Code: Select all

SetWindowLong_()
:wink:
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
User avatar
ChrisR
Addict
Addict
Posts: 1484
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: SplitterGadget with PanelGadget Flickering problem

Post by ChrisR »

Justin wrote: Mon May 27, 2024 6:21 pm The new two SetWindowLongPtr_() versions get rid of the panel flickering, here, you will have to use

Code: Select all

SetWindowLongPtr_(GadgetID(#panel), #GWL_EXSTYLE, GetWindowLongPtr_(GadgetID(#Splitter), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
SetWindowLongPtr_(GadgetItemID(#panel, 0), #GWL_STYLE, GetWindowLongPtr_(GadgetItemID(#panel, 0), #GWL_STYLE) | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN)
On enery panel item.
Thanks, good to know for all GadgetItemID, it works well and without flickering with the double buffer :)
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: SplitterGadget with PanelGadget Flickering problem [Resolved]

Post by tatanas »

I didn't notice at first glance but the CPU usage is huge (25% = 1 core) as soon as #WS_EX_COMPOSITED is used !
I can't use this anti flickering fix because of that :cry:
Windows 10 Pro x64
PureBasic 6.20 x64
Justin
Addict
Addict
Posts: 956
Joined: Sat Apr 26, 2003 2:49 pm

Re: SplitterGadget with PanelGadget Flickering problem [Resolved]

Post by Justin »

You can apply the style only when the splitter is moved or the main window is resized:

Code: Select all

EnableExplicit

Enumeration Gadgets
	#Splitter
	#listicon
	#panel
	#str1
	#str2
	#str3
	#str4
EndEnumeration

Global.i g_oldTabProc

Procedure BindSplitterV()
	Static SplitterPos
	Protected Position = GetGadgetState(EventGadget())
	Debug Event()
	If SplitterPos <> Position
		SplitterPos = Position
		;UpdateWindow_(GadgetID(#listicon))
		;UpdateWindow_(GadgetID(#panel))
	EndIf
EndProcedure

Procedure.i tabProc(hwnd.i, msg.l, wparam.i, lparam.i)
	Select msg
		Case #WM_LBUTTONDOWN
			SetWindowLong_(GadgetID(#panel), #GWL_EXSTYLE, GetWindowLong_(GadgetID(#panel), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
		
		Case #WM_LBUTTONUP
			SetWindowLong_(GadgetID(#panel), #GWL_EXSTYLE, GetWindowLong_(GadgetID(#panel), #GWL_EXSTYLE) & ~#WS_EX_COMPOSITED)
	EndSelect
	
	ProcedureReturn CallWindowProc_(g_oldTabProc, hwnd, msg, wparam, lparam)
EndProcedure

Procedure mainWndProc(hwnd.i, msg.i, wparam.i, lparam.i)
	Select msg
		Case #WM_ENTERSIZEMOVE
			SetWindowLong_(GadgetID(#panel), #GWL_EXSTYLE, GetWindowLong_(GadgetID(#panel), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
	
		Case #WM_EXITSIZEMOVE
			SetWindowLong_(GadgetID(#panel), #GWL_EXSTYLE, GetWindowLong_(GadgetID(#panel), #GWL_EXSTYLE) & ~#WS_EX_COMPOSITED)
	EndSelect
	
	ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure

Procedure wndOnSize()
	ResizeGadget(#Splitter, 0, 0, WindowWidth(0), WindowHeight(0))
EndProcedure

OpenWindow(0, 0, 0, 400, 400, "Splitter", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
SetWindowCallback(@mainWndProc(), 0)
BindEvent(#PB_Event_SizeWindow, @wndOnSize())
; SmartWindowRefresh(0, #True)
ListIconGadget(#listicon, 5, 5, 150, 200, "col1", 100)
PanelGadget(#panel, 0, 0, 200, 200)
AddGadgetItem (#panel, -1, "Panel 1")
StringGadget(#str1, 5, 5, 100, 25, "string one")
StringGadget(#str2, 5, 35, 100, 25, "string two")
StringGadget(#str3, 5, 65, 100, 25, "string three")
StringGadget(#str4, 5, 95, 100, 25, "string four")
AddGadgetItem (#panel, -1, "Panel 2")
AddGadgetItem (#panel, -1, "Panel 3")
CloseGadgetList()

SplitterGadget(#Splitter, 5, 5, 390, 390, #listicon, #panel, #PB_Splitter_Vertical)
; BindGadgetEvent(#Splitter, @BindSplitterV())

g_oldTabProc = SetWindowLongPtr_(GadgetID(#Splitter), #GWLP_WNDPROC, @tabProc())
SetWindowLong_(GadgetItemID(#panel, 0), #GWL_STYLE, GetWindowLong_(GadgetItemID(#panel, 0), #GWL_STYLE) | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN)

While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: SplitterGadget with PanelGadget Flickering problem [Resolved]

Post by tatanas »

Nice trick. Thank you.
It's removing the cpu usage but the StringGadget got black background as soon as we move or resize the gui.

Do we know why the cpu usage is so high when #WS_EX_COMPOSITED is used ? Is it a bug ?
Windows 10 Pro x64
PureBasic 6.20 x64
User avatar
ChrisR
Addict
Addict
Posts: 1484
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: SplitterGadget with PanelGadget Flickering problem [Resolved]

Post by ChrisR »

Thanks for pointing out the CPU usage, around 20% here with Justin's 1st code, too bad it worked fine with just 2 SetWindowLongPtr.
The 2nd code works well here, without the string black background, it's disturbing not to have the same result.
Is there a way of degrading display performance to be able to better test for all configs?
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: SplitterGadget with PanelGadget Flickering problem [Resolved]

Post by tatanas »

It seems the String black background problem is not present in PB 6.10 (It is in 6.04. I will verify again this evening).
Is this flickering problem because of the way Purebasic is handling the Splitter or the Panel ?
Windows 10 Pro x64
PureBasic 6.20 x64
Axolotl
Addict
Addict
Posts: 872
Joined: Wed Dec 31, 2008 3:36 pm

Re: SplitterGadget with PanelGadget Flickering problem [Resolved]

Post by Axolotl »

Just my 2 cents.
I would not blame PureBasic for the flickering.
This flickering problem is also discussed in many other forums.
Mainly it was written about the same window styles and clearing the background (WM_ERASEBKGND) according to the WNDCLASS.
IMO it is the stack of controls like parent window -> child window -> child window and so on. (as you know: all controls (gadgets) are treated as windows)
The mechanism of the system cannot recognize the chain of dependencies and DoubleBuffer (WS_EX_COMPOSITED) requires more memory copies, which leads to higher CPU utilization.
My recommendation for myself: keep going and try to do better.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Post Reply