There is a very beautiful javascript for mouse weel
http://prinzhorn.github.io/skrollr/
http://prinzhorn.github.io/skrollr/dist/skrollr.min.js
Yes but I never saw that any scrolling works like this in max.
Thanks for the nice examples, Mike.
if you develop any tools for max (or maya, or anything else) never try to make it looks or behaves differently than the main tool. the best custom tools look as built-in.
I know that is better to create GUI in some external softvare to look gook and works without bugs, but this is not the point here. And you recently started very informative topic an appropriate UI style.
This is just experimental works. I try to explore possibilities of some .net objects here in max.
At least can you do some “magic touch” to the code to works even more smoothly.
Thanks for your guidance, Denis.
your solution is already looks straightforward for me. i can post my (not finished yet) version. and you will see how our versions are close.
i don’t really like a solution to hide the scrollbar when noting to scroll. i don’t like this behavior in some .net controls as well. i think that to leave it just ‘filled’ makes more sense
Klunk suggested to hide scrollbar when size of form not overlap buttons. I agree to leave scrollbar visible because already looks thin and non-distracting.
Most important thing for me here is “click and drag” functionality over the buttons. Mouse Wheel scrolling is not what I’m looking for.
Another reason why I started this topic is because many scripters build own tools without taking into account the size of tool dialog ei. window form. Sometime the height can be greater than
screen size or width can covers most of the working space. I hope that the authors of these tools
agree with me.
http://www.scriptspot.com/3ds-max/scripts/cleaner
http://www.scriptspot.com/3ds-max/scripts/polyfx-v2-1-update
Anyway this can be fixed in many different ways like organizing some sections using FloatDialog with rollouts, using tabs etc. Worst case scenario will be docking.
Frankly I prefer more using .net form with minimalistic look especially when it comes to projects with many controls ei. in case when you need to join many tools into the one big tool – “All In One” solution. This requires most of the work but in the end worth it.
Denis once said than users can sometime scares of tools that look different of standard max tools, which is true of most cases, but scrips like I posted as example can be also scary and difficult to use although it has very good usage
Klunk suggested to hide scrollbar when size of form not overlap buttons. I agree to leave scrollbar visible because already looks thin and non-distracting.
no I never I just said it jumped when the window was big enough not to need one.
now it’s finished (at least at the point where i want to stop :))
try(form.close()) catch()
(
dotcolor = dotnetclass "System.Drawing.Color"
global form = dotnetobject "MaxCustomControls.Maxform"
form.Text = "VScroll"
form.ShowInTaskbar = off
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.Dock = p.Dock.Fill
barWidth = 7
barMinHeight = 7
global sb = dotnetobject "UserControl"
sb.Backcolor = sb.Backcolor.Black
sb.width = barWidth
sb.DockPadding.All = 1
sb.Dock = sb.Dock.Right
global tt = dotnetobject "Button"
tt.Name = "Thumb"
tt.Backcolor = tt.Backcolor.Dimgray
tt.FlatStyle = tt.FlatStyle.Flat
tt.FlatAppearance.BorderSize = 1
controlops.setselectable tt off
tt.width = 8
tt.MinimumSize = dotnetobject "System.Drawing.Size" barWidth barMinHeight
tt.Location = dotnetobject "System.Drawing.Point" 0 0
sb.controls.add tt
bc = dotnetobject "UserControl"
bc.Enabled = off
bc.Dock = bc.Dock.Fill
bc.Backcolor = bc.Backcolor.FromArgb 40 40 40
sb.controls.add bc
global pp = dotnetobject "UserControl"
pp.Dock = pp.Dock.Fill
cc = dotnetobject "UserControl"
cc.Padding = dotnetobject "Padding" 0 0 1 0
cc.AutoSize = on
bts = for k=25 to 1 by -1 collect
(
bt = dotnetobject "Button"
bt.BackColor = dotcolor.Transparent
bt.Dock = bt.Dock.Top
bt.Text = k as string
bt
)
cc.controls.addrange bts
pp.controls.add cc
p.controls.addrange #(pp, sb)
sb.tag = cc
form.controls.add p
sb.MaximumSize = tt.MaximumSize = (dotnetobject "System.Drawing.Size" barWidth cc.PreferredSize.Height)
tt.tag = #(0,0,0)
fn onSizeChanged s e =
(
c = s.controls.item[0]
v = s.tag.Height - s.Height + s.tag.Location.Y as float
if v > 0 then
(
h = (s.Height as float)/s.tag.PreferredSize.Height*s.Height
c.Location.Y = (s.tag.Location.Y as float)/(s.Height - s.tag.Height)*(s.Height - h)
)
else
(
s.tag.Location.Y = amin 0 (s.tag.Location.Y - v)
h = (s.Height as float)/s.tag.PreferredSize.Height*s.Height
)
h = amax c.MinimumSize.Height ((h + 0.5) as integer)
if c.Location.Y + h > s.Height do c.Location.Y = amax 0 (s.Height - h)
c.Height = h
)
fn onPanelSizeChanged s e = (s.controls.item[0].Width = s.Width)
fn onMouseDown s e =
(
if e.Button == e.Button.Left do s.tag = #(e.y, 0, 1)
)
fn onMouseMove s e =
(
if e.Button == e.Button.Left and e.y != s.tag[1] do
(
p = s.parent.tag
y = s.Location.y + e.y - s.tag[1]
y = amin (s.parent.Height - s.Height) (amax 0 y)
s.tag = #(s.tag[1], y, 0)
if y != s.Location.y do
(
p.Location.Y = (y as float)/(s.parent.Height - s.Height)*(s.parent.Height - p.Height)
s.Location.Y = y
)
)
)
dotnet.addEventHandler tt "MouseDown" onMouseDown
dotnet.addEventHandler tt "MouseMove" onMouseMove
dotnet.addEventHandler sb "SizeChanged" onSizeChanged
dotnet.addEventHandler pp "SizeChanged" onPanelSizeChanged
onPanelSizeChanged pp undefined
onSizeChanged sb undefined
form.ShowModeless()
)
no… you check this line!
if you don’t have this function, just comment it…
but before… try to get why i do this thing…
Why don’t you say that earlier I not have that fn and what represent if is not a secret.
Scrolling works smoothly. You stoped with this but what about other two conditions “click and drag” and “mouse wheel”?
the button in the flat style draws extra frame when it is focused. the only way to disable it is set the button be never selectable.
“click and drag” and “mouse wheel”… not really interested. it’s just an opposite of what i already solved
That’s why I decide to use .net label as scrollbar.
Ok. I appreciate everythine what you done here and You done more then enough.
Big thanks !
ha! you see it… but the using of a flat button gives nice and free: mouse enter, mouse leave, and mouse down appearance
devX simple button object have very nice property “Allow Focus” to disable selection rectangle
and nicer enter-leave-down appearance with gradient touch
try(form.close()) catch()
(
dotcolor = dotnetclass "System.Drawing.Color"
global form = dotnetobject "MaxCustomControls.Maxform"
form.Text = "VScroll"
form.ShowInTaskbar = off
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.Dock = p.Dock.Fill
barWidth = 7
barMinHeight = 7
global sb = dotnetobject "UserControl"
sb.Backcolor = sb.Backcolor.Black
sb.width = barWidth
sb.DockPadding.All = 1
sb.Dock = sb.Dock.Right
global tt = dotnetobject "Button"
tt.Name = "Thumb"
tt.Backcolor = tt.Backcolor.Dimgray
tt.FlatStyle = tt.FlatStyle.Flat
tt.FlatAppearance.BorderSize = 1
--controlops.setselectable tt off
tt.width = 8
tt.MinimumSize = dotnetobject "System.Drawing.Size" barWidth barMinHeight
tt.Location = dotnetobject "System.Drawing.Point" 0 0
sb.controls.add tt
bc = dotnetobject "UserControl"
bc.Enabled = off
bc.Dock = bc.Dock.Fill
bc.Backcolor = bc.Backcolor.FromArgb 40 40 40
sb.controls.add bc
global pp = dotnetobject "UserControl"
pp.Dock = pp.Dock.Fill
cc = dotnetobject "UserControl"
cc.Padding = dotnetobject "Padding" 0 0 1 0
cc.AutoSize = on
bts = for k=25 to 1 by -1 collect
(
devXbtn = dotNetObject "DevExpress.XtraEditors.SimpleButton"
devXbtn.text = ("button"+k as string) ; devXbtn.AllowFocus = off
devXbtn.size = (dotnetobject "System.Drawing.Size" 185 20)
devXbtn.dock = devXbtn.dock.top
devXbtn.appearance.backcolor = devXbtn.appearance.backcolor.FromArgb 100 140 200
devXbtn.appearance.backcolor2 = devXbtn.appearance.backcolor2.FromArgb 50 100 150
devXbtn.appearance.forecolor = devXbtn.appearance.forecolor.FromArgb 0 0 0
devXbtn.appearance.bordercolor = devXbtn.appearance.bordercolor.FromArgb 50 50 50
devXbtn.appearance.GradientMode = (dotNetClass "System.Drawing.Drawing2D.LinearGradientMode").Vertical
devXbtn.BorderStyle = devXbtn.BorderStyle.HotFlat --Flat,HotFlat,NoBorder,Office2003,Simple,Style3D,UltraFlat
devXbtn
)
cc.controls.addrange bts
pp.controls.add cc
p.controls.addrange #(pp, sb)
sb.tag = cc
form.controls.add p
sb.MaximumSize = tt.MaximumSize = (dotnetobject "System.Drawing.Size" barWidth cc.PreferredSize.Height)
tt.tag = #(0,0,0)
fn onSizeChanged s e =
(
c = s.controls.item[0]
v = s.tag.Height - s.Height + s.tag.Location.Y as float
if v > 0 then
(
h = (s.Height as float)/s.tag.PreferredSize.Height*s.Height
c.Location.Y = (s.tag.Location.Y as float)/(s.Height - s.tag.Height)*(s.Height - h)
)
else
(
s.tag.Location.Y = amin 0 (s.tag.Location.Y - v)
h = (s.Height as float)/s.tag.PreferredSize.Height*s.Height
)
h = amax c.MinimumSize.Height ((h + 0.5) as integer)
if c.Location.Y + h > s.Height do c.Location.Y = amax 0 (s.Height - h)
c.Height = h
)
fn onPanelSizeChanged s e = (s.controls.item[0].Width = s.Width)
fn onMouseDown s e =
(
if e.Button == e.Button.Left do s.tag = #(e.y, 0, 1)
)
fn onMouseMove s e =
(
if e.Button == e.Button.Left and e.y != s.tag[1] do
(
p = s.parent.tag
y = s.Location.y + e.y - s.tag[1]
y = amin (s.parent.Height - s.Height) (amax 0 y)
s.tag = #(s.tag[1], y, 0)
if y != s.Location.y do
(
p.Location.Y = (y as float)/(s.parent.Height - s.Height)*(s.parent.Height - p.Height)
s.Location.Y = y
)
)
)
dotnet.addEventHandler tt "MouseDown" onMouseDown
dotnet.addEventHandler tt "MouseMove" onMouseMove
dotnet.addEventHandler sb "SizeChanged" onSizeChanged
dotnet.addEventHandler pp "SizeChanged" onPanelSizeChanged
onPanelSizeChanged pp undefined
onSizeChanged sb undefined
form.ShowModeless()
)
But if we use paint event for gradient and other coloring stuff on base control then will “equate”
performance :).
Yup. devX is slower in any case , but you have to admit that it looks cool