Нормальное перемещение окна, за любую его часть и без рывков, получилось только методом аля-EWD.
Единственный (который я увидел) минус моего кода - во время работы этого скрипта ВСЕ окна с классом AutoHotkeyGUI (а это, обычно, все окна созданные AutoHotkey-ем) будут перемещаться средней клавишей мыши.
- от использования LButton и RButton я отказался ибо они часто используются и это создает ненужную нагрузку на проц.
MButton:: ; Средняя мышь - перемещение окон за любое место внутри окна
;-----------------------------------------------------------------------------
; И вы можете во время перемещения нажать Escape, чтобы отменить перемещение
CoordMode, Mouse ; переключиться на абсолютные координаты экрана
MouseGetPos, EWD_MouseStartX, EWD_MouseStartY, EWD_MouseWin ; получить начальную позицию мыши и ID окна под мышью
WinGetClass, EWD_Win_Class, ahk_id %EWD_MouseWin% ; получаем класс окна под мышью
WinGetTitle, EWD_Win_Title, ahk_id %EWD_MouseWin%
If EWD_Win_Class=AutoHotkeyGUI
{
if !hand
DllCall("SetSystemCursor", UInt, CROSS_CursorHandle, Int, OCR_NORMAL), hand := 1
WinGetPos, EWD_OriginalPosX, EWD_OriginalPosY,,, ahk_id %EWD_MouseWin% ; запоминаем исходные координаты окна
SetTimer, EWD_WatchMouse, 5 ; переходить к указанной подпрограмме через каждые 10 мс
}
else
{
SetTimer, EWD_WatchMouse, off ; отключить таймер
EWD_Work = ; сбрасываем флаг, что подпрограмма выполняется
Send, {MButton Down}
Loop
GetKeyState, MBState, MButton, P ; проверить нажата ли средняя кнопка мыши
Until MBState = "U" ; если кнопка отпущена, то закончить
Send, {MButton Up}
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS:=0x57, UInt, 0, UInt, 0, UInt, 0), hand := ""
Return ; закончить обработку горячей клавиши
}
Return ; закончить обработку горячей клавиши
EWD_WatchMouse: ; подпрограмма обработки событий в таймере
EWD_Work = 1 ; флаг, что подпрограмма выполняется (он нужен для корректной работы закрытия окон по Escape)
GetKeyState, EWD_MButtonState, MButton, P ; проверить нажата ли средняя кнопка мыши
If EWD_MButtonState = U ; если кнопка отпущена, то закончить перемещение окна...
{
SetTimer, EWD_WatchMouse, off ; отключить таймер
EWD_Work = ; сбрасываем флаг, что подпрограмма выполняется
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS:=0x57, UInt, 0, UInt, 0, UInt, 0), hand := ""
Return ; конец подпрограммы, закончить обработку горячей клавиши
}
GetKeyState, EWD_EscapeState, Escape, P ; проверить нажата ли клавиша Escape
If EWD_EscapeState = D ; если нажата, то отменить перемещение окна (вернуть его в начальные координаты)
{
SetTimer, EWD_WatchMouse, off ; отключить таймер
EWD_Work = ; сбрасываем флаг, что подпрограмма выполняется
WinMove, ahk_id %EWD_MouseWin%,, %EWD_OriginalPosX%, %EWD_OriginalPosY% ; вернуть окно в начальные координаты
DllCall("SystemParametersInfo", UInt, SPI_SETCURSORS:=0x57, UInt, 0, UInt, 0, UInt, 0), hand := ""
Return ; конец подпрограммы, закончить обработку горячей клавиши
}
; ...если кнопка нажата, то перемешать окно вслед за перемещением указателя мыши
CoordMode, Mouse ; переключиться на абсолютные координаты экрана
MouseGetPos, EWD_MouseX, EWD_MouseY ; получить текущие координаты мыши
WinGetPos, EWD_WinX, EWD_WinY,,, ahk_id %EWD_MouseWin% ; получить позицию окна под мышкой
SetWinDelay, -1 ; перемещать окно немедленно
; переместить окно под мышью вслед за мышью
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, EWD_WinY + EWD_MouseY - EWD_MouseStartY
EWD_MouseStartX := EWD_MouseX ; обновить X координату для следующего вызова этой подпрограммы по таймеру
EWD_MouseStartY := EWD_MouseY ; обновить Y координату для следующего вызова этой подпрограммы по таймеру
Return ; закончить подпрограмму и обработку горячей клавиши
Собственно, вставляете этот кусок кода в любой свой скрипт ("подрихтовав" сравнение
If EWD_Win_Class=AutoHotkeyGUI
и ваше окно перемещается средней клавишей мыши.
Жизнь стоит того чтобы не быть сволочью. (с) Разные Люди