Your latest Version does not flicker (because of SmartWindowRefresh()), but is has a lot of redraw-issues when you resize the Window quickly.
As I recommended before - try DeFlicker.
I've included the DeFlicker-Module into your test-code, so you will have a full working version to see the difference.
Code: Select all
#DeFlicker_NO = 1
#DeFlicker_Region = 2
#DeFlicker_Top16 = 16
#DeFlicker_Top20 = 20
#DeFlicker_Full = 1000
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
#Enable_DeFlicker = 1 ; <====================== Switch DeFlicker ON or OFF
#EnablePanel=1 ; If set to 1, it makes ListIconGadget #2 flicker badly when window is resized vertically!
OpenWindow(0, 200, 200, 230, 180, "SplitterGadget", #PB_Window_SystemMenu | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
CreateStatusBar(0,WindowID(0))
CompilerIf #EnablePanel=1
PanelGadget(0, 10, 10, 210, 160)
AddGadgetItem(0,-1,"Tab 1")
CompilerEndIf
ListIconGadget(1, 10, 10, 200, 150, "1", 200)
For i=1 To 100
AddGadgetItem(1, -1, Str(i))
Next
ListIconGadget(2, 10, 10, 200, 150, "2", 200)
For i=1 To 100
AddGadgetItem(2, -1, Str(i))
Next
SplitterGadget(3, 10, 10, 180, 110, 1, 2, #PB_Splitter_Vertical | #PB_Splitter_Separator | #PB_Splitter_FirstFixed)
CompilerIf #EnablePanel=1
AddGadgetItem(0,-1,"Tab 2")
CloseGadgetList()
CompilerEndIf
Procedure ResizeApp()
appx=WindowX(0)
appy=WindowY(0)
appw=WindowWidth(0)
apph=WindowHeight(0)
If #Enable_DeFlicker : DeFlicker::StartResize(0) : EndIf ; <====================== Begin DeFlicker
CompilerIf #EnablePanel=1
ResizeGadget(0,#PB_Ignore,#PB_Ignore,appw-20,apph-40)
CompilerEndIf
ResizeGadget(3,#PB_Ignore,#PB_Ignore,appw-45,apph-90)
If #Enable_DeFlicker : DeFlicker::EndResize() : EndIf ; <====================== End-DeFlicker
EndProcedure
Procedure Callback(hWnd,Message,wParam,lParam)
result=#PB_ProcessPureBasicEvents
If Message=#WM_WINDOWPOSCHANGED
ResizeApp()
EndIf
ProcedureReturn result
EndProcedure
SetWindowCallback(@Callback())
ResizeApp() ; Set initial size.
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow