DonationCoder.com forum
 
Read-only archive. This is a static copy of the DonationCoder.com forum. Reading and searching work as before; logging in, posting and private messages do not.
Archive of 2026-10-21 · About this archive · Main site

Author Topic: SOLVED: autohotkey makes cursor slide - i want mouse movement to halt the slide  (Read 32,595 times)

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
i've been using this simple script to slide my cursor around my screen(s) by hitting buttons on my house (these buttons are just assigned to keyboard hotkeys that i'll never normally use).

i find the sliding method of moving the cursor very nice - it means i hardly have to move the mouse about on the mat and, i'm not sure why, but it just seems to feel nicer than using an accelerated cursor (i haven't got used to using skwire's MAT app).

REQUEST:
so, here's the request. although i like this sliding cursor motion - it has to carry out the full autohotkey "MouseMove" function before releasing the cursor - so i can't break the movement part way by moving the cursor with my mouse.

does that make sense? in other words: i'd like the buttons on my mouse to start the cursor sliding across the screen BUT as soon as i move the mouse myself - autohotkey releases the cursor and lets me take control.

i thought i'd be able to figure this out myself but i soon realised that the "MouseMove" function isn't something i can command to stop. well, not with my basic knowledge.

i've included my script if it helps - thanks.

Code: (autoit)
;SlideCursor
;By nudone
;date: 2010-04-26
ScriptVersion=0.2
;function: Slides mouse cursor across whole screens. For multi-monitor systems.

;CoordMode,Mouse,Screen ;this isn't used
;# = winkey, ! = alt, ^ = control, + = shift

Menu,Tray,Icon,%SystemRoot%\system32\SHELL32.dll,101
Menu,Tray,Tip,SlideCursor %ScriptVersion%

Hotkey, #k, 	MoveUp
Hotkey, ^!+k, 	MoveUp 		; * to work with programmable mouse buttons (if winkey not accepted)
Hotkey, ^!+j, 	MoveDown
Hotkey, #j, 	MoveDown 	; *
Hotkey, #+j, 	MoveLeft
Hotkey, ^!+h, 	MoveLeft	; *
Hotkey, #+k, 	MoveRight
Hotkey, ^!+l, 	MoveRight	; *

;screen sizes
TopScreenHeight=1080
MiddleScreenWidth=1920
LeftScreenWidth=1024
RightScreenWidth=1024

;mouse cursor movement speed
VerticalSpeed=5 ; 0 = fastet, 100 = slowest
HorizontalSpeed=10
return

; Move the mouse upwards:
MoveUp:
MouseGetPos, xpos, ypos 
MouseMove, xpos, ypos - (TopScreenHeight*0.95), VerticalSpeed
return

; Move the mouse downwards:
MoveDown:
MouseGetPos, xpos, ypos
MouseMove, xpos, ypos + (TopScreenHeight*0.95), VerticalSpeed
return

; Move the mouse to (far) left:
MoveLeft:
MouseGetPos, xpos, ypos 
;MouseMove, xpos - MiddleScreenWidth - LeftScreenWidth , ypos, HorizontalSpeed ; use for 3 screens full travel
MouseMove, xpos - LeftScreenWidth, ypos, HorizontalSpeed ;
return

; Move the mouse to (far) right:
MoveRight:
MouseGetPos, xpos, ypos 
;MouseMove, xpos + MiddleScreenWidth + LeftScreenWidth , ypos, HorizontalSpeed ;use for 3 screens full travel
MouseMove, xpos + RightScreenWidth, ypos, HorizontalSpeed
return

cranioscopical

  • Friend of the Site
  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 4,776
    • Cody Award
    • Official Forum Clown
    • rotten turkey sandwich - Rotten Turkey Sandwich
i've been using this simple script to slide my cursor around my screen(s) by hitting buttons on my house
Clearly you need to modify the home keys.
Chris

Target

  • Honorary Member
  • Joined in 2006
  • **
  • Posts: 1,840
    • Coding Snacks
Quote
i've been using this simple script to slide my cursor around my screen(s) by hitting buttons on my house...

for some reason this rang a bell with me too...

My initial thoughts on this would be to move the cursor incrementally within a loop (so there is something to break out of)

eg
Code
mousegetpos, xpos, ypos

loop
{
    mousegetpos, , ypos_
    if ypos_ <> ypos
        break
    xpos++  
    mousemove, xpos, ypos, horizontalspeed

    if xpos = %rightscreenwidth%
        Break
}
 

this is an example only - I haven't tested it, but it should break out of the loop when it reaches the screen width, or if the mouse position varies vertically (this being a horizontal movement)
Alcohol is photoshop, bottled
Askhole - someone who ask for advice, then ignores it
"Look wise, say nothing, and grunt. Speech was given to conceal thought" - Sir William Osler

AndyM

  • Charter Member
  • Joined in 2006
  • ***
  • Posts: 616
i've been using this simple script to slide my cursor around my screen(s) by hitting buttons on my house
Clearly you need to modify the home keys.
;D

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
i've been using this simple script to slide my cursor around my screen(s) by hitting buttons on my house
Clearly you need to modify the home keys.
heheheh, oh dear. but very good cranioscopical.

thanks, Target, i will try your script out when i get chance later. it looks like it will work. i'll let you know. (nice bell pun by the way).
« Last Edit: May 06, 2010, 07:40 AM by nudone »

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
okay, this is working fine (almost). i just had to change the if statement to use % % and it started working.

i've been trying to add a bit of a buffer, or error margin, so that the loop doesn't break instantly when it detects mouse movement - i'm sure it will feel better if the cursor is allowed to move slightly off course as it slides.

but, my logic and autohotkey knowledge aren't up to the task (i've not included my OR statements here as they are obviously just completely wrong).

could anyone (Target) see how to add a mouse movement buffer or margin to the script  below?

Code: (autoit)
Hotkey, #k, 	MoveUp
Hotkey, ^!+k, 	MoveUp 		; * to work with programmable mouse buttons (if winkey not accepted)
Hotkey, ^!+j, 	MoveDown
Hotkey, #j, 	MoveDown 	; *
Hotkey, #+j, 	MoveLeft
Hotkey, ^!+h, 	MoveLeft	; *
Hotkey, #+k, 	MoveRight
Hotkey, ^!+l, 	MoveRight	; *	
horizontalspeed=0			; 0 = fastest, 100 = slowest
verticalspeed=0
speedmultiplier=30			; cursor movement needs speeding up a bit
rightscreenwidth=1920		; width of monitor
screenheight=1200			; height of monitor
return

MoveUp:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, xpos_,
	if xpos_ <> %xpos%
		Break
	ypos -= speedmultiplier
	MouseMove, xpos, ypos, verticalspeed
    if ypos = 0
		Break
}
return

MoveDown:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, xpos_,
    if xpos_ <> %xpos%
		Break
	ypos += speedmultiplier
	MouseMove, xpos, ypos, verticalspeed
    if ypos = %screenheight%
		Break
}
return

MoveLeft:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, , ypos_
    if ypos_ <> %ypos%
		Break
	xpos -= speedmultiplier
	MouseMove, xpos, ypos, horizontalspeed
    if xpos = 0
		Break
}
return

MoveRight:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, , ypos_
    if ypos_ <> %ypos%
		Break
	xpos += speedmultiplier
	MouseMove, xpos, ypos, horizontalspeed
    if xpos = %rightscreenwidth%
		Break
}
return

skwire

  • I eat Coding Snacks for breakfast...
  • Global Moderator
  • Joined in 2005
  • *****
  • Posts: 5,297
    • Participated in NANY Challenge Seventeen Times
    • Coding Snacks
    • Superboy Coder
    • Cody Award
    • Volunteers/Staff
    • Gathering Badge
Adjust the FudgeFactor variable to your liking:

Code: (autoit)
Hotkey, #k, 	MoveUp
Hotkey, ^!+k, 	MoveUp 		; * to work with programmable mouse buttons (if winkey not accepted)
Hotkey, ^!+j, 	MoveDown
Hotkey, #j, 	MoveDown 	; *
Hotkey, #+j, 	MoveLeft
Hotkey, ^!+h, 	MoveLeft	; *
Hotkey, #+k, 	MoveRight
Hotkey, ^!+l, 	MoveRight	; *	
horizontalspeed=0			; 0 = fastest, 100 = slowest
verticalspeed=0
speedmultiplier=30			; cursor movement needs speeding up a bit
rightscreenwidth=1920 		; width of monitor
screenheight=1200			; height of monitor
FudgeFactor=50
return

MoveUp:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, xpos_,
    If ( xpos_ < ( xpos - FudgeFactor ) OR ( xpos_ > ( xpos + FudgeFactor ) ) )
		Break
	ypos -= speedmultiplier
	MouseMove, xpos, ypos, verticalspeed
    if ypos = 0
		Break
}
return

MoveDown:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, xpos_,
    If ( xpos_ < ( xpos - FudgeFactor ) OR ( xpos_ > ( xpos + FudgeFactor ) ) )
		Break
	ypos += speedmultiplier
	MouseMove, xpos, ypos, verticalspeed
    if ypos = %screenheight%
		Break
}
return

MoveLeft:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, , ypos_
    If ( ypos_ < ( ypos - FudgeFactor ) OR ( ypos_ > ( ypos + FudgeFactor ) ) )
		Break
	xpos -= speedmultiplier
	MouseMove, xpos, ypos, horizontalspeed
    if xpos = 0
		Break
}
return

MoveRight:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, , ypos_
    If ( ypos_ < ( ypos - FudgeFactor ) OR ( ypos_ > ( ypos + FudgeFactor ) ) )
		Break
	xpos += speedmultiplier
	MouseMove, xpos, ypos, horizontalspeed
    if xpos = %rightscreenwidth%
		Break
}
return
« Last Edit: May 06, 2010, 10:57 AM by skwire »

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
okay, that's great, skwire.

with FudgeFactor=10 and an added FudgeFactorHorizontal=2 (for horizontal cursor slides across the screen), it feels about right.

i'm happy with how things are now - but it would be a near perfect script if the cursor slide could "transition/merge" into the manual cursor movement when user moves the mouse. maybe that is expected way too much though as there could/would be times when the user wants to break the slide immediately - so a set transition would be annoying.

(p.s. i think my OR statement was missing a bracket as it looked about the same - that's reassuring that i wasn't totally out of my depth.)
« Last Edit: May 06, 2010, 11:13 AM by nudone »

Perry Mowbray

  • N.A.N.Y. Organizer
  • Charter Member
  • Joined in 2005
  • ***
  • Posts: 1,817
    • Participated in NANY Challenge Three Times
    • Plugin Coding Medal
i'm happy with how things are now - but it would be a near perfect script if the cursor slide could "transition/merge" into the manual cursor movement when user moves the mouse. maybe that is expected way too much though as there could/would be times when the user wants to break the slide immediately - so a set transition would be annoying.

I think you'd need to be careful that you don't end up chasing your cursor all around your monitors?

This just reminded me of an Amiga mouse hack the kids loved... a rocket was launched when the programme ran and chased the cursor; the user moved the cursor away from the rocket which then changed course and kept chasing... until it caught up with the cursor and it exploded and the cursor disappeared: just long enough for you to wonder what you were going to do without a cursor (the first time anyway).

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
I think you'd need to be careful that you don't end up chasing your cursor all around your monitors?
good point.

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
i've updated the script slightly. it now calculates the "virtual" desktop covered by all of the monitors. it doesn't detect monitors being enabled/disabled so the script has to rerun if you are changing that kind of thing. it seems to work correctly, but then, i've based it on my inverted T screen layout (2 on top in the middle, 3 in a row along the bottom): 3 in a row works, 2 vertical works, all 4 works, and 1 main monitor works.

i have a request (that i know skwire knows the answer to), for switching the mouse cursor icon to another one - but only whilst the slide cursor function is in operation. i just think it would be nice if a giant cursor appeared whilst the sliding occured. i've had a look on the autohotkey forum but the dllcall function they are talking about for cursor swapping is beyond me.

i might try adding something to the script to detect which monitor the cursor is on. it might be handy for the cursor to travel automatically to the side and then up when trying to slide the cursor from the edge screen(s) to the top screen (and down and across when moving from the top screen to the side screens).

something like:
make cursor slide up
if cursor is on middle screen then slide up
else if cursor is on left screen then slide to right then up
else slide cursor to left and up

that sounds simple enough to my basic understanding of autohotkey.

i may also attempt to make the cursor slow down as it approaches the edges of the screen (as it did using the original MouseMove function).

here's the new script anyway.
Code: (autoit)
SysGet, VirtualScreenLeft, 76	; get the dimensions of the virtual desktop (all screens)
SysGet, VirtualScreenWidth, 78
SysGet, VirtualScreenTop, 77
SysGet, VirtualScreenHeight, 79
CoordMode, Mouse, Screen	; make mouse coordinates relative to screen not active window
Hotkey, #k, 	MoveUp
Hotkey, ^!+k, 	MoveUp 		; * to work with programmable mouse buttons (if winkey not accepted)
Hotkey, ^!+j, 	MoveDown
Hotkey, #j, 	MoveDown 	; *
Hotkey, #+j, 	MoveLeft
Hotkey, ^!+h, 	MoveLeft	; *
Hotkey, #+k, 	MoveRight
Hotkey, ^!+l, 	MoveRight	; *	
horizontalspeed = 0			; 0 = fastest, 100 = slowest
verticalspeed =0 
verticalspeedmultiplier = 50			; cursor movement needs speeding up a bit
horizontalspeedmultiplier = 70
borderstop = 100			; border around screens to halt cursor slide
mainscreenwidth = 1920 		; width of monitor
TopEdge := VirtualScreenTop + borderstop			; topmost monitor edge
BottomEdge := VirtualScreenHeight + VirtualScreenTop - borderstop ; bottommost monitor edge
LeftEdge := VirtualScreenLeft + borderstop ; leftmost monitor
RightEdge := VirtualScreenWidth + VirtualScreenLeft - borderstop ; rightmost monitor edge
FudgeFactor=10				; margin of error for vertical slides
FudgeFactorHorizontal=2		; margin of error for horizontal slides
return

MoveUp:
;CoordMode, Mouse, Screen
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, xpos_,
    If ( xpos_ < ( xpos - FudgeFactor ) OR ( xpos_ > ( xpos + FudgeFactor ) ) )
		Break
	ypos -= verticalspeedmultiplier
	MouseMove, xpos, ypos, verticalspeed
    ;if ypos = 0
	if ypos < %TopEdge%
		Break
}
return

MoveDown:
;CoordMode, Mouse, Screen
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, xpos_,
    If ( xpos_ < ( xpos - FudgeFactor ) OR ( xpos_ > ( xpos + FudgeFactor ) ) )
		Break
	ypos += verticalspeedmultiplier
	MouseMove, xpos, ypos, verticalspeed
    ;if ypos = %screenheight%
	if ypos > %BottomEdge%
		Break
}
return

MoveLeft:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, , ypos_
    If ( ypos_ < ( ypos - FudgeFactorHorizontal ) OR ( ypos_ > ( ypos + FudgeFactorHorizontal ) ) )
		Break
	xpos -= horizontalspeedmultiplier
	MouseMove, xpos, ypos, horizontalspeed
    ;if xpos = 0
	if xpos < %LeftEdge%
		Break
}
return

MoveRight:
MouseGetPos, xpos, ypos
loop
{
    MouseGetPos, , ypos_
    If ( ypos_ < ( ypos - FudgeFactorHorizontal ) OR ( ypos_ > ( ypos + FudgeFactorHorizontal ) ) )
		Break
	xpos += horizontalspeedmultiplier
	MouseMove, xpos, ypos, horizontalspeed
    ;if xpos = %mainscreenwidth%
	if xpos > %RightEdge%
		Break
}
return
« Last Edit: May 06, 2010, 04:06 PM by nudone »

Perry Mowbray

  • N.A.N.Y. Organizer
  • Charter Member
  • Joined in 2005
  • ***
  • Posts: 1,817
    • Participated in NANY Challenge Three Times
    • Plugin Coding Medal
i have a request (that i know skwire knows the answer to), for switching the mouse cursor icon to another one - but only whilst the slide cursor function is in operation. i just think it would be nice if a giant cursor appeared whilst the sliding occured. i've had a look on the autohotkey forum but the dllcall function they are talking about for cursor swapping is beyond me.

You mean this one: http://www.autohotkey.com/forum/topic6107.html which actually leads to this one: http://www.autohotkey.com/forum/topic35600.html
« Last Edit: May 06, 2010, 10:43 PM by Perry Mowbray »

Perry Mowbray

  • N.A.N.Y. Organizer
  • Charter Member
  • Joined in 2005
  • ***
  • Posts: 1,817
    • Participated in NANY Challenge Three Times
    • Plugin Coding Medal
I think you'd need to be careful that you don't end up chasing your cursor all around your monitors?
good point.

In hindsight I think it may be a good idea for a game?  :D Maybe you need a gameMode??

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
You mean this one: http://www.autohotkey.com/forum/topic6107.html
yes, they are what i saw - and became no less confused after reading them. i will try to understand it, maybe it's very simple.

i have enough fun with this sliding cursor as it is - but you are welcome to modify it into a game, Perry (truth is, it takes me too long to accomplish anything with autohotkey to try "fun" stuff).

Target

  • Honorary Member
  • Joined in 2006
  • **
  • Posts: 1,840
    • Coding Snacks
i have enough fun with this sliding cursor as it is - but you are welcome to modify it into a game, Perry (truth is, it takes me too long to accomplish anything with autohotkey to try "fun" stuff).

it's all fun (in a hair tearing, teeth grinding kind of way...)
Alcohol is photoshop, bottled
Askhole - someone who ask for advice, then ignores it
"Look wise, say nothing, and grunt. Speech was given to conceal thought" - Sir William Osler

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
i mentioned above that i might try and adapt the script so that it will make the cursor travel around corners - moving from a lower corner screen to the upper middle screen (and vice versa).

but it appears the the script allows for this already, in a buggy kind of way. so that is fortunate.

skwire

  • I eat Coding Snacks for breakfast...
  • Global Moderator
  • Joined in 2005
  • *****
  • Posts: 5,297
    • Participated in NANY Challenge Seventeen Times
    • Coding Snacks
    • Superboy Coder
    • Cody Award
    • Volunteers/Staff
    • Gathering Badge
yes, they are what i saw - and became no less confused after reading them. i will try to understand it, maybe it's very simple.

It is rather simple since Serenity wrapped the functions nicely.  Simply add the following function definitions to the BOTTOM of your script:

Code: (autoit)
RestoreCursors()
{
   SPI_SETCURSORS := 0x57
   DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )
}

SetSystemCursor( Cursor = "", cx = 0, cy = 0 )
{
   BlankCursor := 0, SystemCursor := 0, FileCursor := 0 ; init
   
   SystemCursors = 32512IDC_ARROW,32513IDC_IBEAM,32514IDC_WAIT,32515IDC_CROSS
   ,32516IDC_UPARROW,32640IDC_SIZE,32641IDC_ICON,32642IDC_SIZENWSE
   ,32643IDC_SIZENESW,32644IDC_SIZEWE,32645IDC_SIZENS,32646IDC_SIZEALL
   ,32648IDC_NO,32649IDC_HAND,32650IDC_APPSTARTING,32651IDC_HELP
   
   If Cursor = ; empty, so create blank cursor
   {
      VarSetCapacity( AndMask, 32*4, 0xFF ), VarSetCapacity( XorMask, 32*4, 0 )
      BlankCursor = 1 ; flag for later
   }
   Else If SubStr( Cursor,1,4 ) = "IDC_" ; load system cursor
   {
      Loop, Parse, SystemCursors, `,
      {
         CursorName := SubStr( A_Loopfield, 6, 15 ) ; get the cursor name, no trailing space with substr
         CursorID := SubStr( A_Loopfield, 1, 5 ) ; get the cursor id
         SystemCursor = 1
         If ( CursorName = Cursor )
         {
            CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )   
            Break               
         }
      }   
      If CursorHandle = ; invalid cursor name given
      {
         Msgbox,, SetCursor, Error: Invalid cursor name
         CursorHandle = Error
      }
   }   
   Else If FileExist( Cursor )
   {
      SplitPath, Cursor,,, Ext ; auto-detect type
      If Ext = ico
         uType := 0x1   
      Else If Ext in cur,ani
         uType := 0x2      
      Else ; invalid file ext
      {
         Msgbox,, SetCursor, Error: Invalid file type
         CursorHandle = Error
      }      
      FileCursor = 1
   }
   Else
   {   
      Msgbox,, SetCursor, Error: Invalid file path or cursor name
      CursorHandle = Error ; raise for later
   }
   If CursorHandle != Error
   {
      Loop, Parse, SystemCursors, `,
      {
         If BlankCursor = 1
         {
            Type = BlankCursor
            %Type%%A_Index% := DllCall( "CreateCursor"
            , Uint,0, Int,0, Int,0, Int,32, Int,32, Uint,&AndMask, Uint,&XorMask )
            CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
            DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
         }         
         Else If SystemCursor = 1
         {
            Type = SystemCursor
            CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )   
            %Type%%A_Index% := DllCall( "CopyImage"
            , Uint,CursorHandle, Uint,0x2, Int,cx, Int,cy, Uint,0 )      
            CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
            DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
         }
         Else If FileCursor = 1
         {
            Type = FileCursor
            %Type%%A_Index% := DllCall( "LoadImageA"
            , UInt,0, Str,Cursor, UInt,uType, Int,cx, Int,cy, UInt,0x10 )
            DllCall( "SetSystemCursor", Uint,%Type%%A_Index%, Int,SubStr( A_Loopfield, 1, 5 ) )         
         }         
      }
   }   
}

Then, to change the cursor, do the following:

Code: (autoit)
Cursor := "C:\path\to\my\cursor.cur"
SetSystemCursor( Cursor )

Or:

Code: (autoit)
SetSystemCursor( "C:\path\to\my\cursor.cur" )

To restore the cursor, simply do:

Code: (autoit)
RestoreCursors()

nudone

  • Cody's Creator
  • Columnist
  • Joined in 2005
  • ***
  • Posts: 4,119
    • Cody Award
thank you very much for explaining that, skwire. i might have understood it after a (few) rereads, i just couldn't figure out what was important and what was noise in the thread.

i'll go and implement it now...

Original address: https://www.donationcoder.com/forum/index.php?topic=22640.0