NumericUpDown doesn’t catch Enter key… i don’t want to do any User32 things. but I can’t find another solution yet.
LO means that when we drag mouse UP/DOWN it stops on screen edges. That’s the right point.
here is a version that fixes this problem. It calls edgeless mouse movement. Also I stick X cursor position during dragging, and change cursor to Size North/South…
fn makeTimeSpinner width:60 value:0 onChange: =
(
sp = dotnetobject "NumericUpDown"
sp.Width = width
sp.Backcolor = backcolor
sp.Minimum = -1e9
sp.Maximum = 1e9
sp.Value = value
fn onGotFocus s e = enableAccelerators = off
fn onLostFocus s e =
(
s.Text = s.Value as string
enableAccelerators = on
)
dotnet.addeventhandler sp "GotFocus" onGotFocus
dotnet.addeventhandler sp "LostFocus" onLostFocus
fn onKeyPress s e =
(
char = dotnetclass "System.Char"
c = e.KeyChar
if not (char.IsControl c) and not (char.IsDigit c) do
(
e.Handled = not ((c == "-") and (findstring s.Text c) == undefined)
)
)
dotnet.addeventhandler sp "KeyPress" onKeyPress
fn onTextChanged s e =
(
if s.Text != "-" and s.Text as Integer == undefined do
(
t = s.Controls.Item[1]
i = amax 1 t.SelectionStart
s.Text = replace s.Text i 1 ""
t.SelectionStart = i-1
t.SelectionLength = 0
)
)
dotnet.addeventhandler sp "TextChanged" onTextChanged
fn onMouseDown s e =
(
tag = s.tag
case e.Button of
(
(e.Button.Left): tag[2] == e.y
(e.Button.Right): if tag[3] == 1 do s.value = tag[1]
)
s.tag = tag
)
dotnet.addeventhandler sp "MouseDown" onMouseDown
fn onMouseUp s e =
(
tag = s.tag
case e.Button of
(
(e.Button.Left): tag[1] == s.value
(e.Button.Right): if tag[3] == 0 do s.value = 0
)
s.tag = tag
)
dotnet.addeventhandler sp "MouseUp" onMouseUp
fn onMouseMove s e =
(
p = s.Cursor.Current.Position
tag = s.tag
case e.Button of
(
(e.Button.Left):
(
s.Cursor.Current = (dotnetclass "System.Windows.Forms.Cursors").SizeNS
h = (dotnetclass "SystemInformation").VirtualScreen.Height
if act = (p.x != tag[4]) do p.x = tag[4]
case p.y of
(
0:
(
p.y = h-1
tag[2] += h-2
act = on
)
(h-1):
(
p.y = 0
tag[2] -= h-2
act = on
)
)
if act do s.Cursor.Current.Position = p
tag[3] = 1
s.value = tag[1] + (tag[2] - e.y)*s.Increment
s.tag = tag
)
(e.Button.None):
(
s.Cursor.Current = (dotnetclass "System.Windows.Forms.Cursors").Arrow
s.tag = #(s.value, e.y, 0, p.x)
)
)
)
dotnet.addeventhandler sp "MouseMove" onMouseMove
if onChange != unsupplied do dotnet.addeventhandler sp "ValueChanged" onChange
sp.tag = #(sp.value,0,0,0)
sp
)
try(destroydialog timelineRollout) catch()
rollout timelineRollout "timelineRollout" width:200 height:24
(
dotnetcontrol panel "UserControl" pos:[0,0] height:24
on timelineRollout open do
(
sp = makeTimeSpinner()
sp.Dock = sp.Dock.Left
panel.controls.addrange #(sp)
dotnet.setLifetimeControl sp #dotnet
)
)
createdialog timelineRollout
That is almost exactly how I did it, except you still have one very minor problem.
SystemInformation.VirtualScreen will get you the maximum height of your monitors.
For example, I am using one 19201200 monitor and one 12801024 monitor. In this case VirtualScreen.Height returns 1200. Therefore, the spinner does not wrap properly on the smaller monitor. It is better to use system.windows.forms.screen.frompoint to get the correct screen each time.
i thought about something like that… that’s why i stick the X position. i will check what we can do with it…
to make our spinner almost perfect we have to solve two problems:
#1 support Enter and Escape keys to set or reset the value
#2 disable this annoying BEEP when a wrong key is pressed. (letters, some controls, symbols, ect.)
the problem #1… I know how to solve it using User32 (and I’ve showed it ones in some thread) but I want to make the project without any extra (including on-fly compiled) assembly.
dammit… it seems like i can’t solve #2 without overriding onKeyPress… But maybe anyone can show 100% right and elegant enough way to convert KeyCode (or KeyData) to KeyChar?
start with the second problem… to solve it we need some key event that fires before KeyPressed (which is making the BEEP) and is being able to Suspend the Key.
well… there is only one event that can help us – KeyDown and its KeyEventArgs.
to be continued…
following LO’s advice we need to change the code to:
--h = (dotnetclass "SystemInformation").VirtualScreen.Height
h = ((dotnetclass "Screen").FromPoint p).Bounds.Height
right, LO?
hmm… probably not… bounds return me maximum resolution. WorkingArea could be a solutuion, but it returns the actual size minus height of windows taskbar… which is not right too.
What do you mean by maximum resolution? It seems right to me. bounds.Height Returns 1200 on my big screen and 1024 on my small screen.
i set two screens: 1920 x 1200 and 1680 x 1050
((dotnetclass “Screen”).FromPoint (dotnetobject “System.Drawing.Point” 3000 20)).Bounds.Height
returns me 1200