Тема: AHK: Блокировка передвижения мышки по оси Х при нажатой кнопке
Подскажите пожалуйста, как сделать, что бы при зажатой XButton1 движение по оси ОХ блокировалось.
Заранее спасибо!
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Подскажите пожалуйста, как сделать, что бы при зажатой XButton1 движение по оси ОХ блокировалось.
Заранее спасибо!
...движение по оси ОХ блокировалось.
Имеется ввиду исключение движений мыши по горизонтали?:
#NoEnv
#SingleInstance,Force
SetBatchLines,-1
SetWinDelay,0
CoordMode,Mouse,Screen
Return
XButton1::
MouseGetPos,mx1,my1,mwin,mctrl
Loop
{
MouseGetPos,mx2,my2,mwin,mctrl
If (mx2<>mx1 Or my2<>my1)
Break
Sleep,100
}
If (Abs(mx2-mx1)<Abs(my2-my1))
lock=vertical
MouseGetPos,mx2,my2,mwin,mctrl
MouseMove,%mx1%,%my2%,0
Gosub,LOCK
Loop
{
GetKeyState, state, XButton1, P
If state=U
{
DllCall("ClipCursor")
Break
}
Sleep,10
}
Return
LOCK:
minx=9999
miny=9999
maxw=0
maxh=0
SysGet,monitors,MonitorCount
Loop,% monitors
{
current:=A_Index
SysGet,monitor,Monitor,% current
If (monitorLeft<minx)
minx:=monitorLeft
If (monitorTop<miny)
miny:=monitorTop
If (monitorRight>maxw)
maxw:=monitorRight
If (monitorBottom>maxh)
maxh:=monitorBottom
}
rl:=mx2
rt:=miny
rr:=mx2
rb:=maxh
VarSetCapacity(rect,16)
Loop,4
{
DllCall("RtlFillMemory",UInt,&rect+0+A_Index-1, UInt,1,UChar,rl >> 8*A_Index-8)
DllCall("RtlFillMemory",UInt,&rect+4+A_Index-1, UInt,1,UChar,rt >> 8*A_Index-8)
DllCall("RtlFillMemory",UInt,&rect+8+A_Index-1, UInt,1,UChar,rr >> 8*A_Index-8)
DllCall("RtlFillMemory",UInt,&rect+12+A_Index-1,UInt,1,UChar,rb >> 8*A_Index-8)
}
DllCall("ClipCursor", "UInt", &rect)
Return
Скажу сразу, что автором не являюсь, я только подправил под конкретный вопрос из этого оригинала.
Скажу сразу, что автором не являюсь, я только подправил под конкретный вопрос из этого оригинала.
Что-то там, в оригинале, явно перемудрили!
CoordMode, Mouse
VarSetCapacity(Rect, 16)
Return
~XButton1::
MouseGetPos, MouseX
NumPut(MouseX, Rect), NumPut(0, Rect, 4)
NumPut(MouseX, Rect, 8), NumPut(A_ScreenHeight, Rect, 12)
DllCall("ClipCursor", UInt, &Rect)
Return
~XButton1 Up:: DllCall("ClipCursor", UInt, 0)
...перемудрили!
Из Вашего примера, это очевидно.
Была похожая темка http://forum.script-coding.com/viewtopic.php?id=4570
Ссылка битая:
2teadrinker Можно попросить обратный пример с блокировкой оси Y?
Вот полный путь к теме.
Может этот раздел видят только разработчики и админы.
Вот сам код из той темы
SetBatchLines, -1
SetMouseDelay, -1
CoordMode, Mouse
OnExit, Exit
hHook := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, UInt, DllCall("GetModuleHandle", UInt, 0)
, UInt, 0)
Return
Exit:
DllCall("UnhookWindowsHookEx", UInt, hHook)
ExitApp
~LCtrl::
MouseGetPos,, y_prev
Direction = horizontal
Return
~LShift::
MouseGetPos, x_prev
Direction = vertical
Return
~LCtrl Up:: Direction =
~LShift Up:: Direction =
LowLevelMouseProc(nCode, wParam, lParam)
{
global Direction, x_prev, y_prev
if (nCode < 0 || !Direction || wParam != 0x200) ; WM_MOUSEMOVE = 0x200
Return DllCall("CallNextHookEx", UInt, 0, Int, nCode, UInt, wParam, UInt, lParam)
if Direction = horizontal
x := NumGet(lParam+0), y := y_prev
if Direction = vertical
y := NumGet(lParam+0, 4), x := x_prev
MouseMove, x, y, 0
Return 1
}
MasS, InFlames, вернул тему: Серый форум / AHK: Ортогональное перемещение мыши к жизни.
С использованием api-функции ClipCursor() даже попроще:
; ортогональное движение курсора
CoordMode, Mouse
VarSetCapacity(Rect, 16)
Return
~LShift:: ; вертикальное
MouseGetPos, MouseX
NumPut(MouseX, Rect), NumPut(0, Rect, 4)
NumPut(MouseX, Rect, 8), NumPut(A_ScreenHeight, Rect, 12)
DllCall("ClipCursor", UInt, &Rect)
Return
~LControl:: ; горизонтальное
MouseGetPos,, MouseY
NumPut(0, Rect), NumPut(MouseY, Rect, 4)
NumPut(A_ScreenWidth, Rect, 8), NumPut(MouseY, Rect, 12)
DllCall("ClipCursor", UInt, &Rect)
Return
~LShift Up::
~LControl Up:: DllCall("ClipCursor", UInt, 0)
Добавлю в Коллекцию.
Разъяснили, спасибо.
У примера из поста 10 есть 1 незаметный баг: после нажатия горячей клавиши, запрещающей перемещение в одной из плоскостей, курсор смещается на 1 пиксель влево для горизонтальной и вверх для вертикальной оси, либо начинает подрагивать в этом направлении. Для большинства задач это не критично, но в том же CS 1.6 это приводит к тому, что игрок начинает вращаться вокруг своей оси. При этом скрипт из Серый форум / AHK: Ортогональное перемещение мыши такой эффект не вызывает.
Да, действительно.
...в том же CS 1.6 это приводит к тому, что игрок начинает вращаться вокруг своей оси. При этом скрипт из Серый форум / AHK: Ортогональное перемещение мыши такой эффект не вызывает.
OFF: Не со всеми играми даже и скрипт из Серый форум / AHK: Ортогональное перемещение мыши работает корректно, на пример в CS:S и в BF:BC2 он не работает (курсор упирается в пол), а вот в COD Series он работает так же безупречно как в CS 1.6.
А если так:
; ортогональное движение курсора
CoordMode, Mouse
VarSetCapacity(Rect, 16)
Return
~LShift:: ; вертикальное
MouseGetPos, MouseX
NumPut(MouseX, Rect), NumPut(0, Rect, 4)
NumPut(MouseX, Rect, 8), NumPut(A_ScreenHeight, Rect, 12)
DllCall("ClipCursor", UInt, &Rect)
KeyWait, LShift
Return
~LControl:: ; горизонтальное
MouseGetPos,, MouseY
NumPut(0, Rect), NumPut(MouseY, Rect, 4)
NumPut(A_ScreenWidth, Rect, 8), NumPut(MouseY, Rect, 12)
DllCall("ClipCursor", UInt, &Rect)
KeyWait, LControl
Return
~LShift Up::
~LControl Up:: DllCall("ClipCursor", UInt, 0)
Только что проверил в CS:S, у меня так же работает, как и в CS 1.6.
P.S.
Как вам идея открыть "игровую" ветку форума?
Только что проверил в CS:S, у меня так же работает, как и в CS 1.6.
Это ты про какой скрипт?
А этот?
MasS, ответил здесь. Всё обсуждение вопроса по новой ветке форума — тоже туда.
А этот?
Этот, как и AHK: Ортогональное перемещение мыши у меня на W7 не работают.
Совсем не работают, или только в игре?
Ортогональное перемещение мыши не работает корректно в Direct3D части игр CS:S и в BF:BC2 (курсор упирается в пол/потолок, в DirectDraw'ной части работает), а вот этот вообще ни как не работает у меня в D3D из вышеперечисленных игр, хотя он так же работает в DirectDraw.
Тогда, возможно, в этих играх стоит какая-то защита от скриптов.
Они по времени выхода более поздние чем теже CS 1.6, и COD Series (в плане графического движка), MouseMove в их D3D точно не работают (установлено), если нужно, с эмулировать движение мыши, то только через DllCall("mouse_event", получается.
через DllCall("mouse_event", получается.
Попозже попробую.
У меня работает во всех режимах в CS 1.6 и в CS:S. (Правда признаюсь честно, я жуткий извращенец и играю в них в оконном режиме).
Вот, только что попробовал, и MouseMove работает
Да я уже давно пробовал, в оконном - без изменений. Видимо повезло, к примеру у друга залипают хоткеи в скрипте который на моей машине работает идеально. Железо как причина?, всё может быть...
Скажу точно, что зависит от мыши и клавиатуры, точнее от их драйверов. У меня есть элементарный скрипт для одной онлайн игры, который при нажатии на клавишу мыши посылает циклически F1+клик. Купил новую мышь A4tech X7 и скрипт перестал работать. Помогла замена драйверов, шедших в комплекте, на стандартные из набора Windows. (Об этом в документации к AHK где-то было написано).
У меня как раз клава G-600 и мышь XL-760H от A4Tech.
teadrinker
А можно сделать что бы запрет передвижения был по вертикали? А то я что то нефига не могу разобраться что за что отвечает и где менять
Да и еше можно ли сделать так что бы при нажатии той же XButton1 курсор ровно с одинаковой скоростью двигался вверх, а в это время я мог двигать мышь и передвигать курсов только по горизонтали при этом не ускорят и не замедляя скорость движения вверх?
А можно сделать что бы запрет передвижения был по вертикали?
А который из скриптов у тебя работает?
при нажатии той же XButton1 курсор ровно с одинаковой скоростью двигался вверх
А с какой скоростью?
Grey пишет:через DllCall("mouse_event", получается.
Попозже попробую.
Можно Вас попросить попробовать?, для меня это не критично, просто очень интересно в плане оформления.
Вот пример. Вместо
x := 500, y := 300
CoordMode, Mouse
MouseMove, x, y
можно использовать api-функцию mouse_event:
x := 500, y := 300
MOUSEEVENTF_ABSOLUTE := 0x8000, MOUSEEVENTF_MOVE := 0x1
DllCall("mouse_event"
, UInt, MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE
, Int, Round(x*0xFFFF/A_ScreenWidth)
, Int, Round(y*0xFFFF/A_ScreenHeight)
, UInt, 0)
Говорят, в некоторых играх второй вариант работает, а первый — нет.
Извините, но не могу понять, последний код применительно к коду из какого поста этой темы (#8, #10, #15)?
Ну а в каком коде используется MouseMove?
Только во #2'ом и в #8'ом. И всё же можно код целиком?
SetBatchLines, -1
SetMouseDelay, -1
CoordMode, Mouse
OnExit, Exit
hHook := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Int, RegisterCallback("LowLevelMouseProc", "Fast")
, UInt, DllCall("GetModuleHandle", UInt, 0)
, UInt, 0)
Return
Exit:
DllCall("UnhookWindowsHookEx", UInt, hHook)
ExitApp
~LCtrl::
MouseGetPos,, y_prev
Direction = horizontal
KeyWait, LCtrl
Return
~LShift::
MouseGetPos, x_prev
Direction = vertical
KeyWait, LShift
Return
~LCtrl Up:: Direction =
~LShift Up:: Direction =
LowLevelMouseProc(nCode, wParam, lParam)
{
global Direction, x_prev, y_prev
static MOUSEEVENTF_ABSOLUTE = 0x8000, MOUSEEVENTF_MOVE = 0x1
if (nCode < 0 || !Direction || wParam != 0x200) ; WM_MOUSEMOVE = 0x200
Return DllCall("CallNextHookEx", UInt, 0, Int, nCode, UInt, wParam, UInt, lParam)
if Direction = horizontal
x := NumGet(lParam+0), y := y_prev
if Direction = vertical
y := NumGet(lParam+0, 4), x := x_prev
DllCall("mouse_event"
, UInt, MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE
, Int, Ceil(x*0xFFFF/A_ScreenWidth)
, Int, Ceil(y*0xFFFF/A_ScreenHeight)
, UInt, 0)
Return 1
}
Спасибо, но этот вариант у меня так же в D3D не работает, как и скрипты до этого. Собственно я не вижу такой необходимости, если нужно какое-то ограничение, то это можно реализовать настройкой DPI чувствительности благо щас это грызуны позволяют сделать.
Просто ещё один альтернативный вариант с подстветкой области ограничения в пределах дочернего или обычного окна , написал ранее, но за ненадобностью дописывание скрипта было отложенно. Делюсь тем что успел накодить, может и в таком виде кому-нибудь пригодиться
Управляем режимами с помошью левой кнопки мыши и колеса:
колесо вниз:
1. ограничение снято
2. по оси X
3. по оси Y
4. в пределах дочернего окна
5. в пределах обычного окна
колесо вверх:
1. предыдущий режим
2. ограничение снято
Gui, -Caption +E0x80000 +AlwaysOnTop +ToolWindow +LastFound
hgui:=WinExist()
DllCall("SetLayeredWindowAttributes","uint",hgui,"uint",0xecebea,"uchar",185,"uint",3)
Gui, Margin, 0,0
Gui, Font, bold s12 cff7f00
tw:=300,th:=50
Gui, Add, Text, w%tw% h%th%
CoordMode, Mouse,Screen
VarSetCapacity(RECT,16,0)
;bgra
bmd=
( Join
0000ffff0000ffff0000ffff
0000ffff0000000000000000
0000ffff0000000000000000
)
nSize:=StrLen(bmd)//2
VarSetCapacity(buf,nSize,0)
Loop % nSize
NumPut("0x" . SubStr(bmd,2*A_Index-1,2),buf,A_Index-1,"Char")
hbrbm:=DllCall("CreateBitmap","int",3,"int",3,"uint",1,"uint",32,"uint",&buf)
hpatbr:=DllCall("CreatePatternBrush","uint",hbrbm)
DllCall("DeleteObject","uint",hbrbm)
Esc::
DllCall("DeleteObject","uint",hpatbr)
Loop, Parse, rgnlist, |
DllCall("DeleteObject","uint",A_LoopField)
ExitApp
~LButton & WheelUp::
if clip_mode>0
clip_mode:=-1
else clip_mode:=prev_clip_mode-1
~LButton & WheelDown::
clip_mode+=(clip_mode<4)-clip_mode*(clip_mode>3)
MouseGetPos, x,y,hwnd,hctrl,2
if (!hctrl&&clip_mode=3)
Return
if (!hwnd&&clip_mode=4)
Return
tx:=x+25,ty:=y+25
if clip_mode
{
if clip_mode=1
{
DllCall("SetRect","uint",&RECT,"int",0,"int",y,"int",A_ScreenWidth,"int",y+1)
infotext:="По оси x"
}
else if clip_mode=2
{
DllCall("SetRect","uint",&RECT,"int",x,"int",0,"int",x+1,"int",A_ScreenHeight)
infotext:="По оси y"
}
else if clip_mode=3
{
WinGetPos, wx,wy,ww,wh,ahk_id %hctrl%
DllCall("SetRect","uint",&RECT,"int",wx,"int",wy,"int",wx+ww,"int",wy+wh)
infotext:="В пределах дочернего окна-`n контрола под курсором"
Gosub, showclippedarea
hctrl=
}
else if clip_mode=4
{
WinGetPos, wx,wy,ww,wh,ahk_id %hwnd%
DllCall("SetRect","uint",&RECT,"int",wx,"int",wy,"int",wx+ww,"int",wy+wh)
infotext:="В пределах окна под курсором"
Gosub, showclippedarea
hwnd=
}
prev_clip_mode:=clip_mode
DllCall("ClipCursor","uint",&RECT)
}
else
{
DllCall("ClipCursor","uint",0)
infotext:="Ограничение снято"
}
GuiControl,,Static1, % clip_mode . ". " . infotext
; Gui, Show, % "NA x" . tx . " y" . ty . " w" . tw . " h" . th
DllCall("SetWindowPos","uint",hgui,"uint",0,"int",tx,"int",ty,"int",tw,"int",th,"uint",4|16|64)
SetTimer, hidetext, -2000
Return
hidetext:
DllCall("SetWindowPos","uint",hgui,"uint",0,"int",tx,"int",ty,"int",tw,"int",th,"uint",4|16|128)
Return
showclippedarea:
hdcscr:=DllCall("GetDC","uint",0)
DllCall("SetROP2","uint",hdcscr,"int",15)
hrgn:=DllCall("CreateRectRgn","int",wx,"int",wy,"int",wx+ww,"int",wy+wh)
rgnlist .=hrgn . "|"
DllCall("FrameRgn","uint",hdcscr,"uint",hrgn,"uint",hpatbr,"int",7,"int",7)
DllCall("ReleaseDC","uint",0,"uint",hdcscr)
SetTimer, redraweclippedarea, -2500
Return
redraweclippedarea:
Loop, Parse, rgnlist, |
{
if A_LoopField
{
DllCall("RedrawWindow","uint",0,"uint",0,"uint",A_LoopField,"uint",1|2|4|128|256|512|1024)
DllCall("DeleteObject","uint",A_LoopField)
}
}
rgnlist=
Return
/*
hdc2:=DllCall("GetWindowDC","uint",hclipped)
DllCall("GetRandomRgn","uint",hdc2,"uint",hrgn,"int",4)
DllCall("ReleaseDC","uint",hclipped,"uint",hdc2)
DllCall("GetWindowRgn","uint",hclipped,"uint",hrgn)
DllCall("FillRgn","uint",hdc,"uint",hrgn_wnd,"uint",hpatbr)
R2_BLACK 1
R2_NOTMERGEPEN 2
R2_MASKNOTPEN 3
R2_NOTCOPYPEN 4
R2_MASKPENNOT 5
R2_NOT 6
R2_XORPEN 7
R2_NOTMASKPEN 8
R2_MASKPEN 9
R2_NOTXORPEN 10
R2_NOP 11
R2_MERGENOTPEN 12
R2_COPYPEN 13
R2_MERGEPENNOT 14
R2_MERGEPEN 15
R2_WHITE 16
RDW_INVALIDATE 1
RDW_INTERNALPAINT 2
RDW_ERASE 4
RDW_VALIDATE 8
RDW_NOINTERNALPAINT 16
RDW_NOERASE 32
RDW_NOCHILDREN 64
RDW_ALLCHILDREN 128
RDW_UPDATENOW 256
RDW_ERASENOW 512
RDW_FRAME 1024
RDW_NOFRAME 2048
*/
Просто ещё один альтернативный вариант с подстветкой области ограничения в пределах дочернего или обычного окна
Вот этот скрипт работает в соурс играх!!! ПОЖАЛУЙСТА СДЕЛАЙТЕ НА КНОПКУ передвижение мыши только по горизонтали, а то кнопкой мыши + колесиком в 3D играх трудновато делается. Сделайте пожалуйста этот скрипт на кнопку! БУДУ ОЧЕНЬ БЛАГОДАРЕН
anzor_30, не нужно цитировать предыдущий пост полностью!
Так никто не знает как сделать скрипт для передвижения по горизонтали из поста 41 по нажатию кнопки?
сделать скрипт для передвижения по горизонтали из поста 41 по нажатию кнопки?
Если ещё актуально, замените строки:
~LButton & WheelUp::
if clip_mode>0
clip_mode:=-1
else clip_mode:=prev_clip_mode-1
~LButton & WheelDown::
clip_mode+=(clip_mode<4)-clip_mode*(clip_mode>3)
на свои, как это сделать можно прочесть здесь:
Горячие клавиши для мыши, джойстика и клавиатуры
например:
~z:: ; клавиша z
clip_mode:=!clip_mode ; по горизонтали вкл/выкл
kirtech, СПАСИБО большое!
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться