Page 1 of 2

Double Buffering using uxtheme.lib?

Posted: Sat Oct 02, 2010 12:56 am
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)

Re: Double Buffering using uxtheme.lib?

Posted: Sat Oct 02, 2010 1:40 am
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

Re: Double Buffering using uxtheme.lib?

Posted: Sat Oct 02, 2010 2:09 am
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.

Re: Double Buffering using uxtheme.lib?

Posted: Sat Oct 02, 2010 10:26 am
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.

Re: Double Buffering using uxtheme.lib?

Posted: Sun Oct 03, 2010 2:47 am
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.

Re: Double Buffering using uxtheme.lib?

Posted: Sun Oct 03, 2010 11:23 am
by srod
As I say, the uxTheme library will not help with such matters, the double-buffering is for custom painting only.

Re: Double Buffering using uxtheme.lib?

Posted: Sun Oct 03, 2010 5:15 pm
by Justin
Have you tried setting the #WS_EX_COMPOSITED extended style to the main window?

Re: Double Buffering using uxtheme.lib?

Posted: Sun Oct 03, 2010 11:01 pm
by PyroStrex
I've tried it but what i get is the heaviest flicker of all.

Re: Double Buffering using uxtheme.lib?

Posted: Sun Oct 03, 2010 11:11 pm
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.

Re: Double Buffering using uxtheme.lib?

Posted: Mon Oct 04, 2010 7:22 am
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

Re: Double Buffering using uxtheme.lib?

Posted: Mon Oct 04, 2010 2:32 pm
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

Re: Double Buffering using uxtheme.lib?

Posted: Mon Oct 04, 2010 3:31 pm
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

Re: Double Buffering using uxtheme.lib?

Posted: Mon Oct 04, 2010 3:36 pm
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.

Re: Double Buffering using uxtheme.lib?

Posted: Mon Oct 04, 2010 4:30 pm
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?

Re: Double Buffering using uxtheme.lib?

Posted: Mon Oct 04, 2010 4:34 pm
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.