Page 2 of 3

Re: SplitterGadget with more than two gadgets

Posted: Tue Apr 30, 2024 12:11 pm
by RASHAD
Just tried chi example
It works fine with me
PB 6.1 x64 Windows 11 x64
What is your configurations ?

Re: SplitterGadget with more than two gadgets

Posted: Tue Apr 30, 2024 12:25 pm
by BarryG
Chi's example is using #PB_Event_SizeWindow, but that's not the issue. The issue is glitching when moving the splittergadget, not resizing the window.

Re: SplitterGadget with more than two gadgets

Posted: Tue Apr 30, 2024 1:57 pm
by ChrisR
Maybe try updatewindow on splitter position change

Code: Select all

Global OldProc

Procedure SplitterProc(hWnd, uMsg, wParam, lParam)
  Static SplitterPos
  
  Select uMsg
    Case #WM_NCDESTROY
      
    Case #WM_PAINT
      Protected Position = GetGadgetState(GetProp_(hWnd, "PB_ID"))
      If SplitterPos <> Position
        SplitterPos = Position
      Else
        ProcedureReturn #False
      EndIf
  EndSelect
  
  ProcedureReturn CallWindowProc_(OldProc, hWnd, uMsg, wParam, lParam)
EndProcedure
  
Procedure BindSplitterV()
  Static SplitterPos
  Protected Position = GetGadgetState(EventGadget())
  If SplitterPos <> Position
    SplitterPos = Position
    UpdateWindow_(GadgetID(0))
    UpdateWindow_(GadgetID(1))
    Debug "Vertical Splitter new position: " + Position
  Else
    Debug "Vertical Splitter Event received without position change: " + Position + " !"
  EndIf
EndProcedure

Procedure BindSplitterH()
  Static SplitterPos
  Protected Position = GetGadgetState(EventGadget())
  If SplitterPos <> Position
    SplitterPos = Position
    UpdateWindow_(GadgetID(3))
    Debug "Horizontal Splitter new position: " + Position
  Else
    Debug "Horizontal Event received without position change: " + Position + " !"
  EndIf
EndProcedure

Procedure WinResize()
  ResizeGadget(4, #PB_Ignore, #PB_Ignore, WindowWidth(0)-10, WindowHeight(0)-10)
EndProcedure

OpenWindow(0, 0, 0, 400, 400, "Splitter", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible)

ExplorerListGadget(0, 0, 0, 0, 0, GetUserDirectory(#PB_Directory_Desktop))
ExplorerListGadget(1, 0, 0, 0, 0, GetUserDirectory(#PB_Directory_Pictures))

SplitterGadget(2, 5, 5, 390, 390, 0, 1, #PB_Splitter_Vertical)
BindGadgetEvent(2, @BindSplitterV())

ExplorerListGadget(3, 0, 0, 0, 0, GetHomeDirectory())

SplitterGadget(4, 5, 5, 390, 390, 2, 3, #PB_Splitter_Separator)
BindGadgetEvent(4, @BindSplitterH())
SetGadgetState(4, 250)
; SubClass Splitter for WM_PAINT message can also help 
;OldProc = GetWindowLongPtr_(GadgetID(4), #GWLP_WNDPROC)
;SetWindowLongPtr_(GadgetID(4), #GWLP_WNDPROC, @SplitterProc())

BindEvent(#PB_Event_SizeWindow, @WinResize())

HideWindow(0, #False)
While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend

Re: SplitterGadget with more than two gadgets

Posted: Tue Apr 30, 2024 2:51 pm
by mk-soft
For me, rashad example also works without problems.
Code what changed, which OS, which PB

Re: SplitterGadget with more than two gadgets

Posted: Tue Apr 30, 2024 5:52 pm
by chi
Maybe it's because of the gadget edges? Try following code "as is" and then uncomment the 2 lines...

Code: Select all

Procedure GadResizeT()
  ResizeGadget(0, 0, 0, GadgetWidth(4)/2, GadgetHeight(4))
  ResizeGadget(1, GadgetWidth(4)/2, 0, GadgetWidth(4)/2, GadgetHeight(4))
EndProcedure

Procedure GadResizeB()
  ResizeGadget(2, 0, 0, GadgetWidth(5)/2, GadgetHeight(5))
  ResizeGadget(3, GadgetWidth(5)/2, 0, GadgetWidth(5)/2, GadgetHeight(5))
EndProcedure

Procedure WinResize()
  ResizeGadget(6, #PB_Ignore, #PB_Ignore, WindowWidth(0)-10, WindowHeight(0)-10)
EndProcedure

OpenWindow(0, 0, 0, 400, 400, "Splitter", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible)

ContainerGadget(4, 0, 0, 0, 0, #PB_Container_Flat)
  ExplorerListGadget(0, 0, 0, 0, 0, "c:\")
  ExplorerListGadget(1, 0, 0, 0, 0, "c:\temp\")
CloseGadgetList()
SetWindowLongPtr_(GadgetID(4), #GWL_STYLE, GetWindowLongPtr_(GadgetID(4), #GWL_STYLE)|#WS_CLIPCHILDREN)
; SetWindowLongPtr_(GadgetID(0), #GWL_EXSTYLE, GetWindowLongPtr_(GadgetID(0), #GWL_EXSTYLE)&~#WS_EX_CLIENTEDGE)
; SetWindowLongPtr_(GadgetID(1), #GWL_EXSTYLE, GetWindowLongPtr_(GadgetID(1), #GWL_EXSTYLE)&~#WS_EX_CLIENTEDGE)
BindGadgetEvent(4, @GadResizeT(), #PB_EventType_Resize)

ContainerGadget(5, 0, 0, 0, 0, #PB_Container_Flat)
  EditorGadget(2, 0, 0, 0, 0) : SetGadgetText(2, "c:\")
  EditorGadget(3, 0, 0, 0, 0) : SetGadgetText(3, "c:\temp\")
CloseGadgetList()
SetWindowLongPtr_(GadgetID(5), #GWL_STYLE, GetWindowLongPtr_(GadgetID(5), #GWL_STYLE)|#WS_CLIPCHILDREN)
BindGadgetEvent(5, @GadResizeB(), #PB_EventType_Resize)

SplitterGadget(6, 5, 5, 390, 390, 4, 5, #PB_Splitter_Separator)
SetWindowLongPtr_(GadgetID(6), #GWL_STYLE, GetWindowLongPtr_(GadgetID(6), #GWL_STYLE)|#WS_CLIPCHILDREN)
SetGadgetState(6, 250)
BindEvent(#PB_Event_SizeWindow, @WinResize())

HideWindow(0, #False)
While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
edit: If you comment this line: BindGadgetEvent(5, @GadResizeB(), #PB_EventType_Resize), is the problem gone?

Re: SplitterGadget with more than two gadgets

Posted: Tue Apr 30, 2024 8:11 pm
by mestnyi

Code: Select all

Procedure.i IDGadget( GadgetID.i )  ; Return the id of the gadget from the gadget handle
    If GadgetID
      Protected Gadget = GetProp_( GadgetID, "PB_ID" )
      If IsGadget( Gadget ) And GadgetID( Gadget ) = GadgetID
        ProcedureReturn Gadget
      EndIf
      ProcedureReturn - 1
    Else
      ProcedureReturn - 1
    EndIf
 EndProcedure
 Procedure GadgetsClipCallBack( GadgetID, lParam )
  ; https://www.purebasic.fr/english/viewtopic.php?t=64799
  ;
  ; Для виндовс чтобы приклепить гаджеты на место
  ; надо вызывать процедуру в конце создания всех гаджетов
  ; надо вызвать после создания всех гаджетов
  ; 
  If GadgetID
    Protected Gadget = IDGadget(GadgetID)
          
    If GetWindowLongPtr_( GadgetID, #GWL_STYLE ) & #WS_CLIPSIBLINGS = #False 
      If IsGadget( Gadget ) 
        Select GadgetType( Gadget )
          Case #PB_GadgetType_Spin
            Protected SpinNext = GetWindow_( GadgetID( gadget ), #GW_HWNDNEXT )
            SetWindowLongPtr_( SpinNext, #GWL_STYLE, GetWindowLongPtr_( SpinNext, #GWL_STYLE ) | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN )
            SetWindowPos_( SpinNext, #GW_HWNDFIRST, 0,0,0,0, #SWP_NOMOVE|#SWP_NOSIZE )
            
          Case #PB_GadgetType_Panel
           SetWindowLongPtr_( GadgetID( gadget ), #GWL_EXSTYLE, GetWindowLongPtr_( GadgetID( gadget ), #GWL_EXSTYLE ) | #WS_EX_COMPOSITED )
         Case #PB_GadgetType_ComboBox
            Protected Height = GadgetHeight( Gadget )
            
            ;             Case #PB_GadgetType_Container 
            ;             ; Из-за бага когда устанавливаешь фоновый рисунок (например точки на кантейнер)
            ;               SetGadgetColor( Gadget, #PB_Gadget_BackColor, GetSysColor_( #COLOR_BTNFACE ))
            ;               
            ;             Case #PB_GadgetType_Panel 
            ;             ; Для панел гаджета темный фон убирать
            ;               If Not IsGadget( Gadget ) And (GetWindowLongPtr_(GadgetID, #GWL_EXSTYLE) & #WS_EX_TRANSPARENT) = #False
            ;                 SetWindowLongPtr_(GadgetID, #GWL_EXSTYLE, GetWindowLongPtr_(GadgetID, #GWL_EXSTYLE) | #WS_EX_TRANSPARENT)
            ;               EndIf
            ;               ; SetClassLongPtr_(GadgetID, #GCL_HBRBACKGROUND, GetStockObject_(#NULL_BRUSH))
            
        EndSelect
      EndIf
      
      SetWindowLongPtr_( GadgetID, #GWL_STYLE, GetWindowLongPtr_( GadgetID, #GWL_STYLE ) | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN )
      
      If Height
        ResizeGadget( Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, Height )
      EndIf
      
      SetWindowPos_( GadgetID, #HWND_TOP, 0,0,0,0, #SWP_NOMOVE | #SWP_NOSIZE )
    Else
      If IsGadget( Gadget ) 
        Select GadgetType( Gadget )
          Case #PB_GadgetType_Panel
           SetWindowLongPtr_( GadgetID, #GWL_EXSTYLE, GetWindowLongPtr_( GadgetID, #GWL_EXSTYLE ) | #WS_EX_COMPOSITED )
        EndSelect
      EndIf
    EndIf
    
  EndIf
  
  ProcedureReturn GadgetID
EndProcedure
Procedure ClipGadgets( WindowID )
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    EnumChildWindows_( WindowID, @GadgetsClipCallBack(), 0 )
    SetWindowLongPtr_( WindowID, #GWL_STYLE, GetWindowLongPtr_( WindowID, #GWL_STYLE ) | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN )
    SetWindowPos_( WindowID, #HWND_TOP, 0,0,0,0, #SWP_NOMOVE|#SWP_NOSIZE )
  CompilerEndIf
EndProcedure



OpenWindow(0,0,0,400,300,"SplitterGadget",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)


ExplorerListGadget(1,0,0,200,300,"c:\") ; Top left.

EditorGadget(4,0,0,200,300) : SetGadgetText(4,"c:\") ; Bottom left.
EditorGadget(5,200,0,200,300) : SetGadgetText(5,"c:\temp\") ; Bottom right.
SplitterGadget(2,0,0,400,300,4,5,#PB_Splitter_Vertical)

SplitterGadget(6,0,0,400,300,1,2,#PB_Splitter_Separator) ; Separate the top two gadgets from the bottom two.

ClipGadgets(UseGadgetList(0))
Repeat
  EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow

Re: SplitterGadget with more than two gadgets

Posted: Wed May 01, 2024 11:27 am
by BarryG
chi wrote: Tue Apr 30, 2024 5:52 pmedit: If you comment this line: BindGadgetEvent(5, @GadResizeB(), #PB_EventType_Resize), is the problem gone?
Nope. Here's what I'm experiencing, which I'd love to avoid:

Image

BTW, I'm using PureBasic 6.10 on Windows 10 Pro, and also testing on Windows 11 Pro. Compiling as 64-bit only.

The visual glitches remain when dragging the SplitterGadget() bar, despite all code variations here to help (which I appreciate very much). But, in the end (for now anyway) I've decided to just have a little shrink/expand button between the two sets of four gadgets, and clicking it will just resize both sets of gadgets to a pre-set size instead (small/large). No glitches and an acceptable compromise.

@Fred: I wonder if there's anything you can do behind-the-scenes when the SplitterGadget() bar is being dragged?

Re: SplitterGadget with more than two gadgets

Posted: Wed May 01, 2024 11:56 am
by mk-soft
Since I myself run Window 10 Pro as a VM and do not have this problem, it must be due to your machine or graphics card.
What does your code look like?

When I pull extremely fast, I also experience this for a very short time.
So it must be due to windows and the computing power.

Code: Select all

;-TOP

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(0)
  dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
  ; Resize Gadgets
  ResizeGadget(0, 5, 5, dx - 10, dy - 10)
EndProcedure

Procedure Main()
  Protected dx, dy
  
  #WinStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 600, 400, "Test Window", #WinStyle)
    ; MenuBar
    CreateMenu(0, WindowID(0))
    MenuTitle("File")
    
    ; StatusBar
    CreateStatusBar(0, WindowID(0))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(0)
    dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
    ExplorerListGadget(1, 0, 0, 0, 0, GetUserDirectory(#PB_Directory_Documents))
    ExplorerListGadget(2, 0, 0, 0, 0, GetUserDirectory(#PB_Directory_Downloads))
    SplitterGadget(0, 5, 5, dx - 10, dy - 10, 1, 2)
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), 0)
    
    ; Main Loop
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case 0
              Break
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
            
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
              
          EndSelect
          
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()

Re: SplitterGadget with more than two gadgets

Posted: Wed May 01, 2024 12:58 pm
by BarryG
mk-soft wrote: Wed May 01, 2024 11:56 amWhat does your code look like?
That gif was from using Chi's code just above -> https://www.purebasic.fr/english/viewto ... 78#p620278
mk-soft wrote:it must be due to windows and the computing power
Damn, so it's just my crappy PCs and/or their video cards? On two different PCs? Great. :(

Re: SplitterGadget with more than two gadgets

Posted: Wed May 01, 2024 2:24 pm
by breeze4me
BarryG wrote: Wed May 01, 2024 12:58 pm Damn, so it's just my crappy PCs and/or their video cards? On two different PCs? Great. :(
In all of the above examples, not only on your PCs, but also on my PCs, I'm experiencing the issue of afterimages(trailing images) on Windows 10 Home x64.
This is especially bad when the window is maximized.
Even with subclassing to reduce flicker as much as possible, there are still some drawing issues depending on the child gadget type.
So, I tried using a container gadget to mimic a splitter gadget, but flickering and afterimages occurred there as well.
Anyway, because of this flicker and afterimage, I've been experimenting with 'DirectComposition' in my project and it seems to be working relatively well. It's just that the code has gotten longer and more complex. :lol:

Captured image with method 1 applied.
Image

Captured image with method 2 applied. (the image file size is about 1.4 megabytes.)
Image

Code: Select all

#OldWndProc$ = "OldWndProc"

Procedure WndProc_Splitter(hWnd, Message, wParam, lParam)
  Protected old = GetProp_(hWnd, #OldWndProc$)
  Protected iResult, Gadget, PrevPosXY.l
  
  Select Message
    Case #WM_LBUTTONDOWN
      Gadget = GetWindowLongPtr_(hWnd, #GWLP_ID)
      If GadgetID(Gadget) = hWnd
        SetGadgetData(Gadget, lParam)
      EndIf
      
    Case #WM_LBUTTONUP
      Gadget = GetWindowLongPtr_(hWnd, #GWLP_ID)
      If GadgetID(Gadget) = hWnd
        SetGadgetData(Gadget, -1)
      EndIf
      
    Case #WM_MOUSEMOVE
      If wParam = #MK_LBUTTON
        Gadget = GetWindowLongPtr_(hWnd, #GWLP_ID)
        If GadgetID(Gadget) = hWnd
          PrevPosXY = GetGadgetData(Gadget)
          If PrevPosXY <> lParam
            SetGadgetData(Gadget, lParam)
            
            ; Method 1
            ; Problem 1: When moving the separator on splitter gadget #4, the vertical scroll bar on gadget #0 has a slight afterimage.
            ; Problem 2: When moving the separator on splitter gadget #6, the bottom part of both editor gadgets draws slowly.
            iResult = CallWindowProc_(old, hWnd, Message, wParam, lParam)
            UpdateWindow_(hWnd)
            
            ; Method 2
            ; The problem 2 is solved, but the vertical scroll bar on gadget #0 has a bad afterimage, and the left part of gadget #1 draws slowly.
            ;SendMessage_(hWnd, #WM_SETREDRAW, 0, 0)
            ;iResult = CallWindowProc_(old, hWnd, Message, wParam, lParam)
            ;SendMessage_(hWnd, #WM_SETREDRAW, 1, 0)
            ;RedrawWindow_(hWnd, 0, 0, #RDW_ALLCHILDREN | #RDW_FRAME | #RDW_ERASE | #RDW_INVALIDATE | #RDW_UPDATENOW)
            
            ProcedureReturn iResult
          Else
            ProcedureReturn 0
          EndIf
        EndIf
      EndIf
      
    Case #WM_NCDESTROY
      RemoveProp_(hWnd, #OldWndProc$)
      
  EndSelect
  ProcedureReturn CallWindowProc_(old, hWnd, Message, wParam, lParam)
EndProcedure


Procedure WinResize()
  ResizeGadget(6, #PB_Ignore, #PB_Ignore, WindowWidth(0)-10, WindowHeight(0)-10)
EndProcedure

OpenWindow(0, 0, 0, 400, 400, "Splitter", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible)

ExplorerListGadget(0, 0, 0, 0, 0, "c:\")
SetGadgetItemAttribute(0, 0, #PB_Explorer_ColumnWidth, 800, 3)
ExplorerListGadget(1, 0, 0, 0, 0, "c:\")


EditorGadget(2, 0, 0, 0, 0) : SetGadgetText(2, "c:\")
EditorGadget(3, 0, 0, 0, 0) : SetGadgetText(3, "c:\temp\")

SplitterGadget(4, 0,   0, 400, 200, 0, 1, #PB_Splitter_Vertical)
SplitterGadget(5, 0, 200, 400, 200, 2, 3, #PB_Splitter_Vertical)

SplitterGadget(6, 5, 5, 390, 390, 4, 5, #PB_Splitter_Separator)
SetGadgetState(6, 250)


hWnd = GadgetID(4)
SetWindowLongPtr_(hWnd, #GWL_STYLE, GetWindowLongPtr_(hWnd, #GWL_STYLE) | #WS_CLIPCHILDREN)
SetProp_(hWnd, #OldWndProc$, SetWindowLongPtr_(hWnd, #GWLP_WNDPROC, @WndProc_Splitter()))

hWnd = GadgetID(5)
SetWindowLongPtr_(hWnd, #GWL_STYLE, GetWindowLongPtr_(hWnd, #GWL_STYLE) | #WS_CLIPCHILDREN)
SetProp_(hWnd, #OldWndProc$, SetWindowLongPtr_(hWnd, #GWLP_WNDPROC, @WndProc_Splitter()))

hWnd = GadgetID(6)
SetWindowLongPtr_(hWnd, #GWL_STYLE, GetWindowLongPtr_(hWnd, #GWL_STYLE) | #WS_CLIPCHILDREN)
SetProp_(hWnd, #OldWndProc$, SetWindowLongPtr_(hWnd, #GWLP_WNDPROC, @WndProc_Splitter()))

BindEvent(#PB_Event_SizeWindow, @WinResize())

HideWindow(0, #False)
SetWindowState(0, #PB_Window_Maximize)

While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend

Re: SplitterGadget with more than two gadgets

Posted: Wed May 01, 2024 4:44 pm
by ChrisR
Maybe try this one, when dragging the SplitterGadget(), the 2 Splitter child gadgets are replaced with captured images with WM_PRINT message
On left button up, the splitter's child gadgets are restored

Code: Select all

Global ResizeSplitter

Procedure BindSplitter()
  Static SplitterPos, ImgGadgetChild1, ImgChild1 = #PB_Default, ImgGadgetChild2, ImgChild2 = #PB_Default
  Protected Position, hDC
  
  Position = GetGadgetState(EventGadget())
  If Not Position = SplitterPos
    SplitterPos = Position
    SendMessage_(GadgetID(EventGadget()), #WM_SETREDRAW, #True, 0)
    
    If Not ResizeSplitter
      If ImgChild1 = #PB_Default 
        ImgChild1 = CreateImage(#PB_Any, 1, 1)
        ImgGadgetChild1 = ImageGadget(#PB_Any, 0, 0, 0, 0, 0)
      EndIf
      If ImgChild2 = #PB_Default 
        ImgChild2 = CreateImage(#PB_Any, 1, 1)
        ImgGadgetChild2 = ImageGadget(#PB_Any, 0, 0, 0, 0, 0)
      EndIf
      HideGadget(0, #True) : HideGadget(3, #True)
      SetGadgetAttribute(EventGadget(), #PB_Splitter_FirstGadget,  ImgGadgetChild1)
      SetGadgetAttribute(EventGadget(), #PB_Splitter_SecondGadget, ImgGadgetChild2)
      HideGadget(ImgGadgetChild1, #False) : HideGadget(ImgGadgetChild2, #False)
      ResizeSplitter = #True
    EndIf
    
    If GadgetWidth(ImgGadgetChild1) And GadgetHeight(ImgGadgetChild1)
      ResizeGadget(0, #PB_Ignore, #PB_Ignore, GadgetWidth(ImgGadgetChild1), GadgetHeight(ImgGadgetChild1))
      ResizeImage(ImgChild1, DesktopScaledX(GadgetWidth(ImgGadgetChild1)), DesktopScaledY(GadgetHeight(ImgGadgetChild1)))
      ResizeGadget(1, 0, 0, GadgetWidth(ImgGadgetChild1)/2, GadgetHeight(ImgGadgetChild1))
      ResizeGadget(2, GadgetWidth(1), 0, GadgetWidth(ImgGadgetChild1)-GadgetWidth(1), GadgetHeight(ImgGadgetChild1))
      hDC =  StartDrawing(ImageOutput(ImgChild1))
      If hDC
        SendMessage_(GadgetID(0), #WM_PRINT, hDC, #PRF_CHILDREN | #PRF_CLIENT | #PRF_NONCLIENT | #PRF_OWNED | #PRF_ERASEBKGND)
        StopDrawing()
      EndIf
      SetGadgetState(ImgGadgetChild1, ImageID(ImgChild1))
    Else
      SetGadgetState(ImgGadgetChild1, 0)
    EndIf
    
    If GadgetWidth(ImgGadgetChild2) And GadgetHeight(ImgGadgetChild2)
      ResizeGadget(3, #PB_Ignore, #PB_Ignore, GadgetWidth(ImgGadgetChild2), GadgetHeight(ImgGadgetChild2))
      ResizeImage(ImgChild2, DesktopScaledX(GadgetWidth(ImgGadgetChild2)), DesktopScaledY(GadgetHeight(ImgGadgetChild2)))
      ResizeGadget(4, 0, 0, GadgetWidth(ImgGadgetChild2)/2, GadgetHeight(ImgGadgetChild2))
      ResizeGadget(5, GadgetWidth(4), 0, GadgetWidth(ImgGadgetChild2)-GadgetWidth(4), GadgetHeight(ImgGadgetChild2))
      hDC =  StartDrawing(ImageOutput(ImgChild2))
      If hDC
        SendMessage_(GadgetID(3), #WM_PRINT, hDC, #PRF_CHILDREN | #PRF_CLIENT | #PRF_NONCLIENT | #PRF_OWNED | #PRF_ERASEBKGND)
        StopDrawing()
      EndIf
      SetGadgetState(ImgGadgetChild2, ImageID(ImgChild2))
    Else
      SetGadgetState(ImgGadgetChild2, 0)
    EndIf
    
    UpdateWindow_(GadgetID(EventGadget()))
  Else
    SendMessage_(GadgetID(EventGadget()), #WM_SETREDRAW, #False, 0)
    ;Debug "Event received with same Splitter position"
  EndIf
EndProcedure

Procedure WinResize()
  ResizeGadget(6, #PB_Ignore, #PB_Ignore, WindowWidth(0), WindowHeight(0))
EndProcedure

OpenWindow(0, 0, 0, 400, 300, "SplitterGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)

ContainerGadget(0, 0, 0, 400, 150)
ExplorerListGadget(1, 0, 0, 200, 150, "c:\") ; Top left.
ExplorerListGadget(2, 200, 0, 200, 150, "c:\temp\") ; Top right.
CloseGadgetList()
;SetWindowLongPtr_(GadgetID(0), #GWL_STYLE, GetWindowLongPtr_(GadgetID(0), #GWL_STYLE) | #WS_CLIPCHILDREN)

ContainerGadget(3, 0, 150, 400, 150)
EditorGadget(4, 0, 0, 200, 150) : SetGadgetText(4, "c:\") ; Bottom left.
EditorGadget(5, 200, 0, 200, 150) : SetGadgetText(5, "c:\temp\") ; Bottom right.
CloseGadgetList()
;SetWindowLongPtr_(GadgetID(3), #GWL_STYLE, GetWindowLongPtr_(GadgetID(3), #GWL_STYLE) | #WS_CLIPCHILDREN)

SplitterGadget(6, 0, 0, 400, 300, 0, 3, #PB_Splitter_Separator) ; Separate the top two gadgets from the bottom two.
BindGadgetEvent(6, @BindSplitter())

BindEvent(#PB_Event_SizeWindow, @WinResize())

Repeat
  EventID = WaitWindowEvent()
  If ResizeSplitter = #True
    ;Better here than using #WM_LBUTTONUP when an event is sent following a resize, without a left button up
    ;32768 Or $8000: the most significant bit is set. If the high-order bit is 1, the key is down, otherwise, it is up.
    If Not (GetKeyState_(#VK_LBUTTON) & 32768)
      HideGadget(GetGadgetAttribute(6, #PB_Splitter_FirstGadget),  #True)
      HideGadget(GetGadgetAttribute(6, #PB_Splitter_SecondGadget), #True)
      SetGadgetAttribute(6, #PB_Splitter_FirstGadget,  0)
      SetGadgetAttribute(6, #PB_Splitter_SecondGadget, 3)
      HideGadget(0, #False) : HideGadget(3, #False)
      SendMessage_(GadgetID(6), #WM_SETREDRAW, #True, 0)
      RedrawWindow_(GadgetID(6), #Null, #Null, #RDW_INVALIDATE | #RDW_ERASENOW | #RDW_ALLCHILDREN | #RDW_UPDATENOW)
      ResizeSplitter = #False
    EndIf
  EndIf
Until EventID = #PB_Event_CloseWindow

Re: SplitterGadget with more than two gadgets

Posted: Wed May 01, 2024 10:31 pm
by BarryG
Both breeze4me's and ChrisR's new codes above have fixed it! No glitching anymore with either version. THANK YOU! 8)

Re: SplitterGadget with more than two gadgets

Posted: Thu May 02, 2024 1:16 am
by ChrisR
BarryG wrote: Wed May 01, 2024 12:58 pm Damn, so it's just my crappy PCs and/or their video cards? On two different PCs? Great.
Your crappy PCs seem to be a racing beast, keep it, nothing better to test flickering :)
BarryG wrote: Wed May 01, 2024 11:27 am @Fred: I wonder if there's anything you can do behind-the-scenes when the SplitterGadget() bar is being dragged?
I had also requested an improvement here: Less paint & events for the SplitterGadget
I think the SplitterGadget is receiving too many messages and there are too many redraws done,
It seems to be for all mouse movements, it seems to me that it shouldn't.
For a horizontal splitter, a horizontal mouse movement should not send an event, redraws (same for Vertical)
Also, no event should be sent if the mouse position is less than the minimum Splitter position or greater than the maximum Splitter value.
I think it could be improved with a message, redraw, only if the size of 1 of the 2 child gadgets has changed.
I don't know the internals and I may be wrong, otherwise it would be good for reducing flicker.

Re: SplitterGadget with more than two gadgets

Posted: Thu May 02, 2024 6:40 am
by BarryG
Well I've got it solved with your new code above, so maybe it's not my PCs at all. Just too many SplitterGadget() events like you said.

Re: SplitterGadget with more than two gadgets

Posted: Thu May 02, 2024 3:31 pm
by chi
I wonder why ResizeGadget is so much slower than SetWindowPos...

Code: Select all

#USEWINAPI = 1

Procedure GadResizeT()
  CompilerSelect #USEWINAPI
    CompilerCase 0
      ResizeGadget(0, 0, 0, GadgetWidth(4)/2, GadgetHeight(4))
      ResizeGadget(1, GadgetWidth(4)/2, 0, GadgetWidth(4)/2, GadgetHeight(4))
    CompilerCase 1
      SetWindowPos_(GadgetID(0), 0, 0, 0, GadgetWidth(4)/2, GadgetHeight(4), #SWP_NOMOVE|#SWP_NOZORDER|#SWP_NOACTIVATE)
      SetWindowPos_(GadgetID(1), 0, GadgetWidth(4)/2, 0, GadgetWidth(4)/2, GadgetHeight(4), #SWP_NOZORDER|#SWP_NOACTIVATE)
  CompilerEndSelect
EndProcedure

Procedure GadResizeB()
  CompilerSelect #USEWINAPI
    CompilerCase 0
      ResizeGadget(2, 0, 0, GadgetWidth(5)/2, GadgetHeight(5))
      ResizeGadget(3, GadgetWidth(5)/2, 0, GadgetWidth(5)/2, GadgetHeight(5))
    CompilerCase 1
      SetWindowPos_(GadgetID(2), 0, 0, 0, GadgetWidth(5)/2, GadgetHeight(5), #SWP_NOMOVE|#SWP_NOZORDER|#SWP_NOACTIVATE)
      SetWindowPos_(GadgetID(3), 0, GadgetWidth(5)/2, 0, GadgetWidth(5)/2, GadgetHeight(5), #SWP_NOZORDER|#SWP_NOACTIVATE)
  CompilerEndSelect
EndProcedure

Procedure WinResize()
  CompilerSelect #USEWINAPI
    CompilerCase 0
      ResizeGadget(6, #PB_Ignore, #PB_Ignore, WindowWidth(0)-10, WindowHeight(0)-10)
    CompilerCase 1
      SetWindowPos_(GadgetID(6), 0, 0, 0, WindowWidth(0)-10, WindowHeight(0)-10, #SWP_NOMOVE|#SWP_NOZORDER|#SWP_NOACTIVATE)
  CompilerEndSelect
EndProcedure

OpenWindow(0, 0, 0, 750, 500, "Splitter", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible)

ContainerGadget(4, 0, 0, 0, 0)
  ExplorerListGadget(0, 0, 0, 0, 0, "c:\windows\")
  ExplorerListGadget(1, 0, 0, 0, 0, "c:\program files\")
CloseGadgetList()
SetWindowLongPtr_(GadgetID(4), #GWL_STYLE, GetWindowLongPtr_(GadgetID(4), #GWL_STYLE)|#WS_CLIPCHILDREN)
BindGadgetEvent(4, @GadResizeT(), #PB_EventType_Resize)

ContainerGadget(5, 0, 0, 0, 0)
  EditorGadget(2, 0, 0, 0, 0) : SetGadgetText(2, "c:\windows\")
  EditorGadget(3, 0, 0, 0, 0) : SetGadgetText(3, "c:\program files\")
CloseGadgetList()
SetWindowLongPtr_(GadgetID(5), #GWL_STYLE, GetWindowLongPtr_(GadgetID(5), #GWL_STYLE)|#WS_CLIPCHILDREN)
BindGadgetEvent(5, @GadResizeB(), #PB_EventType_Resize)

SplitterGadget(6, 5, 5, 390, 390, 4, 5, #PB_Splitter_Separator)
SetWindowLongPtr_(GadgetID(6), #GWL_STYLE, GetWindowLongPtr_(GadgetID(6), #GWL_STYLE)|#WS_CLIPCHILDREN)
SetGadgetState(6, 250)
BindEvent(#PB_Event_SizeWindow, @WinResize())

HideWindow(0, #False)
While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend