Python中的简单热键脚本 - 如何设置全局热键以发送一串文本?

3
我想知道如何使用wxPython和win32apis创建一个简单的脚本,以激活具有特定标题并输出文本(按键)的窗口(如果它尚未处于活动状态)。其中一个可能的应用是游戏中的快捷键。我已经研究了wxPython RegisterHotKey(),但作为业余的Python程序员,我不太清楚。
脚本的基本结构将是:
  1. 定义热键(类似于win+F_)
  2. 监视热键击键
  3. 查看所需窗口(标题)是否已经处于活动状态,如果没有,则激活它
  4. 模拟输入一些文本
我知道有更简单的方法来实现这一点(例如AutoHotkey),但我更喜欢使用自己编写并对Python产生兴趣的东西。
谢谢!
记录上,我在Windows 7 AMD64上使用Python 2.7,虽然我怀疑解释器版本/平台/架构在这里没有太大影响。

https://github.com/boppreh/keyboard - Andrew
1个回答

4
你是在谈论激活一个你在wx中创建的窗口还是一个独立的应用程序,例如记事本?如果是在wx中,那么很简单。你只需要使用Raise()将你需要的任何框架带入焦点。你可能会使用PubSub或PostEvent来让子框架知道它需要被激活。
如果你是在谈论记事本,那么情况会变得更加复杂。这是一个我基于从网络和PyWin32邮件列表中获得的一些东西创建的丑陋的黑客方法:
def windowEnumerationHandler(self, hwnd, resultList):
    '''
    This is a handler to be passed to win32gui.EnumWindows() to generate
    a list of (window handle, window text) tuples.
    '''

    resultList.append((hwnd, win32gui.GetWindowText(hwnd)))

def bringToFront(self, windowText):
    '''
    Method to look for an open window that has a title that
    matches the passed in text. If found, it will proceed to
    attempt to make that window the Foreground Window.
    '''
    secondsPassed = 0
    while secondsPassed <= 5:
        # sleep one second to give the window time to appear
        wx.Sleep(1)

        print 'bringing to front'
        topWindows = []
        # pass in an empty list to be filled
        # somehow this call returns the list with the same variable name
        win32gui.EnumWindows(self.windowEnumerationHandler, topWindows)
        print len(topWindows)
        # loop through windows and find the one we want
        for i in topWindows:
            if windowText in i[1]:
                print i[1]
                win32gui.ShowWindow(i[0],5)
                win32gui.SetForegroundWindow(i[0])
        # loop for 5-10 seconds, then break or raise
        handle = win32gui.GetForegroundWindow()
        if windowText in win32gui.GetWindowText(handle):
            break
        else:
            # increment counter and loop again                
            secondsPassed += 1

然后我使用了SendKeys包将文本发送到窗口(参见http://www.rutherfurd.net/python/sendkeys/)。如果用户打开其他任何东西,脚本将会中断或发生奇怪的事情。如果您打开像MS Office这样的东西,请改用win32com而不是SendKeys。那样更加可靠。


谢谢!我考虑过使用SendKeys,但是最新版本只支持Python 2.6,虽然它很可能向后兼容,但是自安装程序会特别寻找匹配的Python版本。 此外,“脚本将中断或发生奇怪的事情”是指如果用户在发送按键时切换窗口,会发生什么吗? - terrygarcia
如果用户在脚本运行时切换窗口,则SendKeys将继续向焦点发送键,如果您没有预料到这一点,可能会感到困惑。 - Mike Driscoll
这不是什么大问题,但如果是的话,不能使用while:解决吗?在那段代码中我该用什么替换窗口标题?最后,Python 2.6的SendKeys是否适用于Python 2.7;我只需手动将源代码提取到所需的模块目录中吗?我讨厌Windows作为开发平台;一直懒得重新安装Ubuntu,因为我通过“安装”明显冲突的Python包破坏了其引导序列,具有讽刺意味。 - terrygarcia
1
我想你可以使用while循环并查询当前聚焦的窗口,以查看它是否是正确的标题。调用bringToFront(“windowTitle”)来运行脚本。我没有尝试从源代码安装SendKeys,但应该可以工作。只需提取存档,打开命令外壳并导航到它。然后执行“python setup.py install”。 - Mike Driscoll
1
如果他没有包含setup.py文件,那么通常你可以将其解压到正确的位置。 - Mike Driscoll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接