Double Buffering using uxtheme.lib?

Just starting out? Need help? Post your questions and find answers here.
PyroStrex
User
User
Posts: 61
Joined: Mon Mar 22, 2010 3:08 pm

Double Buffering using uxtheme.lib?

Post by PyroStrex »

like stated here:

http://www.codeguru.com/cpp/w-p/vista/a ... hp/c15709/

1. How can I do the same thing in PureBasic?.
2. Even if i can, is there any difference to the flicker?
3. Do I need to install Windows 7 SDK for this? (I'm using windows 7)
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Double Buffering using uxtheme.lib?

Post by IdeasVacuum »

1) The Code Guru example is c/c++ and looks to be using the Win API plus the 'uxtheme' lib. The API functions can be easily used by PB, as described here: http://www.purebasic.fr/english/viewtopic.php?t=10046

2) The article sounds convincing - proof of the pudding is in the eating though.

3) Apparently not, unless the 'uxtheme' is a member of the SDK.
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

You need 3 files, UxTheme.dll, UxTheme.lib, UxTheme.h
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
PyroStrex
User
User
Posts: 61
Joined: Mon Mar 22, 2010 3:08 pm

Re: Double Buffering using uxtheme.lib?

Post by PyroStrex »

Hmm.. I will see If i can make ur tips work. Actually I just wanna free all flickers in my application. I have a problem while trying to free flickers for Tab Control or PanelGadget. It is when i was changing the tab and not resize. The flicker is not on the tab (since i already found a way to free the flicker for the tabs) but when the child changing. I don't really have a problem for checkboxgadget and optiongadget but for gadget like listviewgadget (not listicongadget) or stringgadget, It really is flickering.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Double Buffering using uxtheme.lib?

Post by srod »

That library will not help with child controls, it is designed for custom painting routines which, to be honest, is easy enough to implement directly without using the uxTheme library.

When performing some custom painting all you need do is configure your painting routines to draw to an arbitrary HDC given a horizontal and vertical offset. This will allow the said routine to then render directly to the screen or to an off-screen bitmap as appropriate. If wishing to double-buffer then simply create a bitmap the exact size of the update rectangle and which is compatible with the painting DC, select it into a compatible DC and call your painting routine with the offsets of the update rectangle etc. Once done, blt this to the screen directly atop the update rectangle.

I've done this many times and it works fine. The good thing though is that this method does not require Vista or above.
I may look like a mule, but I'm not a complete ass.
PyroStrex
User
User
Posts: 61
Joined: Mon Mar 22, 2010 3:08 pm

Re: Double Buffering using uxtheme.lib?

Post by PyroStrex »

Can you give me an example to do that for panelgadget's child? I can't seem to get it work. If you mean I will not be getting flickers with vista and above.. I'm using Windows 7 Professional and still, I see a huge flicker.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Double Buffering using uxtheme.lib?

Post by srod »

As I say, the uxTheme library will not help with such matters, the double-buffering is for custom painting only.
I may look like a mule, but I'm not a complete ass.
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Double Buffering using uxtheme.lib?

Post by Justin »

Have you tried setting the #WS_EX_COMPOSITED extended style to the main window?
PyroStrex
User
User
Posts: 61
Joined: Mon Mar 22, 2010 3:08 pm

Re: Double Buffering using uxtheme.lib?

Post by PyroStrex »

I've tried it but what i get is the heaviest flicker of all.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Re: Double Buffering using uxtheme.lib?

Post by Fluid Byte »

Hmm.. I will see If i can make ur tips work. Actually I just wanna free all flickers in my application. I have a problem while trying to free flickers for Tab Control or PanelGadget.
Got any source code? Using #WS_CLIPCHILDREN / #WS_CLIPSIBLINGS can help reducing the flicker drasticly.
In fact, I was able to fix even the nastiest flickering caused by dozens of nested windows.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
PyroStrex
User
User
Posts: 61
Joined: Mon Mar 22, 2010 3:08 pm

Re: Double Buffering using uxtheme.lib?

Post by PyroStrex »

I don't know.. I don't have any flickers when I didn't use PanelGadget. But here is my source code for the demonstration.

Code: Select all

Enumeration
  #Str1
  #Str2
  
  #Panel1
  #Str3
  #Str4
EndEnumeration

If OpenWindow(0, 0, 0, 200, 200, "Flicker Free Test", #PB_Window_SizeGadget | #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #WS_CLIPCHILDREN)
  ;Making huge flicker to the PanelGadget
  ;SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
  
  StringGadget(#Str1, 5, 5, 190, 20, "")
  StringGadget(#Str2, 5, 30, 190, 20, "")
  
  PanelGadget(#Panel1, 5, 55, 192, 140)
  AddGadgetItem(#Panel1, -1, "Tab 01")
  StringGadget(#Str3, 5, 5, 172, 20, "")
  StringGadget(#Str4, 5, 30, 172, 20, "")
  AddGadgetItem(#Panel1, -1, "Tab 02")
  CloseGadgetList()
  
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Gadget
        EventGadget = EventGadget()
        EventType = EventType()
      Case #PB_Event_SizeWindow
        ResizeGadget(#Str1, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 10, #PB_Ignore)
        ResizeGadget(#Str2, #PB_Ignore, #PB_Ignore, GadgetWidth(#Str1), #PB_Ignore)
        ResizeGadget(#Panel1, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 8, WindowHeight(0) - GadgetY(#Panel1) - 5)
        ResizeGadget(#Str3, #PB_Ignore, #PB_Ignore, GadgetWidth(#Panel1) - 18, #PB_Ignore)
        ResizeGadget(#Str4, #PB_Ignore, #PB_Ignore, GadgetWidth(#Str3), #PB_Ignore)
      Case #PB_Event_CloseWindow
        EventWindow = EventWindow()
        If EventWindow = 0
          CloseWindow(0)
          Break
        EndIf
    EndSelect
  ForEver
EndIf
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Double Buffering using uxtheme.lib?

Post by Justin »

Strange, here on xp #WS_EX_COMPOSITED produces zero flickering but the string gadgets appear disabled.
Anyway, the problem is the static control the panel uses as a container, setting #WS_CLIPCHILDREN to it seems to fix it, also #WS_CLIPSIBLINGS is needed to its childs.
This code removes the flickering on xp, although the tab items flicker a little, you can't avoid that.

Code: Select all

Enumeration
  #Str1
  #Str2
  
  #Panel1
  #Str3
  #Str4
EndEnumeration

procedure EnumChilds(hwnd.i, param.i)
	SetWindowLongPtr_(hwnd, #GWL_STYLE, GetWindowLongPtr_(hwnd, #GWL_STYLE) | #WS_CLIPCHILDREN)

	procedurereturn #true
endprocedure 

If OpenWindow(0, 0, 0, 200, 200, "Flicker Free Test", #PB_Window_SizeGadget | #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #WS_CLIPCHILDREN)
  ;Making huge flicker to the PanelGadget
  ;SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
  
  StringGadget(#Str1, 5, 5, 190, 20, "", #WS_CLIPSIBLINGS)
  StringGadget(#Str2, 5, 30, 190, 20, "", #WS_CLIPSIBLINGS)
  
  PanelGadget(#Panel1, 5, 55, 192, 140)
  AddGadgetItem(#Panel1, -1, "Tab 01")
  StringGadget(#Str3, 5, 5, 172, 20, "", #WS_CLIPSIBLINGS)
  StringGadget(#Str4, 5, 30, 172, 20, "", #WS_CLIPSIBLINGS)
  AddGadgetItem(#Panel1, -1, "Tab 02")
  CloseGadgetList()

	;Set #WS_CLIPCHILDREN to the panel and its childrens, only the statics are necessary i guess
	SetWindowLongPtr_(GadgetID(#Panel1), #GWL_STYLE, GetWindowLongPtr_(GadgetID(#Panel1), #GWL_STYLE) | #WS_CLIPCHILDREN)
	EnumChildWindows_(GadgetID(#Panel1), @EnumChilds(), 0)
  
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Gadget
        EventGadget = EventGadget()
        EventType = EventType()
      Case #PB_Event_SizeWindow
        ResizeGadget(#Str1, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 10, #PB_Ignore)
        ResizeGadget(#Str2, #PB_Ignore, #PB_Ignore, GadgetWidth(#Str1), #PB_Ignore)
        ResizeGadget(#Panel1, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 8, WindowHeight(0) - GadgetY(#Panel1) - 5)
        ResizeGadget(#Str3, #PB_Ignore, #PB_Ignore, GadgetWidth(#Panel1) - 18, #PB_Ignore)
        ResizeGadget(#Str4, #PB_Ignore, #PB_Ignore, GadgetWidth(#Str3), #PB_Ignore)
      Case #PB_Event_CloseWindow
        EventWindow = EventWindow()
        If EventWindow = 0
          CloseWindow(0)
          Break
        EndIf
    EndSelect
  ForEver
EndIf
PyroStrex
User
User
Posts: 61
Joined: Mon Mar 22, 2010 3:08 pm

Re: Double Buffering using uxtheme.lib?

Post by PyroStrex »

Here is the latest code which reduce the flicker and thanks to you Justin, no more flicker to the controls inside the PanelGadget. But, one last thing, The Tab doesn't flick when the tab was changed (The control is). But when resized, the tab is flicking again. Any way to prevent it?

Code: Select all

Enumeration
  #Str1
  #Str2
  
  #Panel1
  #Str3
  #Str4
  #Str5
  #Str6
EndEnumeration

Global Panel1OldProcedure = #Null

Procedure PanelMainCallBack(hWnd, uMsg, wparam, lparam)
  Protected ps.PAINTSTRUCT

  Select uMsg
    Case #WM_ERASEBKGND
      ProcedureReturn 1
    Case #WM_PAINT
      If wparam 
        ProcedureReturn CallWindowProc_(PanelMainOldProcedure, hWnd, uMsg, wparam, lparam)
      EndIf            
      hdc = BeginPaint_(hWnd, ps)
      memDC = CreateCompatibleDC_(hdc)
      hBMP = CreateCompatibleBitmap_(hdc, ps\rcPaint\right, ps\rcPaint\bottom)
      hOldBMP = SelectObject_(memDC, hBMP)

      CallWindowProc_(Panel1OldProcedure, hWnd, #WM_ERASEBKGND, memDC, 0)
      CallWindowProc_(Panel1OldProcedure, hWnd, #WM_PRINT, memDC, #PRF_CLIENT)

      BitBlt_(hdc, ps\rcPaint\left, ps\rcPaint\top, ps\rcPaint\right, ps\rcPaint\bottom, memDC, ps\rcPaint\left, ps\rcPaint\top, #SRCCOPY)
        
      ;Cleanup  
      SelectObject_(memDC, hOldBMP)        
      DeleteObject_(hBMP)
      DeleteDC_(memDC)
        
      EndPaint_(hwin, ps)
      ProcedureReturn 0
    Default
      ProcedureReturn CallWindowProc_(Panel1OldProcedure, hWnd, uMsg, wparam, lparam) 
  EndSelect 
EndProcedure

Procedure EnumChilds(hwnd.i, param.i)
   SetWindowLongPtr_(hwnd, #GWL_STYLE, GetWindowLongPtr_(hwnd, #GWL_STYLE) | #WS_CLIPCHILDREN)

   ProcedureReturn #True
EndProcedure 

If OpenWindow(0, 0, 0, 200, 200, "Flicker Free Test", #PB_Window_SizeGadget | #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #WS_CLIPCHILDREN)
  ;Making huge flicker to the PanelGadget
  ;SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE) | #WS_EX_COMPOSITED)
  
  StringGadget(#Str1, 5, 5, 190, 20, "", #WS_CLIPSIBLINGS)
  StringGadget(#Str2, 5, 30, 190, 20, "", #WS_CLIPSIBLINGS)
  
  PanelGadget(#Panel1, 5, 55, 192, 140)
  AddGadgetItem(#Panel1, -1, "Tab 01")
  StringGadget(#Str3, 5, 5, 172, 20, "", #WS_CLIPSIBLINGS)
  StringGadget(#Str4, 5, 30, 172, 20, "", #WS_CLIPSIBLINGS)
  AddGadgetItem(#Panel1, -1, "Tab 02")
  StringGadget(#Str5, 5, 5, 172, 20, "", #WS_CLIPSIBLINGS)
  StringGadget(#Str6, 5, 30, 172, 20, "", #WS_CLIPSIBLINGS)
  CloseGadgetList()

   ;Set #WS_CLIPCHILDREN to the panel and its childrens, only the statics are necessary i guess
   SetWindowLongPtr_(GadgetID(#Panel1), #GWL_STYLE, GetWindowLongPtr_(GadgetID(#Panel1), #GWL_STYLE) | #WS_CLIPCHILDREN)
   EnumChildWindows_(GadgetID(#Panel1), @EnumChilds(), 0)
   
   Panel1OldProcedure = SetWindowLongPtr_(GadgetID(#Panel1), #GWLP_WNDPROC, @PanelMainCallBack())
   
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Gadget
        EventGadget = EventGadget()
        EventType = EventType()
      Case #PB_Event_SizeWindow
        ResizeGadget(#Str1, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 10, #PB_Ignore)
        ResizeGadget(#Str2, #PB_Ignore, #PB_Ignore, GadgetWidth(#Str1), #PB_Ignore)
        ResizeGadget(#Panel1, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 8, WindowHeight(0) - GadgetY(#Panel1) - 5)
        ResizeGadget(#Str3, #PB_Ignore, #PB_Ignore, GadgetWidth(#Panel1) - 18, #PB_Ignore)
        ResizeGadget(#Str4, #PB_Ignore, #PB_Ignore, GadgetWidth(#Str3), #PB_Ignore)
        ResizeGadget(#Str5, #PB_Ignore, #PB_Ignore, GadgetWidth(#Panel1) - 18, #PB_Ignore)
        ResizeGadget(#Str6, #PB_Ignore, #PB_Ignore, GadgetWidth(#Str5), #PB_Ignore)
      Case #PB_Event_CloseWindow
        EventWindow = EventWindow()
        If EventWindow = 0
          CloseWindow(0)
          Break
        EndIf
    EndSelect
  ForEver
EndIf
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Double Buffering using uxtheme.lib?

Post by srod »

With XP themes enabled the panels are not filled correctly here because of the #WS_CLIPCHILDREN style. They appear greyed when they should be themed.

It is a style which must be used with care.
I may look like a mule, but I'm not a complete ass.
PyroStrex
User
User
Posts: 61
Joined: Mon Mar 22, 2010 3:08 pm

Re: Double Buffering using uxtheme.lib?

Post by PyroStrex »

Did you mean about the tab is not filled with white background but instead was filled with the backcolor of the window? If yes, then I also noticed the same thing. So, do you have any workaround for this case?
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Double Buffering using uxtheme.lib?

Post by srod »

Not the tab no, the panel (unless you are confusing tabs with panels? :) )

Workaround... don't resize the panel gadget until after the user has finished resizing the window (use a callback and look out for the #WM_EXITSIZEMOVE message).

I have managed to reduce flicker with panels by employing some custom erasing, but that can be a bit fiddly. Styles such as #WS_EX_COMPOSITED just do not seem to work correctly and cause more problems than they solve etc. Themed panels are a right pain when it comes to flicker.
I may look like a mule, but I'm not a complete ass.
Post Reply