mouse drag anywhere on window to move and resize

Post your working scripts, libraries and tools
nickstokes
Posts: 8
Joined: 05 Nov 2015, 18:24

mouse drag anywhere on window to move and resize

16 Oct 2018, 09:14

See the discussion on this script.

Save the attached ahk alongside your script and add the following three lines in it:

Code: Select all

#Include windrag.ahk
^!LButton::WindowMouseDragMove()
^!RButton::WindowMouseDragResize()
While holding down ctrl+alt, left click anywhere on a window and drag to move; or right click and drag to resize.


Edited post, attachments don't seem to work with a temporary folder error. here is the source:

Code: Select all

;  File: windrag.ahk
/** 

Example usage, add the following three lines to your AHK script:


#Include windrag.ahk
^!LButton::WindowMouseDragMove()
^!RButton::WindowMouseDragResize()


* While holding down ctrl+alt, left click anywhere on a window and drag to move.
* While holding down ctrl+alt, right click any outer quadrant of a window and
  drag to resize, or near the center of a window to move. The system icons will
  show where you're going.

*/

;    +---------------------+
;    |   Set/Reset cursor  |
;    +---------------------+
; from: https://autohotkey.com/board/topic/32608-changing-the-system-cursor/

; Parameter 1 is file path or cursor name, e.g. IDC_SIZEALL. If this is omitted it will hide the cursor.
;   IDC_ARROW     IDC_UPARROW      IDC_SIZENESW      IDC_NO
;   IDC_IBEAM     IDC_SIZE         IDC_SIZEWE        IDC_HAND
;   IDC_WAIT      IDC_ICON         IDC_SIZENS        IDC_APPSTARTING
;   IDC_CROSS     IDC_SIZENWSE     IDC_SIZEALL       IDC_HELP
;
; Parameters 2 and 3 are the desired width and height of cursor. Omit these to use the default size, e.g. loading a 48x48 cursor will display as 48x48.
;
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 ) )			
			}          
		}
	}	
}

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





;          +-----------------------------------------+
;          |          SetWindowPosNoFlicker          |
;          +-----------------------------------------+
SetWindowPosNoFlicker(handle, wx, wy, ww, wh)
{

 ;WinMove ahk_id %handle%,, wx, wy, ww, wh

  DllCall("user32\SetWindowPos"
   , "Ptr", handle
   , "Ptr", 0
   , "Int", wx
   , "Int", wy
   , "Int", ww
   , "Int", wh
   , "UInt", 0)
  ; 0x4000	= SWP_ASYNCWINDOWPOS
; 0x2000	= SWP_DEFERERASE
; 0x400		= SWP_NOSENDCHANGING
; 0x200		= SWP_NOOWNERZORDER
; 0x100		= SWP_NOCOPYBITS
; 0x10		= SWP_NOACTIVATE
; 0x8			= SWP_NOREDRAW
; 0x4			= SWP_NOZORDER



  ;DllCall("user32\RedrawWindow"
  ; , "Ptr", handle
  ; , "Ptr", 0
  ; , "Ptr", 0
  ;, "UInt", 0x0100)  ;RDW_INVALIDATE | RDW_UPDATENOW

  /*
   RDW_INVALIDATE          0x0001
   RDW_INTERNALPAINT       0x0002
   RDW_ERASE               0x0004
  
   RDW_VALIDATE            0x0008
   RDW_NOINTERNALPAINT     0x0010
   RDW_NOERASE             0x0020
  
   RDW_NOCHILDREN          0x0040
   RDW_ALLCHILDREN         0x0080
  
   RDW_UPDATENOW           0x0100
   RDW_ERASENOW            0x0200
  
   RDW_FRAME               0x0400
   RDW_NOFRAME             0x0800
  */
  
}









;          +--------------------------------------------+
;          |             WindowMouseDragMove            |
;          +--------------------------------------------+

/**
@brief Drag windows around following mouse while pressing left click

For example, assign to ctrl+alt while mouse drag

@code
^!LButton::WindowMouseDragMove()
@endcode

@todo `WindowMouseDragMove` Left click is hardcoded. Customize to any given key.

@remark based on: https://autohotkey.com/board/topic/25106-altlbutton-window-dragging/ 
Fixed a few things here and there
*/
WindowMouseDragMove()
{
CoordMode, Mouse, Screen
MouseGetPos, x0, y0, window_id
WinGet, window_minmax, MinMax, ahk_id %window_id%
WinGetPos, wx, wy, ww, wh, ahk_id %window_id%

; Return if the window is maximized or minimized
if window_minmax <> 0 
{
   return
}
init := 1
SetWinDelay, 0
while(GetKeyState("LButton", "P"))
{
  MouseGetPos, x, y

  if( x == x0 && y == y0 ) {
     continue
  }
  
  if( init == 1 )  {
     SetSystemCursor( "IDC_SIZEALL" )
	 init := 0
  }

  wx += x - x0
  wy += y - y0
  x0 := x
  y0 := y

  WinMove ahk_id %window_id%,, wx, wy
}
SetWinDelay, -1
RestoreCursors()
return
}


;          +--------------------------------------------+
;          |             WindowMouseDragResize          |
;          +--------------------------------------------+

/**
@brief Resize windows from anywhere within the window, without having to aim the edges or corners 
 following mouse while right-click press

For example:

@code
^!RButton::WindowMouseDragResize()
@endcode

Initial mouse move determines which corner to drag for resize.
Use in combination with WindowMouseDragMove for best effect.

@todo `WindowMouseDragResize` Right-click is hardcoded. Customize to any given key.
@todo `WindowMouseDragResize` Inverted option as an argument for corner-selection logic.

@remark based on: https://autohotkey.com/board/topic/25106-altlbutton-window-dragging/ 
Fixed a few things here and there
*/
WindowMouseDragResize0()
{
CoordMode, Mouse, Screen
MouseGetPos, mx0, my0, window_id
WinGetPos, wx, wy, ww, wh, ahk_id %window_id%
WinGet, window_minmax, MinMax, ahk_id %window_id%

; menu-resize based solution - 
; https://autohotkey.com/boards/viewtopic.php?f=5&t=48520&p=216844#p216844
; WinMenuSelectItem, ahk_id %window_id%,,0&, Size
; return

SetWinDelay, 0

; Resore if maximized
if (window_minmax > 0)
{
  WinRestore ahk_id %window_id%

  ; Restore the window if maximized or minimized and set the position as seen
  ; badeffect ; WinMove ahk_id %window_id%, , wx, wy, ww, wh
}


; window-menu ; mx := mx0
; window-menu ; my := my0
; window-menu ; while(mx == mx0 || my == my0) {
; window-menu ;    Sleep 10
; window-menu ;    MouseGetPos, mx, my
; window-menu ; }
; window-menu ; 
; window-menu ; ; 0x0112 WM_SYSCOMMAND
; window-menu ; ; 0xF000 SC_SIZE
; window-menu ; PostMessage,  0x0112, 0xF000, 0, , ahk_id %window_id%
; window-menu ; if( ErrorLevel != 0 ) {
; window-menu ;    return
; window-menu ; }

firstDeltaX := "init"
firstDeltaY := "init"
cursorInit := 1
while(GetKeyState("RButton","P")) {  
  ; resize the window based on cursor position
  MouseGetPos, mx, my
  if(mx == mx0 && my == my0) {
     continue
  }

  if( firstDeltaX == "init" && mx-mx0 <> 0 ) {
     firstDeltaX := mx-mx0
  }
  if( firstDeltaY == "init" && my-my0 <> 0 ) {
     firstDeltaY := my-my0
  }
  if( cursorInit == 1 &&  firstDeltaX != "init"  &&  firstDeltaY != "init") {
	 SetSystemCursor( firstDeltaX*firstDeltaY>0 ? "IDC_SIZENWSE" : "IDC_SIZENESW" )
	 cursorInit := 0
  }
  
  deltaX := mx - mx0
  deltaY := my - my0
  
  if(firstDeltaX<0) {
    ww += deltaX
  }
  else {
	wx += deltaX
	ww -= deltaX
  }
  if(firstDeltaY<0) {
    wh += deltaY
  }
  else {
	wy += deltaY
	wh -= deltaY
  }
 
  mx0 := mx
  my0 := my
  
  WinMove ahk_id %window_id%,, wx, wy, ww, wh
}
RestoreCursors()
return
}





;          +--------------------------------------------+
;          |             WindowMouseDragResize          |
;          +--------------------------------------------+

/**
@brief Resize windows from anywhere within the window, without having to aim the edges or corners 
 following mouse while right-click press

For example:

@code
^!RButton::WindowMouseDragResize()
@endcode

Initial mouse move determines which corner to drag for resize.
Use in combination with WindowMouseDragMove for best effect.

@todo `WindowMouseDragResize` Right-click is hardcoded. Customize to any given key.
@todo `WindowMouseDragResize` Inverted option as an argument for corner-selection logic.

@remark based on: https://autohotkey.com/board/topic/25106-altlbutton-window-dragging/ 
Fixed a few things here and there
*/
WindowMouseDragResize()
{
; determine corner drag if mouse is this many percent points away from the center
cornerTolerance := 20
CoordMode, Mouse, Screen
MouseGetPos, mx0, my0, window_id
WinGetPos, wx, wy, ww, wh, ahk_id %window_id%
WinGet, window_minmax, MinMax, ahk_id %window_id%

; menu-resize based solution - 
; https://autohotkey.com/boards/viewtopic.php?f=5&t=48520&p=216844#p216844
; WinMenuSelectItem, ahk_id %window_id%,,0&, Size
; return

SetWinDelay, 0

; Restore if maximized [??]
if (window_minmax > 0)
{
  WinRestore ahk_id %window_id%
}

; establish drag corner depending on which quadrant the mouse is
wxCenter := wx+(ww/2)
wyCenter := wy+(wh/2)
xNoCornerZoneHalfSize := ww*(cornerTolerance/200.) ; 100 is for percent, 2 is for half
yNoCornerZoneHalfSize := wh*(cornerTolerance/200.)
wxLeftCorner   := wxCenter - xNoCornerZoneHalfSize
wxRightCorner  := wxCenter + xNoCornerZoneHalfSize
wyTopCorner    := wyCenter - yNoCornerZoneHalfSize
wyBottomCorner := wyCenter + yNoCornerZoneHalfSize

xCorner := mx0 < wxLeftCorner  ?  -1 : mx0>wxRightCorner  ? 1 : 0
yCorner := my0 < wyTopCorner   ?  -1 : my0>wyBottomCorner ? 1 : 0
; OutputDebug % "slyutil: win " wx " " wy " " ww " " wh
; OutputDebug % "slyutil: mouse " mx0 " " my0
; OutputDebug, slyutil: wxCenter %wxCenter% wyCenter %wyCenter%  xNoCornerZoneHalfSize %xNoCornerZoneHalfSize% yNoCornerZoneHalfSize %yNoCornerZoneHalfSize%
; OutputDebug, slyutil: xCorner %xCorner% yCorner %yCorner%

if( xCorner*yCorner>0 )
  SetSystemCursor("IDC_SIZENWSE")
else if (xCorner*yCorner<0)
  SetSystemCursor("IDC_SIZENESW")
else
{
   if(xCorner==0 && yCorner == 0)
     SetSystemCursor("IDC_SIZEALL")
   else
     SetSystemCursor( xCorner==0 ? "IDC_SIZENS" : "IDC_SIZEWE")
}


   
;SendMessage 0x0B, 1, , ,  ahk_id %window_id%
;SendMessage, 0x231, 0, 0,, ahk_id %window_id%	; WM_ENTERSIZEMOVE

while(GetKeyState("RButton","P")) { 
  MouseGetPos, mx, my
  if(mx == mx0 && my == my0) {
     continue
  }

  deltaX := mx - mx0
  deltaY := my - my0
  
  if(xCorner == 0 && yCorner == 0) {
    ; move
    wx += mx - mx0
    wy += my - my0
  }
  else if(xCorner>0)
    ww += deltaX
  else if(xCorner<0)
  {
	 wx += deltaX
	 ww -= deltaX
  }
  if(yCorner>0)
    wh += deltaY
  else if(yCorner<0)
  {
	 wy += deltaY
	 wh -= deltaY
  }
 
  mx0 := mx
  my0 := my
  
  SetWindowPosNoFlicker(window_id, wx, wy, ww, wh)
}
;SendMessage 0x0B, 0, , ,  ahk_id %window_id%
;SendMessage, 0x232, 0, 0,, ahk_id %window_id%	; WM_EXITSIZEMOVE
RestoreCursors()
return
}

Return to “Scripts and Functions”

Who is online

Users browsing this forum: Sam_ and 28 guests