When a call to SetGadgetAttribute(gadget, #PB_ScrollArea_InnerWidth, ...) or
SetGadgetAttribute(gadget, #PB_ScrollArea_InnerHeight, ...) not only changes the size of the scroll area gadget's child control, but also resets its x and y coordinates to 0,0 before scrolling.
PB internal call: MoveWindow(hwndScrChild, 0, 0, rt.right, rt.bottom, 1)
Afterwards, the internal child control scrolls.
This causes the canvas gadget to move along with them. Consequently, the canvas's mouse coordinates change, triggering continuous events.
Code: Select all
EnableExplicit
#window = 0
#window_width = 300
#window_height = 400
#window_margin = 5
#button_width = 80
#button_height = 25
#boxes_width = 200
#boxes_height = 50
#boxes_borders = 4
Enumeration; gadgets
#button
#scrollarea
#canvas
EndEnumeration
Structure boxes_list
color.l
y.i
h.i
selected.b
EndStructure
NewList boxes.boxes_list()
Define window_handle
Define vscroll_size, hscroll_size
Declare redraw_boxes()
;- procedures
Procedure resize_window()
Shared window_handle
Protected window_width, window_height
window_width = WindowWidth(#window)
window_height = WindowHeight(#window)
ResizeGadget(#scrollarea, window_width - #boxes_width - #window_margin, #window_margin, #boxes_width, window_height - #window_margin * 2)
redraw_boxes()
EndProcedure
Global PrevWndProcScrChild
Procedure WndProcScrChild(hWnd, uMsg, wParam, lParam)
If uMsg = #WM_WINDOWPOSCHANGING
Protected *wp.WINDOWPOS = lParam
If *wp
Debug "child x,y = " + *wp\x + " , " + *wp\y
EndIf
EndIf
ProcedureReturn CallWindowProc_(PrevWndProcScrChild, hWnd, uMsg, wParam, lParam)
EndProcedure
Procedure.b open_window()
Shared window_handle
Protected result.b
window_handle = OpenWindow(#window, #PB_Ignore, #PB_Ignore, #window_width, #window_height, "unlimited events", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
If window_handle
ButtonGadget(#button, 5, 5, #button_width, #button_height, "Add box")
ScrollAreaGadget(#scrollarea, 0, 0, 0, 0, 0, 0, 0, #PB_ScrollArea_BorderLess)
CanvasGadget(#canvas, 0, 0, 0, 0)
CloseGadgetList()
PrevWndProcScrChild = SetWindowLongPtr_(GetWindow_(GadgetID(#scrollarea), #GW_CHILD), #GWLP_WNDPROC, @WndProcScrChild())
WindowBounds(#window, #window_width, #window_height, #PB_Ignore, #PB_Ignore)
SmartWindowRefresh(#window, #True)
BindEvent(#PB_Event_SizeWindow, @resize_window(), #window)
result = #True
EndIf
ProcedureReturn result
EndProcedure
Procedure redraw_boxes()
Shared boxes()
Shared vscroll_size
Protected boxes_height
Protected vscroll_enabled.b
If GadgetHeight(#scrollarea) > 0
ForEach boxes()
boxes_height + #boxes_height
Next
Protected hChilld = GetWindow_(GadgetID(#scrollarea), #GW_CHILD)
If boxes_height > GadgetHeight(#scrollarea) - #boxes_borders
vscroll_enabled = #True
SetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerWidth, #boxes_width - DesktopUnscaledX(#boxes_borders) - DesktopUnscaledX(vscroll_size))
SetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerHeight, boxes_height)
ResizeGadget(#canvas, 0, 0, #boxes_width - DesktopUnscaledX(#boxes_borders) - DesktopUnscaledX(vscroll_size), boxes_height)
; Debug "REDRAW with SCROLL " + Str(ElapsedMilliseconds())
Else
SetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerWidth, #boxes_width - DesktopUnscaledX(#boxes_borders))
SetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerHeight, boxes_height)
ResizeGadget(#canvas, 0, 0, #boxes_width - DesktopUnscaledX(#boxes_borders), boxes_height)
; Debug "REDRAW " + Str(ElapsedMilliseconds())
EndIf
If StartDrawing(CanvasOutput(#canvas))
boxes_height = 0
ForEach boxes()
boxes()\y = DesktopScaledY(boxes_height)
boxes_height + #boxes_height
boxes()\h = DesktopScaledY(boxes_height) - boxes()\y
Next
ForEach boxes()
If boxes()\selected = #True
Box(0, boxes()\y, DesktopScaledX(GadgetWidth(#canvas)), boxes()\h, RGB(Red(boxes()\color) * 0.5, Green(boxes()\color) * 0.5, Blue(boxes()\color) * 0.5))
Else
Box(0, boxes()\y, DesktopScaledX(GadgetWidth(#canvas)), boxes()\h, boxes()\color)
EndIf
Next
StopDrawing()
EndIf
EndIf
EndProcedure
Procedure add_box()
Shared boxes()
AddElement(boxes())
boxes()\color = RGB(Random(255, 100), Random(255, 100), Random(255, 100))
redraw_boxes()
EndProcedure
Procedure canvas_boxes(event_type)
Shared boxes()
Protected mouse_x, mouse_y
Select event_type
Case #PB_EventType_MouseLeave
ForEach boxes()
boxes()\selected = #False
Next
redraw_boxes()
Case #PB_EventType_MouseMove
mouse_x = GetGadgetAttribute(#canvas, #PB_Canvas_MouseX)
mouse_y = GetGadgetAttribute(#canvas, #PB_Canvas_MouseY)
ForEach boxes()
If mouse_y >= boxes()\y And mouse_y <= boxes()\y + boxes()\h - 1
boxes()\selected = #True
Else
boxes()\selected = #False
EndIf
Next
redraw_boxes()
EndSelect
EndProcedure
Procedure main_loop()
Shared window_handle
Shared boxes()
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #button: add_box()
Case #canvas: canvas_boxes(EventType())
EndSelect
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
If window_handle
CloseWindow(#window)
EndIf
EndProcedure
;- main code
vscroll_size = GetSystemMetrics_(#SM_CXVSCROLL)
If open_window()
resize_window()
main_loop()
EndIf
End
......
child x,y = 0 , 0
child x,y = 0 , -3
child x,y = 0 , -4
child x,y = 0 , -7
child x,y = 0 , -8
child x,y = 0 , -11
child x,y = 0 , -13
child x,y = 0 , -16
child x,y = 0 , -17
child x,y = 0 , -20
child x,y = 0 , -21
child x,y = 0 , -25
child x,y = 0 , -28
child x,y = 0 , -30
child x,y = 0 , -32
child x,y = 0 , -34
child x,y = 0 , -37
child x,y = 0 , -38
child x,y = 0 , -41
child x,y = 0 , -42
child x,y = 0 , -45
child x,y = 0 , -47
child x,y = 0 , -51
child x,y = 0 , -54
child x,y = 0 , -55
child x,y = 0 , -58
child x,y = 0 , -59
child x,y = 0 , -62
child x,y = 0 , -63
child x,y = 0 , -66
child x,y = 0 , -68
child x,y = 0 , -71
child x,y = 0 , -72
child x,y = 0 , -75
child x,y = 0 , -76
child x,y = 0 , -79
child x,y = 0 , -80
child x,y = 0 , -83
child x,y = 0 , -85
child x,y = 0 , -87
child x,y = 0 , -89
child x,y = 0 , -92
child x,y = 0 , -93
child x,y = 0 , -96
child x,y = 0 , -97
child x,y = 0 , -100
child x,y = 0 , -102
child x,y = 0 , -104
child x,y = 0 , -106
child x,y = 0 , -109
child x,y = 0 , -110
child x,y = 0 , -110
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
child x,y = 0 , 0
child x,y = 0 , -110
......
The workaround is as follows: only set the internal width or height when the internal width or height of the scroll area gadget differs.
Code: Select all
EnableExplicit
#window = 0
#window_width = 300
#window_height = 400
#window_margin = 5
#button_width = 80
#button_height = 25
#boxes_width = 200
#boxes_height = 50
#boxes_borders = 4
Enumeration; gadgets
#button
#scrollarea
#canvas
EndEnumeration
Structure boxes_list
color.l
y.i
h.i
selected.b
EndStructure
NewList boxes.boxes_list()
Define window_handle
Define vscroll_size, hscroll_size
Declare redraw_boxes()
;- procedures
Procedure resize_window()
Shared window_handle
Protected window_width, window_height
window_width = WindowWidth(#window)
window_height = WindowHeight(#window)
ResizeGadget(#scrollarea, window_width - #boxes_width - #window_margin, #window_margin, #boxes_width, window_height - #window_margin * 2)
redraw_boxes()
EndProcedure
Procedure.b open_window()
Shared window_handle
Protected result.b
window_handle = OpenWindow(#window, #PB_Ignore, #PB_Ignore, #window_width, #window_height, "unlimited events", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
If window_handle
ButtonGadget(#button, 5, 5, #button_width, #button_height, "Add box")
ScrollAreaGadget(#scrollarea, 0, 0, 0, 0, 0, 0, #PB_ScrollArea_BorderLess)
CanvasGadget(#canvas, 0, 0, 0, 0)
CloseGadgetList()
WindowBounds(#window, #window_width, #window_height, #PB_Ignore, #PB_Ignore)
SmartWindowRefresh(#window, #True)
BindEvent(#PB_Event_SizeWindow, @resize_window(), #window)
result = #True
EndIf
ProcedureReturn result
EndProcedure
Procedure redraw_boxes()
Shared boxes()
Shared vscroll_size
Protected boxes_height
Protected vscroll_enabled.b
If GadgetHeight(#scrollarea) > 0
ForEach boxes()
boxes_height + #boxes_height
Next
If boxes_height > GadgetHeight(#scrollarea) - #boxes_borders
vscroll_enabled = #True
If GetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerWidth) <> #boxes_width - DesktopUnscaledX(#boxes_borders) - DesktopUnscaledX(vscroll_size)
SetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerWidth, #boxes_width - DesktopUnscaledX(#boxes_borders) - DesktopUnscaledX(vscroll_size))
EndIf
If GetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerHeight) <> boxes_height
SetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerHeight, boxes_height)
EndIf
ResizeGadget(#canvas, 0, 0, #boxes_width - DesktopUnscaledX(#boxes_borders) - DesktopUnscaledX(vscroll_size), boxes_height)
Debug "REDRAW with SCROLL " + Str(ElapsedMilliseconds())
Else
If GetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerWidth) <> #boxes_width - DesktopUnscaledX(#boxes_borders)
SetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerWidth, #boxes_width - DesktopUnscaledX(#boxes_borders))
EndIf
If GetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerHeight) <> boxes_height
SetGadgetAttribute(#scrollarea, #PB_ScrollArea_InnerHeight, boxes_height)
EndIf
ResizeGadget(#canvas, 0, 0, #boxes_width - DesktopUnscaledX(#boxes_borders), boxes_height)
Debug "REDRAW " + Str(ElapsedMilliseconds())
EndIf
If StartDrawing(CanvasOutput(#canvas))
boxes_height = 0
ForEach boxes()
boxes()\y = DesktopScaledY(boxes_height)
boxes_height + #boxes_height
boxes()\h = DesktopScaledY(boxes_height) - boxes()\y
Next
ForEach boxes()
If boxes()\selected = #True
Box(0, boxes()\y, DesktopScaledX(GadgetWidth(#canvas)), boxes()\h, RGB(Red(boxes()\color) * 0.5, Green(boxes()\color) * 0.5, Blue(boxes()\color) * 0.5))
Else
Box(0, boxes()\y, DesktopScaledX(GadgetWidth(#canvas)), boxes()\h, boxes()\color)
EndIf
Next
StopDrawing()
EndIf
EndIf
EndProcedure
Procedure add_box()
Shared boxes()
AddElement(boxes())
boxes()\color = RGB(Random(255, 100), Random(255, 100), Random(255, 100))
redraw_boxes()
EndProcedure
Procedure canvas_boxes(event_type)
Shared boxes()
Protected mouse_x, mouse_y
Select event_type
Case #PB_EventType_MouseLeave
ForEach boxes()
boxes()\selected = #False
Next
redraw_boxes()
Case #PB_EventType_MouseMove
mouse_x = GetGadgetAttribute(#canvas, #PB_Canvas_MouseX)
mouse_y = GetGadgetAttribute(#canvas, #PB_Canvas_MouseY)
ForEach boxes()
If mouse_y >= boxes()\y And mouse_y <= boxes()\y + boxes()\h - 1
boxes()\selected = #True
Else
boxes()\selected = #False
EndIf
Next
redraw_boxes()
EndSelect
EndProcedure
Procedure main_loop()
Shared window_handle
Shared boxes()
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #button: add_box()
Case #canvas: canvas_boxes(EventType())
EndSelect
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
If window_handle
CloseWindow(#window)
EndIf
EndProcedure
;- main code
vscroll_size = GetSystemMetrics_(#SM_CXVSCROLL)
If open_window()
resize_window()
main_loop()
EndIf
End