[英]Using python with windows 10 to enable mouse wraparound
我正在嘗試使用自動光標定位與 pyWinhook 的某種組合來在多屏幕桌面設置上實現光標環繞。 最終,當我點擊屏幕的最右側或最左側邊緣時,我希望擴展代碼的功能以包裝到不同的系統,但現在我通過嘗試使其在單個功能上運行而忽略了網絡位系統。
最初,我使用 pyautogui 將這個簡單的腳本放在一起來進行包裝:
import pyautogui
MAX_X, MAX_Y = pyautogui.size()
MAX_X -= 1
MAX_Y -= 1
def detect_wrap():
x, y = pyautogui.position()
if x >= MAX_X:
pyautogui.moveTo(0,y)
elif x <= 0:
pyautogui.moveTo(MAX_X,y)
elif y >= MAX_Y:
pyautogui.moveTo(x, 0)
elif y <= 0:
pyautogui.moveTo(x, MAX_Y)
return
print(pyautogui.size())
while True:
detect_wrap()
這工作正常,但最后有令人討厭的無限循環,所以我嘗試尋找一種更干凈地處理它的方法,並偶然發現了 pyWinhook 和 pythoncom 並編造了一個類似的腳本來嘗試實現相同的目標。 但是,當我這樣做時,不是從底部跳到頂部,從最右邊跳到左邊等等,腳本卡在邊緣並停留在那里。 雖然我不確定為什么。 我放入了一些打印語句以試圖闡明一些情況,並看到鼠標確實移動到了相對的邊界,但有些東西一直使它返回。 我深入研究 pyautogui 並弄清楚它是如何移動光標的(使用 ctypes.windll.user32.SetCursorPos(xpos, ypos)),所以我將 pyautogui 排除在等式之外。 我剩下的看起來像這樣(請注意,這是一項正在進行的工作):
import win32api
import pyWinhook as pyHook
import pythoncom
import ctypes
import win32api, win32con
import win32.win32gui as win32gui
import os, sys, time
SCREEN_WIDTH = 0 # This will actually be set later, when we know the size of the attached screen(s)
SCREEN_HEIGHT = 0 # This will actually be set later, when we know the size of the attached screen(s)
XMAX = 0 # This will actually be set later, when we know the size of the attached screen(s)
YMAX = 0 # This will actually be set later, when we know the size of the attached screen(s)
XMIN = 1
YMIN = 1
def setWrapPos(xpos, ypos, border):
win32gui.ReleaseCapture()
if border == 'left':
xpos = SCREEN_WIDTH - 1
elif border == 'top':
ypos = SCREEN_HEIGHT - 1
elif border == 'right':
xpos = XMIN
elif border == 'bottom':
ypos = YMIN
else:
print('ERROR: Illegal border passed to setWrapPos()')
ctypes.windll.user32.SetCursorPos(xpos, ypos)
time.sleep(0.01)
return
def onclick(event):
print('Detected mouseclick at (%d,%d)' % event.Position)
return True
def trackMouse(event):
hm.UnhookMouse()
flags, hcursor, coords = win32gui.GetCursorInfo()
xpos, ypos = coords
print("Mouse at (%d, %d)" % (xpos, ypos))
if (xpos <= XMIN):
setWrapPos(xpos, ypos, 'left')
elif (ypos <= YMIN):
setWrapPos(xpos, ypos, 'top')
elif (xpos >= XMAX):
setWrapPos(xpos, ypos, 'right')
elif (ypos >= YMAX):
setWrapPos(xpos, ypos, 'bottom')
flags, hcursor, coords = win32gui.GetCursorInfo()
xpos, ypos = coords
print("Mouse moved to (%d, %d)" % (xpos, ypos))
hm.HookMouse()
return True
def onWinCombo(event):
if event.Key == 'X':
print('Lcontrol-X was detected. Exiting.')
hm.UnhookMouse()
hm.UnhookKeyboard()
os._exit(0)
else:
hm.KeyDown = onKeyboardEvent
return False
def noMoreCombo(event):
hm.KeyDown = onKeyboardEvent
hm.KeyUp = None
return False
def onKeyboardEvent(event):
print('Keyboard action detected, ' + str(event.Key) + ' was pressed.')
if str(event.Key) == 'Lcontrol':
print('Lcontrol detected.')
hm.KeyDown = onWinCombo
hm.KeyUp = noMoreCombo
return True
curr_right = 0
mons = win32api.EnumDisplayMonitors()
i = 0
while i < win32api.GetSystemMetrics(win32con.SM_CMONITORS):
minfo = win32api.GetMonitorInfo(mons[i][0])
if minfo['Monitor'][2] > SCREEN_HEIGHT:
SCREEN_HEIGHT = minfo['Monitor'][3]
print("Monitor #" + str(i+1) + ": " + str(minfo['Monitor'][2] - curr_right) + "x" + str(minfo['Monitor'][3]))
i += 1
curr_right += minfo['Monitor'][2]
minfo = win32api.GetMonitorInfo(mons[i-1][0])
SCREEN_WIDTH = minfo['Monitor'][2]
XMAX = SCREEN_WIDTH - 1
YMAX = SCREEN_HEIGHT - 1
hm = pyHook.HookManager()
hm.SubscribeMouseAllButtonsDown(onclick)
hm.SubscribeMouseMove(trackMouse)
hm.KeyDown = onKeyboardEvent
hm.HookMouse()
hm.HookKeyboard()
pythoncom.PumpMessages()
代碼有效,但無論我嘗試過什么,我似乎都無法避免讓光標彈回邊界而不是跳到另一邊。 我的想法已經用完了,所以想也許這里的某個人會想到發生了什么。
提前感謝您的任何見解。
更新:我創建了一個名為 wrap.py 的工作鼠標環繞 python 腳本,並將結果放在 GitHub 上https://github.com/XyzzyBob/wrap 。 我也在 Win10 下用 pyinstaller 編譯它,但無法上傳文件,因為我無法從代碼所在的位置傳輸文件。
python 腳本需要一堆庫,如 github 頁面所述,並且僅適用於 Windows。 如果我發現需要,我可能會在某個時候為 Linux 和 Mac 重做它,但現在 Windows 是我使用它的地方。
仍在開發用於多系統控制的網絡版本,但這是一個更大的程序。 這方面的進展可能會顯示為 github 頁面上的一個分支。
======================== xxxxxxxxxxxxxxxxxx ======================== ==
找到了一種使用不同庫來實現我想要做的事情的方法。 鼠標庫顯然處理低級掛鈎,並具有獲取和設置鼠標狀態項(如位置)的例程。 解決方案基本上是這樣的:
import mouse
...
def mouseEvent(event):
if isinstance(event, mouse._mouse_event.MoveEvent):
trackMouse(event)
elif isinstance(event, mouse._mouse_event.ButtonEvent):
onclick(event)
else:
print(event)
return True
...
def trackMouse(event):
xpos = event.x
ypos = event.y
print("Mouse at (%d, %d)" % (xpos, ypos))
if (xpos <= XMIN):
setWrapPos(xpos, ypos, 'left')
elif (ypos <= YMIN):
setWrapPos(xpos, ypos, 'top')
elif (xpos >= XMAX):
setWrapPos(xpos, ypos, 'right')
elif (ypos >= YMAX):
setWrapPos(xpos, ypos, 'bottom')
return True
...
def onclick(event):
print(event.event_type + ' for ' + event.button + ' button at ' + str(mouse.get_position()))
return True
### Main ###
hm = mouse.hook(mouseEvent)
pythoncom.PumpMessages()
現在只需要添加鍵盤鈎子和其他位,使其成為一個連貫的包。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.