Using your example I replaced “FLP” with ContainerControl
try(form.close()) catch()
(
global form = dotnetobject "MaxCustomControls.Maxform"
form.Text = "Show Test"
form.ShowInTaskbar = off
form.BackColor = form.BackColor.DarkGray
form.DockPadding.All = 2
form.StartPosition = form.StartPosition.Manual
form.Size = dotnetobject "System.Drawing.Size" 200 300
form.Location = dotnetobject "System.Drawing.Point" 800 200
p = dotnetobject "UserControl"
p.Backcolor = p.Backcolor.Gray
p.Dock = p.Dock.Fill
sb = dotnetobject "UserControl"
sb.Backcolor = sb.Backcolor.black
sb.width = 8
sb.Dock = sb.Dock.Right
global tt = dotnetobject "Button"
tt.Backcolor = tt.Backcolor.dimgray
tt.FlatStyle = tt.FlatStyle.Flat
tt.width = 8
sb.controls.add tt
global fp = dotnetobject "ContainerControl"
fp.dock = fp.dock.fill
fp.backColor = fp.backColor.gray
--fp.FlowDirection = fp.FlowDirection.TopDown
--fp.WrapContents = off
for k=1 to 20 do
(
bt = dotnetobject "Button"
bt.text = k as string
bt.dock = bt.dock.Bottom
bt.Size = dotnetobject "System.Drawing.Size" 160 24
fp.controls.add bt
)
p.controls.addrange #(fp, sb)
form.controls.add p
form.ShowModeless()
)
fp.VerticalScroll.Value = 50
fn onSizeChanged s e =
(
s.tag.controls.item[0].Height = s.tag.height*(s.Height as float/s.PreferredSize.Height)
)
dotnet.addEventHandler fp "SizeChanged" onSizeChanged
fp.tag = tt.parent
onSizeChanged fp undefined
Now I can get but not set VerticalScroll.value :).
Tried with this in listener when form is opened
cc = (form.controls.item[0]).controls.item[0]
-- this works
cc.verticalscroll.value
-->50
-- but this not ei. nothing happens
cc.verticalscroll.value = 30
Opposite behavior from FLP. Where did I go wrong?
Ok I get it. Like this
for k = 20 to 1 by -1 do
(
bt = dotnetobject "Button"
bt.text = k as string
bt.dock = bt.dock.top
bt.Size = dotnetobject "System.Drawing.Size" 160 24
fp.controls.add bt
)
Ok now when I run
cc = (form.controls.item[0]).controls.item[0]
-- to see top item (works)
cc.verticalscroll.value = 1
-- with this i can't see the last one (not works)
cc.verticalscroll.value = 100
because you refused ‘AutoScroll’ service you have to do all yourself. it will scroll the control, but you have to recalculate VerticalScroll.maximum when size or scroll changed, record the current scroll value, and change it if size changed… and no Scroll event for you anymore…
so everything do yourself. that’s a punishment for neglect built-in features.
no hope for any help from control… but it doesn’t mean no help from me
you have SizeChanged event… it gives you all what you need. your custom scrollbar has to keep tracking about scroll value, and fire ‘scroll’ event when its thumb position was changed
you will be probably surprised when you see how everything easy
here is a beginning:
try(form.close()) catch()
(
global form = dotnetobject "MaxCustomControls.Maxform"
form.Text = "Show Test"
form.ShowInTaskbar = off
form.BackColor = form.BackColor.DarkGray
form.DockPadding.All = 2
form.StartPosition = form.StartPosition.Manual
form.Size = dotnetobject "System.Drawing.Size" 200 300
form.Location = dotnetobject "System.Drawing.Point" 800 200
p = dotnetobject "UserControl"
p.Backcolor = p.Backcolor.Gray
p.Dock = p.Dock.Fill
sb = dotnetobject "UserControl"
sb.Backcolor = sb.Backcolor.black
sb.width = 8
sb.Dock = sb.Dock.Right
global tt = dotnetobject "Button"
tt.Backcolor = tt.Backcolor.dimgray
tt.FlatStyle = tt.FlatStyle.Flat
tt.width = 8
sb.controls.add tt
global cc = dotnetobject "ContainerControl"
cc.Dock = cc.Dock.Fill
cc.BackColor = cc.BackColor.gray
bts = for k=20 to 1 by -1 collect
(
bt = dotnetobject "Button"
bt.text = k as string
bt.Dock = bt.Dock.Top
bt.Size = dotnetobject "System.Drawing.Size" 160 24
bt
)
cc.controls.addrange bts
p.controls.addrange #(cc, sb)
cc.tag = sb
sb.tag = 0
fn onSizeChanged s e =
(
s.tag.controls.item[0].Height = amin s.Height (s.tag.height*(s.Height as float/s.PreferredSize.Height))
s.VerticalScroll.Maximum = amax s.VerticalScroll.Minimum (s.PreferredSize.Height - s.Height - s.tag.tag)
)
dotnet.addEventHandler cc "SizeChanged" onSizeChanged
form.controls.add p
onSizeChanged cc undefined
cc.VerticalScroll.Maximum = cc.PreferredSize.Height - cc.Height
form.ShowModeless()
)
First ugly result.
try(form.close()) catch()
(
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" w h)
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 200 500
form.MinimumSize = defSize 200 103
form.Bounds = defRect 10 110 200 284
-->>> main container
mainUC = dotnetobject "UserControl"
mainUC.Backcolor = mainUC.Backcolor.Gray
mainUC.Dock = mainUC.Dock.Fill
-->>> scroll container
scrollUC = dotnetobject "UserControl"
scrollUC.Backcolor = scrollUC.Backcolor.black
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 "ContainerControl"
cc.Dock = cc.Dock.Fill ; cc.tag = scrollUC
cc.BackColor = defColor 20 20 180
-->>> 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
)
--> add Controls
cc.controls.addrange btns
scrollUC.controls.add scrollBar
mainUC.controls.addrange #(cc, scrollUC)
form.controls.add mainUC
-->>> add Events
fn onSizeChanged s e =
(
s.tag.controls.item[0].Height = amin s.Height (s.tag.height*(s.Height as float/s.PreferredSize.Height))
s.VerticalScroll.Maximum = amax s.VerticalScroll.Minimum (s.PreferredSize.Height - s.Height - s.tag.tag)
)
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 c.Hand else c.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.VerticalScroll.Value = s.Location.y)
dotnet.addeventhandler scrollBar "MouseDown" onMouseDown
dotnet.addeventhandler scrollBar "MouseMove" onMouseMove
dotnet.addEventHandler cc "SizeChanged" onSizeChanged
onSizeChanged cc undefined
cc.VerticalScroll.Maximum = cc.PreferredSize.Height - cc.Height
form.Show(maxHW())
)
2 questions:
- how to get rid of flickering
- is it impotrtant to set LifetimeControl for all .net objects to #dotnet
#1
dont’t use scrollable control as panel
#2
yes. it’s important. it makes them protected from garbage collection.
Not understant #1 answer.
#2 ok. Do I need to set this for all .net object or only few (main controls only)?
When I move blue label (scrollbar) all buttons in ContainerControl start to flicker and also start to show and hide vertial scrolbar of ContainerControl
#2 question: Like this?
mapped fn setLifetimeControl control = dotnet.setLifetimeControl control #dotnet
allControls = join btns #(form, mainUC, scrollUC, scrollBar, cc)
setLifetimeControl allControls
that’s why i suggested to not use scrollable control (ContainerControl in your case)
I get same result when replace ContainerControl with UserControl.
I need to use different aproch.
edit
I was thinking to use Label as container for buttons and just offset label location.y in main UserControl. What do you think?
And this is the answer
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 = mainUC.Backcolor.Gray
mainUC.Dock = mainUC.Dock.Fill
-->>> scroll container
scrollUC = dotnetobject "UserControl"
scrollUC.Backcolor = scrollUC.Backcolor.black
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)
format "ccheight %
" cc.height
--> add Controls
cc.controls.addrange btns
scrollUC.controls.add scrollBar
mainUC.controls.addrange #(cc, scrollUC)
form.controls.add mainUC
-->>> add Events
fn onSizeChanged s e =
(
scrollBar.Height = amin s.Height (scrollUC.height*(mainUC.Height as float/cc.Height))
if mainUC.Height >= cc.Height do cc.Location.y = scrollBar.Location.y = 0
)
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())
)
For me .net Label is most adjustable control for custom controls creations.
Now I want to adjust form event “SizeChanged” to be able to control location of “cc” label.
woooooooooooooooow, great – This is fantastic!!!
Branko, Everything works just perfect at me, the only thing is that I get this error
undefined
ccheight 400
undefined
– Error occurred in onMouseMove(); filename: C:\Users\SkyDrive\scripts…; position: 2934; line: 72
– Frame:
– c: undefined
– e: dotNetObject:System.Windows.Forms.MouseEventArgs
– crs: dotNetClass:System.Windows.Forms.Cursors
– s: dotNetObject:System.Windows.Forms.Label
– tag: undefined
– d: undefined
>> MAXScript dotNet event handler Exception:
– Unknown property: “Hand” in undefined <<
I edited code above.
I was changed Cursor variable name and forgot to change on other places in the code.
Hope that’s works now