It is currently Wed Feb 19, 2020 2:32 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Thu Mar 31, 2016 4:29 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Apr 16, 2007 3:57 am
Posts: 457
Location: Germany, NRW
Hi there,

any PB Programmer on Windows might have noticed, that a resizeable GUI will flicker like hell while resizing the Window.

DeFlicker provides you with an easy way to suppress this flicker by just adding two simple lines of code:
---------------------------------------------------------------------------------------------------------------------------------------------------------
1. In your Gadget-Resize Routine, just call 'DeFlicker_StartResize(Window#)' before your first ResizeGadget()
2. If you finished the resizing, just call 'DeFlicker_EndResize()' after your last ResizeGadget()
... Done !!!

So, that's all you have to add to your Code: (Ok, ... if we also count the XInclude-Line, you need 3 additional Lines of Code:) :wink:
Code:
XInclude "Modul_DeFlicker.pbi"
...
...
DeFlicker_StartResize(Window#)
... (Your Routine where you resize your Gadgets)
DeFlicker_EndResize()
...

DeFlicker has already been testet by several users it seems to work fine on XP, Win7, Win8.1 & Win10.

[EDIT 31.01.2020] Changed DeFlicker functions to use Macros and CompilerIF to make sure DeFlicker is only active on Windows. So you can include DeFlicker even in your crossplatform code without any need to change your code for OSX or Linux

You will find some Information about additional Functions within the Sourcecode in german language.
But because these additional functions are only needed if you have to finetune the deflickering, you may not need them at all.
Nevertheless ... if you would like to know more about these finetuning-functions and do not understand the german description, leave me a comment.

The Code does include a stress-test demo with 124 resizable Gadgets.
At the top left in the demo, you can enable or disable the 2 included 'DeFlicker'-commands with a CheckBox.
So you can easily see the difference with 'DeFlicker' and without 'DeFlicker'.

'DeFlicker' is Windows-Only, but as far as I know, Linux and OS-X do not have this flicker-problem at all.

Code:
;   Modul: DeFlicker
;   ----------------------------
;   Bei größenveränderlichen Fenstern tritt häufig (vor allem bei älteren, langsameren PCs) ein störendes
;   Flimmern auf, wenn das Fenster und die darin befindlichen Gadgets resized werden.
;   Durch DeFlicker kann man dieses Flimmern nun auf einfache Weise unterbinden.

;   Anwendung:
;   ---------------------
;   Die 'standard' Anwendung ist denkbar einfach:
;   In der Routine, in der das Resizing der Gadgets vorgenommen wird, muss vor dem ersten ResizeGadget()
;   die DeFlicker-Funktion 'StartResize(Window)' aufgerufen werden (mit Angabe der entspechenden Fensternummer).
;   Wenn alle Gadgets resized wurden, muss noch EndResize() aufgerufen werden, wodurch das Fenster und die Gadgets
;   (weitestgehend) flimmerfrei neu gezeichnet wird.

;   Hinweis:
;   ---------------------
;   Manchmal muss - um ein optimales Ergebnis zu erhalten - noch bei eingen Gadgets ein wenig Feintuning betrieben werden.
;   Wenn z.B. transparente Images verwendet werden, so sollte DeFlicker für diese Images ggfl. abgeschaltet werden um
;   keine unschönen Nebeneffekte durch nicht gelöschte Grafikreste zu erhalten (siehe 'SetGadgetDeFlicker()' oder
;   'SetGadgetTypeDeFlicker()' weiter unten).
;
;   Hierzu kann man das DeFlickern auf 4 Arten sowohl generell für eine GadgetTyp als auf für einzelne Gadgets justieren:
;   -   #DeFlicker_Full      -   der gesamte Bereich eines Gadgets wird entflimmert (sinnvoll bei allen 'normalen' rechteckigen Gadgets)
;   -   #DeFlicker_NO         -   der Bereich des Gadgets wird nicht entflimmert (sinnvoll bei allen Arten von Container- Gadgets, die weitere Gadgets enthalten)
;   -   #DeFlicker_Top16/20   -   hier werden nur die oberen 16/20 Pixel des Gadgets entflimmert (z.B. nützlich für PanelGadgets die nur in der Höhe verändert werden)
;     (oder auch Werte)         (statt der Konstanten #DeFlicker_Top16/20 kann auch die Anzahl der Pixel als Parameter übergeben
;                               werden (also z.B. '16' oder '20'. Erlaubt sind hierbei Werte von 3-999 Pixel)
;   -   #DeFlicker_Region      -   Bei #DeFlicker_Region kann ein spezieller Bereich definiert werden, der entflimmert werden soll.
;                              Dies ist z.B. zum Optimieren des Tab-Bereichs bei PanelGadgets sinnvoll.

;   Zur Verfügung stehende Funktionen:
;   ----------------------------------------
;   -   DeFlicker_StartResize(Window)                                 -   verhindert von nun an, dass das Fenster neu gezeichnet wird (s.o.)
;   -   DeFlicker_EndResize(RefreshWindow=#True)                     -   erlaubt wieder das Neuzeichnen des Fensters und zeichnet den Inhalt neu (s.o.)
;                                                                     (Hinweis: EndResize() ruft automatisch 'RefreshWindow(Window)' auf um den Fensterinhalt
;                                                                      neu zu zeichnen. Dies kann durch den optionalen Parameter (RefreshWindow=#False)
;                                                                      unterbunden werden. RefreshWindow() kann dann bei Bedarf separat aufgerufen werden.
;   -   DeFlicker_RefreshWindow(Window)                              -   zeichnet den Fensterinhalt möglichst flimmerfrei neu (s.o.)


;   -   DeFlicker_SetGadgetTypeDeFlicker(GadgetType, RefreshType)   -   setzt die standard DeFlicker-Art für einen bestimmten GadgetType
;                                                                     (#DeFlicker_Region ist hierbei nicht möglich)
;   -   DeFlicker_GetGadgetTypeDeFlicker(GadgetType)                  -   gibt die aktuell eingestellte DeFlicker-Art für einen GadgetType zurück


;   -   DeFlicker_SetGadgetDeFlicker(Gadget, RefreshType [, xPos, yPos, Width, Height])
;                                                                  -   setzt die DeFlicker-Art für ein ganz bestimmtes Gadget
;                                                                     Bei #DeFlicker_Region muss noch der Bereich definiert werden
;   -   DeFlicker_GetGadgetDeFlicker(Gadget)                        -   gibt die aktuell eingestellte DeFlicker-Art für dieses Gadget zurück


;   Anwendungsbeispiel:
;   ---------------------------------------------------------------------------------------------------------------------------
;   Am Ende dieses Codes (nach der Definition des Moduls: DeFlicker) findet Ihr ein kleines Hardcore-Beispiel mit 124 Gadgets

Macro DeFlicker_StartResize(Window)
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      DeFlicker::StartResize(Window)
   CompilerEndIf
EndMacro

Macro DeFlicker_EndResize(RefreshWindow=#True)
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      DeFlicker::EndResize(RefreshWindow)
   CompilerEndIf
EndMacro

Macro DeFlicker_RefreshWindow(Window)
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      DeFlicker::RefreshWindow(Window)
   CompilerEndIf
EndMacro

Macro SetGadgetTypeDeFlicker(GadgetType, RefreshType)
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      DeFlicker::SetGadgetTypeDeFlicker(GadgetType, RefreshType)
   CompilerEndIf
EndMacro

Macro GetGadgetTypeDeFlicker(GadgetType)
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      DeFlicker::GetGadgetTypeDeFlicker(GadgetType)
   CompilerElse
      0
   CompilerEndIf
EndMacro

Macro SetGadgetDeFlicker(Gadget, RefreshType, xPos=#PB_Ignore, yPos=#PB_Ignore, Width=#PB_Ignore, Height=#PB_Ignore)
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      DeFlicker::SetGadgetDeFlicker(Gadget, RefreshType, xPos, yPos, Width, Height)
   CompilerEndIf
EndMacro

Macro GetGadgetDeFlicker(Gadget)
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      DeFlicker::GetGadgetDeFlicker(Gadget)
   CompilerEndIf
EndMacro


#DeFlicker_NO         = 1
#DeFlicker_Region      = 2
#DeFlicker_Top16      = 16
#DeFlicker_Top20      = 20
#DeFlicker_Full      = 1000

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
   
   DeclareModule      DeFlicker
      
      Declare   StartResize(Window)
      Declare   RefreshWindow(Window)
      Declare   EndResize(RefreshWindow=#True)
      
      Declare   GetGadgetTypeDeFlicker(GadgetType)
      Declare   SetGadgetTypeDeFlicker(GadgetType, RefreshType)
      
      Declare   GetGadgetDeFlicker(Gadget)
      Declare   SetGadgetDeFlicker(Gadget, RefreshType, xPos=#PB_Ignore, yPos=#PB_Ignore, Width=#PB_Ignore, Height=#PB_Ignore)
      
   EndDeclareModule
   Module   DeFlicker
      
      EnableExplicit
      
      #DeFlicker_NO         = 1
      #DeFlicker_Region      = 2
      #DeFlicker_Top16      = 16
      #DeFlicker_Top20      = 20
      #DeFlicker_Full      = 1000
      
      Structure   GadgetDetails_Struct
         GadgetID.i
         GadgetNumber.i
         GadgetType.i
         left.l
         top.l
         right.l
         bottom.l
      EndStructure
      Structure   UserDefined_DeFlickerType_Struct
         GadgetNumber.i
         DeFlicker_Type.l
         xPos.w
         yPos.w
         Width.w
         Height.w
      EndStructure
      
      #MaxGadgetTypes = 40
      Global   Dim GadgetType_Default.l(#MaxGadgetTypes)
      Global   NewList   CallBackGadgetList.GadgetDetails_Struct()
      Global   NewList   UserDefined_DeFlickerType.UserDefined_DeFlickerType_Struct()
      Global   LastResizedWindow
      Global    DeflickerLevel
      Define   n
      
      For n = 0 To #MaxGadgetTypes
         GadgetType_Default(n) = #DeFlicker_Full                        ; Standard für alle Gadgets ist erst einmal 'Full'-Deflicker
      Next
      
      GadgetType_Default(#PB_GadgetType_Frame)      = #DeFlicker_Top16   ; Jetzt werden einige Ausnamen voreingestellt
      GadgetType_Default(#PB_GadgetType_Container)   = #DeFlicker_NO
      GadgetType_Default(#PB_GadgetType_Splitter)   = #DeFlicker_NO
      GadgetType_Default(#PB_GadgetType_Panel)      = #DeFlicker_Full
      
      Procedure   GetGadgetList_Callback(hwnd,*WinPos.POINT)            ; interne Routine - CallBack zum Ermitteln der Gadgets-Liste
         
         ; CallBack zur Erstellung einer LinkedListe mit Details zu allen Gadgets in einem Window
         
         Protected   ActPBGadget, GadgetPos.RECT
         
         ActPBGadget = GetProp_(hwnd, "PB_ID")                                    ; Gadget# des PB-Gadgets
         
         If IsGadget(ActPBGadget) And GadgetID(ActPBGadget) = hwnd               ; Checken ob die ermittelte Gadget# aus ok ist
            If AddElement(CallBackGadgetList())
               CallBackGadgetList()\GadgetID         = hwnd
               CallBackGadgetList()\GadgetNumber   = ActPBGadget
               CallBackGadgetList()\GadgetType      = GadgetType(ActPBGadget)
               GetWindowRect_(hwnd, @GadgetPos)                                             ; Desktop-Position des Gadgets ermitteln
               CallBackGadgetList()\left            = GadgetPos\left      - *WinPos\x         ; Gadgetposition auf Position im Fenster umrechnen
               CallBackGadgetList()\top            = GadgetPos\top      - *WinPos\y         ;       ''
               CallBackGadgetList()\right            = GadgetPos\right      - *WinPos\x         ;       ''
               CallBackGadgetList()\bottom         = GadgetPos\bottom   - *WinPos\y         ;       ''
            EndIf
         EndIf
         
         ProcedureReturn #True
         
      EndProcedure
      Procedure   GetGadgetList(Window, List GadgetList.GadgetDetails_Struct())   ; interne Routine zum Erstellen einer Liste mit allen Gadgets
         
         ; Ermittelt Details aller PB-Gadgets in einem Fenster und gibt diese in einer LinkedList zurück
         
         Protected   WinPos.POINT
         
         If IsWindow(Window)
            WinPos\x = WindowX(Window, #PB_Window_InnerCoordinate)   ; Window-Position ermitteln, dami diese an den CallBack übergeben werden kann
            WinPos\y = WindowY(Window, #PB_Window_InnerCoordinate)
            
            ClearList(CallBackGadgetList())                                          ; LinkedList des CallBacks löschen
            EnumChildWindows_(WindowID(Window),@GetGadgetList_Callback(),@WinPos)   ; Alle Gadgets ermitteln und per CallBack auswerten
            CopyList(CallBackGadgetList(), GadgetList())                              ; Die vom CallBack erstellte LinkedListe auf die eigentliche Liste kopieren
         Else
            Debug "Window Nr."+Str(Window)+" konnte nicht gefunden werden."
         EndIf
         
         ProcedureReturn   ListSize(GadgetList())
         
      EndProcedure
      
      Procedure   StartResize(Window)
         If IsWindow(Window)
            If DeflickerLevel = 0
               SendMessage_(WindowID(Window),#WM_SETREDRAW,#False,0)
               LastResizedWindow = Window
            EndIf
            ;          DeflickerLevel + 1
         Else
            Debug "Window Nr."+Str(Window)+" nicht gefunden."
         EndIf
      EndProcedure
      Procedure   RefreshWindow(Window)
         
         If IsWindow(Window)
            
            Protected   ps.PAINTSTRUCT
            Protected   Validate.RECT
            Protected   NewList GadgetList.GadgetDetails_Struct()
            Protected   hWnd.i = WindowID(Window)
            Protected   WinRect.rect
            Protected   ActDeFlickerType
            Protected   ClearEventLoop = #True
            
            GetGadgetList(Window, GadgetList())
            
            GetClientRect_(hWnd, @WinRect)
            InvalidateRect_(hWnd,WinRect,1)
            
            ForEach GadgetList()
               
               If GadgetList()\GadgetType = #PB_GadgetType_Panel
                  ClearEventLoop = #True
               EndIf
               
               ActDeFlickerType   = GadgetType_Default(GadgetList()\GadgetType)
               
               ForEach UserDefined_DeFlickerType()
                  If UserDefined_DeFlickerType()\GadgetNumber = GadgetList()\GadgetNumber
                     ActDeFlickerType = UserDefined_DeFlickerType()\DeFlicker_Type
                     Break
                  EndIf
               Next
               
               Select ActDeFlickerType
                     
                  Case   #DeFlicker_Full            ;   Gadget-Bereich wird komplett 'DeFlickered'
                     
                     ValidateRect_(hWnd, @GadgetList()\left)
                     
                  Case   #DeFlicker_Region
                     
                     Validate\left      = GadgetList()\left   + UserDefined_DeFlickerType()\xPos
                     Validate\top      = GadgetList()\top   + UserDefined_DeFlickerType()\yPos
                     Validate\right      = GadgetList()\left   + UserDefined_DeFlickerType()\Width
                     Validate\bottom   = GadgetList()\top   + UserDefined_DeFlickerType()\Height
                     
                  Case   #DeFlicker_Region+1 To #DeFlicker_Full-1      ;  Nur oberen Teil des Gadgets 'DeFlickern'
                     
                     Validate\left      = GadgetList()\left + 8
                     Validate\top      = GadgetList()\top
                     Validate\right      = GadgetList()\right - 8
                     Validate\bottom   = GadgetList()\top + ActDeFlickerType - 1
                     
                     If GadgetList()\GadgetType = #PB_GadgetType_Frame
                        If StartDrawing(WindowOutput(Window))
                           DrawingFont(GetGadgetFont(GadgetList()\GadgetNumber))
                           Validate\right      = GadgetList()\left + 8 + TextWidth(GetGadgetText(GadgetList()\GadgetNumber))
                           Validate\bottom   = GadgetList()\top + TextHeight(GetGadgetText(GadgetList()\GadgetNumber))
                           If Validate\right > GadgetList()\right : Validate\right = GadgetList()\right : EndIf
                           StopDrawing()
                        EndIf
                     EndIf
                     ValidateRect_(hWnd, @Validate)
                  Default
                     
                     ; No DeFlicker at all
                     
               EndSelect
               
            Next
            
            BeginPaint_(hWnd, ps.PAINTSTRUCT)
            EndPaint_(hWnd, ps.PAINTSTRUCT)
            RedrawWindow_(hWnd,#Null,#Null,#RDW_INVALIDATE);
            
            CompilerIf #PB_Compiler_Debugger         ; need this Trick to get special Gadgets refreshed (like PanelGadget)
               DisableDebugger
               If ClearEventLoop
                  While WindowEvent() : Wend
               EndIf
               EnableDebugger
            CompilerElse
               If ClearEventLoop
                  While WindowEvent() : Wend
               EndIf
            CompilerEndIf
            
         Else
            Debug "Window Nr."+Str(Window)+" nicht gefunden."
         EndIf
      EndProcedure
      Procedure   EndResize(RefreshWindow=#True)
         ;       If DeflickerLevel > 0 : DeflickerLevel - 1 : EndIf
         If DeflickerLevel = 0
            SendMessage_(WindowID(LastResizedWindow),#WM_SETREDRAW,#True,0)
            If RefreshWindow : RefreshWindow(LastResizedWindow): EndIf
         EndIf
      EndProcedure
      
      Procedure   GetGadgetTypeDeFlicker(GadgetType)
         If GadgetType >= 0 And GadgetType <= #MaxGadgetTypes
            ProcedureReturn GadgetType_Default(GadgetType)
         EndIf
      EndProcedure
      Procedure   SetGadgetTypeDeFlicker(GadgetType, RefreshType)
         If GadgetType >= 0 And GadgetType <= #MaxGadgetTypes And RefreshType >= #DeFlicker_NO And RefreshType <= #DeFlicker_Full And RefreshType <> #DeFlicker_Region
            GadgetType_Default(GadgetType) = RefreshType
            ProcedureReturn #True
         EndIf
      EndProcedure
      
      Procedure   GetGadgetDeFlicker(Gadget)
         ForEach UserDefined_DeFlickerType()
            If UserDefined_DeFlickerType()\GadgetNumber = Gadget
               ProcedureReturn UserDefined_DeFlickerType()\DeFlicker_Type
            EndIf
         Next
      EndProcedure
      Procedure   SetGadgetDeFlicker(Gadget, RefreshType, xPos=#PB_Ignore, yPos=#PB_Ignore, Width=#PB_Ignore, Height=#PB_Ignore)
         
         If IsGadget(Gadget) And RefreshType >= #DeFlicker_NO And RefreshType <= #DeFlicker_Full
            
            Repeat
               ForEach UserDefined_DeFlickerType()
                  If UserDefined_DeFlickerType()\GadgetNumber = Gadget
                     Break 2
                  EndIf
               Next
               
               AddElement(UserDefined_DeFlickerType())
            Until #True
            
            With UserDefined_DeFlickerType()
               \GadgetNumber      = Gadget
               \DeFlicker_Type   = RefreshType
               If RefreshType   = #DeFlicker_Region
                  \xPos            = xPos
                  \yPos            = yPos
                  \Width         = Width
                  \Height         = Height
               EndIf
            EndWith
            
         EndIf
         
      EndProcedure
      
   EndModule
CompilerEndIf


; ========================================================================================
; ====                        Sample-Code with 124 Gadgets                            ====
; ========================================================================================


CompilerIf #PB_Compiler_IsMainFile
   
   EnableExplicit

   #winMain = 0
   Global   DeFlicker_enabled = #True
   Global   xCount = 8, yCount = 14
   Define   n
   
   Procedure   ResizeGadgets()      ; Dies ist die BindEvent-Routine zum resizen der Gadgets
     
      Protected   x,y, ActX, ActY, ActWidth.f, ActHeight.f
      Protected   ActWinWidth = WindowWidth(#winMain), ActWinHeight = WindowHeight(#winMain)
     
      ; =============================  just call StartResize() before you resize  ============================
     
      If DeFlicker_enabled
         DeFlicker_StartResize(#winMain)
      EndIf
     
      ; ======================================================================================================
     
         
      ; Resize Button-Area
     
      ActX = 8
      ActY = 28
      ActWidth = (ActWinWidth - ActX - 300 - (xCount-1) * 5) / xCount
      ActHeight = (ActWinHeight - ActY - 13 - (yCount-1) * 5) / yCount
     
      For x = 0 To xCount - 1
         For y = 0 To yCount - 1
            ResizeGadget(30 + x + y*xCount, ActX + x * (ActWidth + 5), ActY + y * (ActHeight + 5), ActWidth, ActHeight)
         Next
      Next
     
      ResizeGadget(1, ActWinWidth - 290, 10, 280, ActWinHeight/2 - 15)
      ResizeGadget(20,ActWinWidth - 270, 35, 250, 19)
      ResizeGadget(21,ActWinWidth - 270, 55, 250, 19)
      ResizeGadget(22,ActWinWidth - 270, 75, 250, 19)
      ResizeGadget(23,ActWinWidth - 275, 98, 250, ActWinHeight/2 - 143)
      ResizeGadget(24,ActWinWidth - 275, ActWinHeight/2 - 38, 250, 25)
     
      ResizeGadget(2, ActWinWidth - 290, ActWinHeight/2 + 5, 280, ActWinHeight/2 - 15)
      ResizeGadget(10,10,10,(GadgetWidth(2)-6)/2-15, (GadgetHeight(2)-50)/2)
      ResizeGadget(11,(GadgetWidth(2)-6)/2+5,10,(GadgetWidth(2)-6)/2-15, (GadgetHeight(2)-50)/2)
      ResizeGadget(12,10,(GadgetHeight(2)-50)/2 + 20,(GadgetWidth(2)-36)/2, (GadgetHeight(2)-50)/2-10)
      ResizeGadget(13,(GadgetWidth(2)-6)/2+5,(GadgetHeight(2)-50)/2 + 20,(GadgetWidth(2)-6)/2-15, (GadgetHeight(2)-50)/2-10)
     
      ; =============  just call EndResize() when you are finished with the Gadget resizing  =================
     
      If DeFlicker_enabled
         DeFlicker_EndResize()
      EndIf
     
      ; ======================================================================================================
     
   EndProcedure
   
   Procedure   CheckBox_EnableDeFlicker()
      If IsGadget(0)
         DeFlicker_enabled = GetGadgetState(0)
      EndIf
   EndProcedure
   
   OpenWindow(#winMain,0,0,800,600,"DeFlicker Hardcore-Sample", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
   WindowBounds(#winMain, 520, 360, #PB_Default, #PB_Default)
   
   BindEvent(#PB_Event_SizeWindow, @ResizeGadgets())
   
   CheckBoxGadget(0,10,5, 150, 20, "enable DeFlicker")      ; CheckBox um
   SetGadgetState(0, DeFlicker_enabled)
   BindGadgetEvent(0, @CheckBox_EnableDeFlicker())
   
   FrameGadget(1, 10,10,10,10," iFrame ")
   OptionGadget(20,10,10,10,10,"I use PB on Windows")
   OptionGadget(21,10,10,10,10,"I use PB on Linux")
   OptionGadget(22,10,10,10,10,"I use PB on MacOS")
   EditorGadget(23,10,10,10,10, #PB_Editor_WordWrap)
   ComboBoxGadget(24,10,10,10,10)
   
   PanelGadget(2, 10,10,10,10)
   AddGadgetItem(2, -1, "Panel 1")
   ButtonGadget(10, 10,10,80,80,"do")
   ButtonGadget(11, 100,10,80,80,"re")
   ButtonGadget(12, 10,100,80,80,"mi")
   ButtonGadget(13, 100,100,80,80,"fa")
   AddGadgetItem(2, -1, "Panel 2")
   AddGadgetItem(2, -1, "Panel 3")
   CloseGadgetList()
   
   For n = 30 To 29 + xCount * yCount
      ButtonGadget(n,10,10,10,10,"Btn:"+Str(n-29))
   Next
   
   ResizeGadgets()
   
   While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
   
CompilerEndIf

If it's of some use for you or if you locate some problems, just leave a message. :wink:

_________________
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)


Last edited by PureLust on Sat Feb 01, 2020 12:57 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Thu May 26, 2016 3:36 am 
Offline
Enthusiast
Enthusiast

Joined: Thu Nov 15, 2012 11:38 pm
Posts: 118
Location: Los Angeles
Verrry nice! Interestingly, the only flicker I get is when decreasing horizontally or vertically over PB's Procedure Browser pane. :? Even more curious is the flicker is more intense with DeFlicker on. :shock: None of this happens with any other pane.

Win 7 Ultimate, PB 5.42 LTS x64


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Thu May 26, 2016 6:24 am 
Offline
Enthusiast
Enthusiast

Joined: Fri Feb 19, 2010 3:42 am
Posts: 541
You should enable the checkbox as default.

This is great!!!!!!!

Thanks a lot!!!


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Mon May 30, 2016 10:54 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Apr 16, 2007 3:57 am
Posts: 457
Location: Germany, NRW
HanPBF wrote:
This is great!!!!!!!
Thanks a lot!!!
You are welcome. :wink:

Jagermeister wrote:
..., the only flicker I get is when decreasing horizontally or vertically over PB's Procedure Browser pane. :?
What do you mean with "PB's Procedure Browser pane"? There is no Browser-Gadget in my example. Do you mean the Window, created by PB, titled "DeFlicker Hardcore-Sample"?

Jagermeister wrote:
Even more curious is the flicker is more intense with DeFlicker on. :shock:
Do you mean, it flickers more, if you check the Checkbox "enable DeFlicker" in the top-left? :shock:

Thanks and greets,
PL.

_________________
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Mon Sep 04, 2017 1:10 pm 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1905
This is working great for me, PureLust. Thank you! :)

A quick question: do these constants need to be defined twice in the code?

Can I keep the ones inside the module instead, and remove the outside ones?

Code:
#DeFlicker_NO         = 1
#DeFlicker_Region      = 2
#DeFlicker_Top16      = 16
#DeFlicker_Top20      = 20
#DeFlicker_Full      = 1000


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Tue Sep 05, 2017 2:58 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4628
Location: Lyon - France
A little bit late "May 30, 2016" :oops:
But thanks to DUDE, i have see this splendid code, missed before :oops:
Thanks for sharing 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Wed Sep 06, 2017 6:05 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Apr 16, 2007 3:57 am
Posts: 457
Location: Germany, NRW
Dude wrote:
A quick question: do these constants need to be defined twice in the code?

Can I keep the ones inside the module instead, and remove the outside ones?[/code]

Hi Dude, ... the outside ones are just for easy access, if you do not use 'UseModule'.

E.g.: Without 'UseModule' you usually need to write:
- DeFlicker::GadgetType_Default(#PB_GadgetType_Splitter) = DeFlicker::#DeFlicker_NO

Because of the outside defined constants, you can save the 'DeFlicker::'-prefix for the Constants:
- DeFlicker::GadgetType_Default(#PB_GadgetType_Splitter) = #DeFlicker_NO

So .. DeFlicker does non need the Outside constants ... it's just to save some code.

But ... you only need these constants if you are not happy with DeFlickers Result with Default-Settings and want want to tweak DeFlickers output.
So, in most cases you may not use/need them at all and can get rid of the outside once anyway. ;)


Kwai chang caine wrote:
Thanks for sharing 8)

You are welcome. :mrgreen:

_________________
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Fri Sep 08, 2017 8:26 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 14, 2011 6:07 pm
Posts: 342
Nice :D
Many thanks for sharing :D


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Sun Sep 24, 2017 7:54 am 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1905
Jagermeister wrote:
more curious is the flicker is more intense with DeFlicker on. :shock:

I noticed today I don't need DeFlicker if I use SmartWindowRefresh(win,#True) and actioning the #WM_SIZING and #WM_WINDOWPOSCHANGED messages in a callback like so:

Code:
If Message=#WM_SIZING or Message=#WM_WINDOWPOSCHANGED
  UpdateWindow_(WindowID(win))
EndIf

Doing this has removed all flicker in my specific situation.


Last edited by Dude on Sat Jan 27, 2018 8:33 am, edited 3 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Mon Jan 01, 2018 8:46 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Apr 16, 2007 3:57 am
Posts: 457
Location: Germany, NRW
Dude wrote:
Adding this simple #WM_SIZING check has removed all flicker in my specific situation.

Hi Dude, ... I've just tested your Version and it works excellent !!! Image

But whow ... I was never aware, how much SmartWindowRefresh slows down the resizing-process of a Window. :shock:

In the following test-code (it's just a conversion of the DeFlicker-Example-Window to your Version) you can enable and disable SmartWindowRefresh with the checkbox top-left.

Any idea, what SmartWindowRefresh does, that could cause such a dramatic performance dropdown?

Code:
EnableExplicit

#winMain = 0
Global   xCount = 8, yCount = 14
Define   n

Procedure   ResizeGadgets()      ; Dies ist die BindEvent-Routine zum resizen der Gadgets
   
   Protected   x,y, ActX, ActY, ActWidth.f, ActHeight.f
   Protected   ActWinWidth = WindowWidth(#winMain), ActWinHeight = WindowHeight(#winMain)
   
   ; Resize Button-Area
   
   ActX = 8
   ActY = 28
   ActWidth = (ActWinWidth - ActX - 300 - (xCount-1) * 5) / xCount
   ActHeight = (ActWinHeight - ActY - 13 - (yCount-1) * 5) / yCount
   
   For x = 0 To xCount - 1
      For y = 0 To yCount - 1
         ResizeGadget(30 + x + y*xCount, ActX + x * (ActWidth + 5), ActY + y * (ActHeight + 5), ActWidth, ActHeight)
      Next
   Next
   
   ResizeGadget(1, ActWinWidth - 290, 10, 280, ActWinHeight/2 - 15)
   ResizeGadget(20,ActWinWidth - 270, 35, 250, 19)
   ResizeGadget(21,ActWinWidth - 270, 55, 250, 19)
   ResizeGadget(22,ActWinWidth - 270, 75, 250, 19)
   ResizeGadget(23,ActWinWidth - 275, 98, 250, ActWinHeight/2 - 143)
   ResizeGadget(24,ActWinWidth - 275, ActWinHeight/2 - 38, 250, 25)
   
   ResizeGadget(2, ActWinWidth - 290, ActWinHeight/2 + 5, 280, ActWinHeight/2 - 15)
   ResizeGadget(10,10,10,(GadgetWidth(2)-6)/2-15, (GadgetHeight(2)-50)/2)
   ResizeGadget(11,(GadgetWidth(2)-6)/2+5,10,(GadgetWidth(2)-6)/2-15, (GadgetHeight(2)-50)/2)
   ResizeGadget(12,10,(GadgetHeight(2)-50)/2 + 20,(GadgetWidth(2)-36)/2, (GadgetHeight(2)-50)/2-10)
   ResizeGadget(13,(GadgetWidth(2)-6)/2+5,(GadgetHeight(2)-50)/2 + 20,(GadgetWidth(2)-6)/2-15, (GadgetHeight(2)-50)/2-10)
   
EndProcedure

Procedure MyWindowCallback(WindowID, Message, wParam, lParam)
   Protected   Result = #PB_ProcessPureBasicEvents
   
   If Message=#WM_SIZING
      UpdateWindow_(WindowID)
   EndIf
   
   ProcedureReturn Result
EndProcedure

Procedure   CheckBox_EnableSmartWindowRefresh()
   If IsGadget(0)
      SmartWindowRefresh(#winMain, GetGadgetState(0))
   EndIf
EndProcedure

OpenWindow(#winMain,0,0,800,600,"DeFlicker Hardcore-Sample", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
WindowBounds(#winMain, 520, 360, #PB_Default, #PB_Default)
SmartWindowRefresh(#winMain,#True)

BindEvent(#PB_Event_SizeWindow, @ResizeGadgets())

CheckBoxGadget(0,10,5, 150, 20, "enable SmartWindowRefresh")      ; CheckBox um
SetGadgetState(0, #True)
BindGadgetEvent(0, @CheckBox_EnableSmartWindowRefresh())

FrameGadget(1, 10,10,10,10," iFrame ")
OptionGadget(20,10,10,10,10,"I use PB on Windows")
OptionGadget(21,10,10,10,10,"I use PB on Linux")
OptionGadget(22,10,10,10,10,"I use PB on MacOS")
EditorGadget(23,10,10,10,10, #PB_Editor_WordWrap)
ComboBoxGadget(24,10,10,10,10)

PanelGadget(2, 10,10,10,10)
AddGadgetItem(2, -1, "Panel 1")
ButtonGadget(10, 10,10,80,80,"do")
ButtonGadget(11, 100,10,80,80,"re")
ButtonGadget(12, 10,100,80,80,"mi")
ButtonGadget(13, 100,100,80,80,"fa")
AddGadgetItem(2, -1, "Panel 2")
AddGadgetItem(2, -1, "Panel 3")
CloseGadgetList()

For n = 30 To 29 + xCount * yCount
   ButtonGadget(n,10,10,10,10,"Btn:"+Str(n-29))
Next

SetWindowCallback(@MyWindowCallback())   

ResizeGadgets()

While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
Ohh, ... btw: Image HAPPY NEW YEAR TO ALL OF YOU !!! :mrgreen:

_________________
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Mon Jan 01, 2018 9:46 pm 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 13893
Location: France
SmartWindowRefresh bascially create a clip region out of all sibling control, and apply it to the WM_ERASEBACKGROUND message, so the erase doesn't overwrite the controls with a solid color. So the more control you have in your root window, the worste it will perfom.


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Mon Jan 01, 2018 10:02 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Apr 16, 2007 3:57 am
Posts: 457
Location: Germany, NRW
Fred wrote:
SmartWindowRefresh bascially create a clip region out of all sibling control, and apply it to the WM_ERASEBACKGROUND message, so the erase doesn't overwrite the controls with a solid color. So the more control you have in your root window, the worste it will perfom.
Hi Fred, thanks for clarifying.
So, in theory it does the same as my Deflicker-Routine.
But instead of using Clip-Regions, I just use InvalidateRect() and ValidateRect() to exclude all controls, which seems to be much faster.

Maybe it's worth to try this method on SmartWindowRefresh and include Dudes 'UpdateWindow_(WindowID(win))' to get a fast and perfect Result?

_________________
[Dynamic-Dialogs] - create complex GUIs the easy way
[DeFlicker] - easily deflicker your resizeable Windows
[WinFX] - Window Effects (incl. 'click-through' Window)


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Mon Jan 01, 2018 10:13 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Feb 19, 2010 3:42 am
Posts: 541
Thanks for all Your work!

But: hopefully PB team does not put so much time anymore in Win32 technology.
It's 2018... :wink:

(At Xojo site they work also around that annoying flicker problem; at the moment, this IDE is not usable for windows UI projects...)

O.k., maybe I am wrong. Is Win32 still used across PB community for UI? Not only little helper tools; for big projects?


Happy New Year 2018!!!!


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Mon Jan 01, 2018 10:19 pm 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 13893
Location: France
What's the alternative to win32 ?

@PureLust, I will give it a try.


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] DeFlicker - easily deflicker resizeable Windows
PostPosted: Mon Jan 01, 2018 10:53 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Feb 19, 2010 3:42 am
Posts: 541
http://www.cplusplus.com/forum/lounge/140601/

Unfortunately no true alternative...

Styling win32 is a mess.
So, combining canvasgadget with other gadgets seems indeed best solution at the moment.

Only better would be an embeddable WebKit or other HTML engine with true PureBasic interaction.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye