great! Now, some hints – make it scroll on mouse wheel, and on drag any button – up and down – if pressed only – not releasing, but dragging.
Of course this is not required, but I want to tell you that you have made not possible – possible!
I will now www.go2bed.com – it’s too late over here!
you need to catch the jump error when trying to drag the scroll bar down when the window is large enough not to need a scroll bar.
Yup. I know. Still work on label location when manually change form size. In the next update I will fix that
I fixed issue with scrollbar.
To do next:
#1. Drag – slide using Middle Mouse Button (MMB) over buttons
#2. Scroll Up/Down using Mouse wheel over buttons
Any example or suggestion?
try(form.close()) catch()
(
mapped fn setLifetimeControl control = dotnet.setLifetimeControl control #dotnet
fn maxHW = (dotNetObject "maxCustomControls.win32HandleWrapper" (dotNetObject "System.IntPtr" (windows.getMaxHWND())))
fn defColor r g b = ((dotNetClass "System.Drawing.Color").FromArgb r g b)
fn defSize w h = (dotNetObject "System.Drawing.Size" w h)
fn defPoint x y = (dotNetObject "System.Drawing.Point" x y)
fn defRect x y w h = (dotNetObject "System.Drawing.Rectangle" x y w h)
-->>> main form
global form = dotnetobject "Form"
form.Icon = (dotNetClass "ManagedServices.AppSDK").GetMainApplicationIcon()
form.FormBorderStyle = form.FormBorderStyle.SizableToolWindow
form.StartPosition = form.StartPosition.Manual
form.Text = "vScrollTest" ; form.ShowInTaskbar = off
form.BackColor = defColor 150 20 20 ; form.DockPadding.All = 2
form.MaximumSize = defSize 185 500
form.MinimumSize = defSize 185 103
form.Bounds = defRect 10 110 185 284
-->>> main container
mainUC = dotnetobject "UserControl"
mainUC.Backcolor = defColor 40 40 40
mainUC.Dock = mainUC.Dock.Fill
-->>> scroll container
scrollUC = dotnetobject "UserControl"
scrollUC.Backcolor = defColor 40 40 40
scrollUC.width = 6 ; scrollUC.tag = 0
scrollUC.Dock = scrollUC.Dock.Right
-->>> scrollbar
global scrollBar = dotnetobject "Label"
scrollBar.Backcolor = defColor 51 175 235
scrollBar.width = 6
-->>> button container
global cc = dotnetobject "Label"
cc.location = defPoint 0 0 ; cc.tag = scrollUC
cc.BackColor = defColor 20 20 180
--cc.autosize = off
-->>> buttons
btns = for k = 20 to 1 by -1 collect
(
btn = dotnetobject "Button"
btn.FlatStyle = btn.FlatStyle.Flat
btn.FlatAppearance.BorderSize = 1
btn.FlatAppearance.BorderColor = defColor 60 60 60
btn.Backcolor = defColor 180 180 180
btn.text = "Button_#"+k as string
btn.Dock = btn.Dock.Top
btn.Size = defSize 160 20
btn
) ; cc.size = defSize 160 (btns[1].height*20)
--> add Controls
cc.controls.addrange btns
scrollUC.controls.add scrollBar
mainUC.controls.addrange #(cc, scrollUC)
form.controls.add mainUC
form.tag = mainUC.height
-->>> add Events
fn onSizeChanged s e =
(
ratio = (mainUC.Height as float/cc.Height)
scrollBar.Height = amin s.Height (scrollUC.height*ratio)
if mainUC.Height >= cc.Height then (cc.Location.y = scrollBar.Location.y = 0 ; scrollBar.visible = off) else
(
if not scrollBar.visible do scrollBar.visible = on
scrollBar.Location.y = if (loc = scrollBar.Location.y - (mainUC.Height - s.tag)*ratio) <= 0 then 0 else
(
if mainUC.Height > s.tag then loc else 0
)
format "sb.loc = %
" scrollBar.Location.y
)
s.tag = mainUC.Height
)
fn onMouseDown s e =
(
local crs = dotnetclass "Cursors"
if s.Height != s.Parent.Height then (s.Cursor.Current = crs.Hand ; s.tag = #(e.y,0))
else (s.Cursor.Current = crs.Default ; s.tag = #(e.y,1))
)
fn onMouseMove s e =
(
local crs = dotnetclass "Cursors", tag
case e.Button of
(
(e.Button.None): (s.Cursor.Current = if s.Height != s.Parent.Height then crs.Hand else crs.Default)
(e.Button.Left): if s.Height == s.Parent.Height then (tag = s.tag ; tag[2] = 0 ; s.tag = tag) else
(
tag = s.tag ; d = e.y - tag[1] ; tag[2] = 1
s.location.y = amin (s.Parent.Height - s.Height) (amax 0 (s.location.y + d))
s.tag = tag
)
)
)
dotnet.addeventhandler scrollBar "Move" (fn scroll s e = (cc.Location.y = -s.Location.y/(mainUC.Height as float/cc.Height)))
dotnet.addeventhandler scrollBar "MouseDown" onMouseDown
dotnet.addeventhandler scrollBar "MouseMove" onMouseMove
dotnet.addEventHandler form "SizeChanged" onSizeChanged
allControls = join btns #(form, mainUC, scrollUC, scrollBar, cc)
setLifetimeControl allControls
onSizeChanged form undefined
--cc.VerticalScroll.Maximum = cc.PreferredSize.Height - cc.Height
form.Show(maxHW())
)
Added MMB “drag” method
try(form.close()) catch()
(
mapped fn setLifetimeControl control = dotnet.setLifetimeControl control #dotnet
fn maxHW = (dotNetObject "maxCustomControls.win32HandleWrapper" (dotNetObject "System.IntPtr" (windows.getMaxHWND())))
fn defColor r g b = ((dotNetClass "System.Drawing.Color").FromArgb r g b)
fn defSize w h = (dotNetObject "System.Drawing.Size" w h)
fn defPoint x y = (dotNetObject "System.Drawing.Point" x y)
fn defRect x y w h = (dotNetObject "System.Drawing.Rectangle" x y w h)
-->>> main form
global form = dotnetobject "Form"
form.Icon = (dotNetClass "ManagedServices.AppSDK").GetMainApplicationIcon()
form.FormBorderStyle = form.FormBorderStyle.SizableToolWindow
form.StartPosition = form.StartPosition.Manual
form.Text = "vScrollTest" ; form.ShowInTaskbar = off
form.BackColor = defColor 150 20 20 ; form.DockPadding.All = 2
form.MaximumSize = defSize 185 500
form.MinimumSize = defSize 185 103
form.Bounds = defRect 10 110 185 284
-->>> main container
mainUC = dotnetobject "UserControl"
mainUC.Backcolor = defColor 40 40 40
mainUC.Dock = mainUC.Dock.Fill
-->>> scroll container
scrollUC = dotnetobject "UserControl"
scrollUC.Backcolor = defColor 40 40 40
scrollUC.width = 6 ; scrollUC.tag = 0
scrollUC.Dock = scrollUC.Dock.Right
-->>> scrollbar
global scrollBar = dotnetobject "Label"
scrollBar.Backcolor = defColor 51 175 235
scrollBar.width = 6
-->>> button container
global cc = dotnetobject "Label"
cc.location = defPoint 0 0 ; cc.tag = scrollUC
cc.BackColor = defColor 20 20 180
-->>> buttons
fn onMMouseDown s e =
(
local crs = dotnetclass "Cursors"
if e.Button == e.Button.Middle do
(
if not scrollBar.visible then (s.Cursor.Current = crs.Default ; s.tag = #(s.Parent.mousePosition.y,1)) else
(
(s.Cursor.Current = crs.Hand ; s.tag = #(s.Parent.mousePosition.y,0))
)
)
)
fn onMMouseMove s e =
(
local crs = dotnetclass "Cursors"
if e.Button == e.Button.Middle then
(
ratio = (mainUC.Height as float/cc.Height)
if not scrollBar.visible then (s.Cursor.Current = crs.Default) else
(
tag = s.tag ; d = (s.Parent.mousePosition.y - tag[1]) ; tag[2] = 1
clearlistener() ; format "d = %
" d
scrollBar.location.y = amin (scrollBar.Parent.Height - scrollBar.Height) (amax 0 ((scrollBar.location.y + d)*ratio))
s.tag = tag
)
) else (if s.Cursor.Current != crs.Default do s.Cursor.Current = crs.Default)
)
btns = for k = 20 to 1 by -1 collect
(
btn = dotnetobject "Button"
btn.FlatStyle = btn.FlatStyle.Flat
btn.FlatAppearance.BorderSize = 1
btn.FlatAppearance.BorderColor = defColor 60 60 60
btn.Backcolor = defColor 180 180 180
btn.text = "Button_#"+k as string
btn.Dock = btn.Dock.Top
btn.Size = defSize 160 20
dotnet.addeventhandler btn "MouseDown" onMMouseDown
dotnet.addeventhandler btn "MouseMove" onMMouseMove
btn
) ; cc.size = defSize 160 (btns[1].height*20)
--> add Controls
cc.controls.addrange btns
scrollUC.controls.add scrollBar
mainUC.controls.addrange #(cc, scrollUC)
form.controls.add mainUC
form.tag = mainUC.height
-->>> add Events
fn onSizeChanged s e =
(
ratio = (mainUC.Height as float/cc.Height)
scrollBar.Height = amin s.Height (scrollUC.height*ratio)
if mainUC.Height >= cc.Height then (cc.Location.y = scrollBar.Location.y = 0 ; scrollBar.visible = off) else
(
if not scrollBar.visible do scrollBar.visible = on
scrollBar.Location.y = if (loc = scrollBar.Location.y - (mainUC.Height - s.tag)*ratio) <= 0 then 0 else
(
if mainUC.Height > s.tag then loc else 0
)
)
s.tag = mainUC.Height
)
fn onMouseDown s e =
(
local crs = dotnetclass "Cursors"
if s.Height != s.Parent.Height then (s.Cursor.Current = crs.Hand ; s.tag = #(e.y,0))
else (s.Cursor.Current = crs.Default ; s.tag = #(e.y,1))
)
fn onMouseMove s e =
(
local crs = dotnetclass "Cursors", tag
case e.Button of
(
(e.Button.None): (s.Cursor.Current = if s.Height != s.Parent.Height then crs.Hand else crs.Default)
(e.Button.Left): if s.Height == s.Parent.Height then (tag = s.tag ; tag[2] = 0 ; s.tag = tag) else
(
tag = s.tag ; d = e.y - tag[1] ; tag[2] = 1
s.location.y = amin (s.Parent.Height - s.Height) (amax 0 (s.location.y + d))
s.tag = tag
)
)
)
dotnet.addeventhandler scrollBar "Move" (fn scroll s e = (cc.Location.y = -s.Location.y/(mainUC.Height as float/cc.Height)))
dotnet.addeventhandler scrollBar "MouseDown" onMouseDown
dotnet.addeventhandler scrollBar "MouseMove" onMouseMove
dotnet.addEventHandler form "SizeChanged" onSizeChanged
allControls = join btns #(form, mainUC, scrollUC, scrollBar, cc)
setLifetimeControl allControls
onSizeChanged form undefined
form.Show(maxHW())
)
may be you can make it scroll on mouse wheel rotation, not when it is pressed – I didn’t understand from the very beginning that I need to press on it! Except it, you could make an increment for every step on wheel rotation to change the position of about 1-3 buttons in dependence of the dimension of the window.
when you rotate a step – 1-3 btn will dissapear from the top, and so on!
That is the next step but first I need to solve draging which is “the most used” thing that user applies when it comes to scrollable control.
try(form.close()) catch()
(
local skipcicle = 0
mapped fn setLifetimeControl control = dotnet.setLifetimeControl control #dotnet
fn maxHW = (dotNetObject "maxCustomControls.win32HandleWrapper" (dotNetObject "System.IntPtr" (windows.getMaxHWND())))
fn defColor r g b = ((dotNetClass "System.Drawing.Color").FromArgb r g b)
fn defSize w h = (dotNetObject "System.Drawing.Size" w h)
fn defPoint x y = (dotNetObject "System.Drawing.Point" x y)
fn defRect x y w h = (dotNetObject "System.Drawing.Rectangle" x y w h)
-->>> main form
global form = dotnetobject "Form"
form.Icon = (dotNetClass "ManagedServices.AppSDK").GetMainApplicationIcon()
form.FormBorderStyle = form.FormBorderStyle.SizableToolWindow
form.StartPosition = form.StartPosition.Manual
form.Text = "vScrollTest" ; form.ShowInTaskbar = off
form.BackColor = defColor 150 20 20 ; form.DockPadding.All = 2
form.MaximumSize = defSize 185 500
form.MinimumSize = defSize 185 103
form.Bounds = defRect 10 110 185 284
-->>> main container
mainUC = dotnetobject "UserControl"
mainUC.Backcolor = defColor 40 40 40
mainUC.Dock = mainUC.Dock.Fill
-->>> scroll container
scrollUC = dotnetobject "UserControl"
scrollUC.Backcolor = defColor 40 40 40
scrollUC.width = 6 ; scrollUC.tag = 0
scrollUC.Dock = scrollUC.Dock.Right
-->>> scrollbar
global scrollBar = dotnetobject "Label"
scrollBar.Backcolor = defColor 51 175 235
scrollBar.width = 6
-->>> button container
global cc = dotnetobject "Label"
cc.location = defPoint 0 0 ; cc.tag = scrollUC
cc.BackColor = defColor 20 20 180
-->>> buttons
fn onMMouseDown s e =
(
local crs = dotnetclass "Cursors"
if e.Button == e.Button.Middle do
(
if not scrollBar.visible then (s.Cursor.Current = crs.Default ; s.tag = #(s.Parent.mousePosition.y,1)) else
(
(s.Cursor.Current = crs.Hand ; s.tag = #(s.Parent.mousePosition.y,0))
)
)
)
fn onMMouseMove s e =
(
local crs = dotnetclass "Cursors"
if e.Button == e.Button.Middle then
(
if skipcicle == 7 then
(
if not scrollBar.visible then (s.Cursor.Current = crs.Default) else
(
tag = s.tag ; d = (s.Parent.mousePosition.y - tag[1]) ; tag[2] = 1
scrollBar.location.y = amin (scrollBar.Parent.Height - scrollBar.Height) (amax 0 (scrollBar.location.y + d))
s.tag = tag
)
skipcicle = 0
)
else skipcicle += 1
)
else (if s.Cursor.Current != crs.Default do s.Cursor.Current = crs.Default)
)
btns = for k = 20 to 1 by -1 collect
(
btn = dotnetobject "Button"
btn.FlatStyle = btn.FlatStyle.Flat
btn.FlatAppearance.BorderSize = 1
btn.FlatAppearance.BorderColor = defColor 60 60 60
btn.Backcolor = defColor 180 180 180
btn.text = "Button_#"+k as string
btn.Dock = btn.Dock.Top
btn.Size = defSize 160 20
dotnet.addeventhandler btn "MouseDown" onMMouseDown
dotnet.addeventhandler btn "MouseMove" onMMouseMove
btn
) ; cc.size = defSize 160 (btns[1].height*20)
--> add Controls
cc.controls.addrange btns
scrollUC.controls.add scrollBar
mainUC.controls.addrange #(cc, scrollUC)
form.controls.add mainUC
form.tag = mainUC.height
-->>> add Events
fn onSizeChanged s e =
(
ratio = (mainUC.Height as float/cc.Height)
scrollBar.Height = amin s.Height (scrollUC.height*ratio)
if mainUC.Height >= cc.Height then (cc.Location.y = scrollBar.Location.y = 0 ; scrollBar.visible = off) else
(
if not scrollBar.visible do scrollBar.visible = on
scrollBar.Location.y = if (loc = scrollBar.Location.y - (mainUC.Height - s.tag)*ratio) <= 0 then 0 else
(
if mainUC.Height > s.tag then loc else 0
)
)
s.tag = mainUC.Height
)
fn onMouseDown s e =
(
local crs = dotnetclass "Cursors"
if s.Height != s.Parent.Height then (s.Cursor.Current = crs.Hand ; s.tag = #(e.y,0))
else (s.Cursor.Current = crs.Default ; s.tag = #(e.y,1))
)
fn onMouseMove s e =
(
local crs = dotnetclass "Cursors", tag
case e.Button of
(
(e.Button.None): (s.Cursor.Current = if s.Height != s.Parent.Height then crs.Hand else crs.Default)
(e.Button.Left): if s.Height == s.Parent.Height then (tag = s.tag ; tag[2] = 0 ; s.tag = tag) else
(
tag = s.tag ; d = e.y - tag[1] ; tag[2] = 1
s.location.y = amin (s.Parent.Height - s.Height) (amax 0 (s.location.y + d))
s.tag = tag
)
)
)
dotnet.addeventhandler scrollBar "Move" (fn scroll s e = (cc.Location.y = -s.Location.y/(mainUC.Height as float/cc.Height)))
dotnet.addeventhandler scrollBar "MouseDown" onMouseDown
dotnet.addeventhandler scrollBar "MouseMove" onMouseMove
dotnet.addEventHandler form "SizeChanged" onSizeChanged
allControls = join btns #(form, mainUC, scrollUC, scrollBar, cc)
setLifetimeControl allControls
onSizeChanged form undefined
form.Show(maxHW())
)
Hey Mike,
nice try but still jumpy.
Try again 2nd update I just corrected the code
OK, of course you’re much powerful then me, I’m just here to make people smile :))))
I love the way it works now :)))
Now, make it work with wheel rotation
I don’t say why you are here
Your solution is good but both solution still need a lot of simplification and optimization.
3rd update will arrive soon
Added mouse wheel scrolling
Not perfect but works.
try(form.close()) catch()
(
local SI = (dotNetClass "SystemInformation")
mapped fn setLifetimeControl control = dotnet.setLifetimeControl control #dotnet
fn maxHW = (dotNetObject "maxCustomControls.win32HandleWrapper" (dotNetObject "System.IntPtr" (windows.getMaxHWND())))
fn defColor r g b = ((dotNetClass "System.Drawing.Color").FromArgb r g b)
fn defSize w h = (dotNetObject "System.Drawing.Size" w h)
fn defPoint x y = (dotNetObject "System.Drawing.Point" x y)
fn defRect x y w h = (dotNetObject "System.Drawing.Rectangle" x y w h)
-->>> main form
global form = dotnetobject "Form"
form.Icon = (dotNetClass "ManagedServices.AppSDK").GetMainApplicationIcon()
form.FormBorderStyle = form.FormBorderStyle.SizableToolWindow
form.StartPosition = form.StartPosition.Manual
form.Text = "vScrollTest" ; form.ShowInTaskbar = off
form.BackColor = defColor 150 20 20 ; form.DockPadding.All = 2
form.MaximumSize = defSize 185 500
form.MinimumSize = defSize 185 103
form.Bounds = defRect 10 110 185 284
-->>> main container
mainUC = dotnetobject "UserControl"
mainUC.Backcolor = defColor 40 40 40
mainUC.Dock = mainUC.Dock.Fill
-->>> scroll container
scrollUC = dotnetobject "UserControl"
scrollUC.Backcolor = defColor 40 40 40
scrollUC.width = 6 ; scrollUC.tag = 0
scrollUC.Dock = scrollUC.Dock.Right
-->>> scrollbar
global scrollBar = dotnetobject "Label"
scrollBar.Backcolor = defColor 51 175 235
scrollBar.width = 6
-->>> button container
global cc = dotnetobject "Label"
cc.location = defPoint 0 0 ; cc.tag = scrollUC
cc.BackColor = defColor 20 20 180
-->>> buttons
fn onMouseWheel s e =
(
if scrollBar.visible do
(
local ratio = (mainUC.Height as float/cc.Height)
case of
(
((e.Delta * SI.MouseWheelScrollLines / 120) > 0): s.tag -=10
((e.Delta * SI.MouseWheelScrollLines / 120) < 0): s.tag +=10
)
scrollBar.location.y = amin (scrollBar.Parent.Height - scrollBar.Height) (amax 0 ((scrollBar.location.y + s.tag)*ratio))
)
)
fn onMMouseDown s e =
(
local crs = dotnetclass "Cursors"
if e.Button == e.Button.Middle do
(
if not scrollBar.visible then (s.Cursor.Current = crs.Default ; s.tag = #(s.Parent.mousePosition.y,1)) else
(
(s.Cursor.Current = crs.Hand ; s.tag = #(s.Parent.mousePosition.y,0))
)
)
)
fn onMMouseMove s e =
(
local crs = dotnetclass "Cursors"
if e.Button == e.Button.Middle then
(
local ratio = (mainUC.Height as float/cc.Height)
if not scrollBar.visible then (s.Cursor.Current = crs.Default) else
(
tag = s.tag ; d = (s.Parent.mousePosition.y - tag[1]) ; tag[2] = 1
scrollBar.location.y = amin (scrollBar.Parent.Height - scrollBar.Height) (amax 0 ((scrollBar.location.y + d)*ratio))
s.tag = tag
)
) else (if s.Cursor.Current != crs.Default do s.Cursor.Current = crs.Default)
)
btns = for k = 20 to 1 by -1 collect
(
btn = dotnetobject "Button"
btn.FlatStyle = btn.FlatStyle.Flat
btn.FlatAppearance.BorderSize = 1
btn.FlatAppearance.BorderColor = defColor 60 60 60
btn.Backcolor = defColor 180 180 180
btn.text = "Button_#"+k as string
btn.Dock = btn.Dock.Top
btn.Size = defSize 160 20
dotnet.addeventhandler btn "MouseHover" (fn mh s e = if not s.focused do (s.Focus() ; s.tag = scrollBar.location.y))
dotnet.addeventhandler btn "MouseWheel" onMouseWheel
dotnet.addeventhandler btn "MouseDown" onMMouseDown
dotnet.addeventhandler btn "MouseMove" onMMouseMove
btn
) ; cc.size = defSize 160 (btns[1].height*20)
--> add Controls
cc.controls.addrange btns
scrollUC.controls.add scrollBar
mainUC.controls.addrange #(cc, scrollUC)
form.controls.add mainUC
form.tag = mainUC.height
-->>> add Events
fn onSizeChanged s e =
(
local ratio = (mainUC.Height as float/cc.Height)
scrollBar.Height = amin s.Height (scrollUC.height*ratio)
if mainUC.Height >= cc.Height then (cc.Location.y = scrollBar.Location.y = 0 ; scrollBar.visible = off) else
(
if not scrollBar.visible do scrollBar.visible = on
scrollBar.Location.y = if (loc = scrollBar.Location.y - (mainUC.Height - s.tag)*ratio) <= 0 then 0 else
(
if mainUC.Height > s.tag then loc else 0
)
)
s.tag = mainUC.Height
)
fn onMouseDown s e =
(
local crs = dotnetclass "Cursors"
if s.Height != s.Parent.Height then (s.Cursor.Current = crs.Hand ; s.tag = #(e.y,0))
else (s.Cursor.Current = crs.Default ; s.tag = #(e.y,1))
)
fn onMouseMove s e =
(
local crs = dotnetclass "Cursors", tag
case e.Button of
(
(e.Button.None): (s.Cursor.Current = if s.Height != s.Parent.Height then crs.Hand else crs.Default)
(e.Button.Left): if s.Height == s.Parent.Height then (tag = s.tag ; tag[2] = 0 ; s.tag = tag) else
(
tag = s.tag ; d = e.y - tag[1] ; tag[2] = 1
s.location.y = amin (s.Parent.Height - s.Height) (amax 0 (s.location.y + d))
s.tag = tag
)
)
)
dotnet.addeventhandler scrollBar "Move" (fn scroll s e = (cc.Location.y = -s.Location.y/(mainUC.Height as float/cc.Height)))
dotnet.addeventhandler scrollBar "MouseDown" onMouseDown
dotnet.addeventhandler scrollBar "MouseMove" onMouseMove
dotnet.addEventHandler form "SizeChanged" onSizeChanged
allControls = join btns #(form, mainUC, scrollUC, scrollBar, cc)
setLifetimeControl allControls
onSizeChanged form undefined
form.Show(maxHW())
)
Some suggestions for optimization?
I’m not sure that I’m right, but you use
((e.Delta * SI.MouseWheelScrollLines / 120) > 0): s.tag -=10
((e.Delta * SI.MouseWheelScrollLines / 120) < 0): s.tag +=10
I think it is to restrected => just a little move – and it already reacts – that’s why I think, when you rotate in one direction, it is thinking at some small periods that I’m moving back.
But I’m not sure I’m right