Windows 上 Python 3.1 的 SendKeys

2024-02-15

最新的 Python Sendkeys 模块适用于 Python 2.6。我无法自己升级它,因为它需要重新编译 C 模块。

有谁知道将密钥发送到窗口的相当简单的替代方法?

使用 win32ui.FindWindow() 我可以找到正确的窗口,然后使用 PyCWnd.SetActiveWindow() 将其激活,因此所需要的只是一种将击键发送到活动窗口的简单方法。

目的是执行菜单项。

该应用程序是用 Delphi 编写的,并且没有我所知道的任何进程间接口。


这是一个调用 user32.SendInput() 的工作模块。

不完美,但可用。

Edit:

昨天我用一个类做了一个版本,并在一个工作的 tkinter 应用程序中使用它。当我有时间清理它时,会将它放在这里。

已将其添加到下面的文档字符串中:

[ 如果我在我的个人资料中的文件夹中工作,那就可以了。
在另一个分区上工作时发生了这些问题。
文件权限正常,所以不知道是什么阻止了SendInput。 ]

SciTE 仍然需要完全准确窗口标题。

#!/usr/bin/python
# -*- coding: utf-8 -*-

''' send_input for python 3, from [email protected] /cdn-cgi/l/email-protection

code from Daniel F is adapted here. The original is at:
http://mail.python.org/pipermail/python-win32/2005-April/003131.html


SendInput sends to the window that has the keyboard focus.
That window must not be minimized.


There seem to be some strange limitations with user32.SendInput()
Here is what happened in my testing (on Vista sp2).

 [edit: It is OK if I work from a folder within my profile.    
 These problems happened when working on another partition.    
 File permissions were OK, so do not know what blocked SendInput.]

1
I opened Notepad from the Start menu,
then in Notepad opened test.txt,
and all worked fine.

2
I opened Notepad by opening test.txt in Explorer.
find_window() found Notepad, but user32.SendInput() had no effect.
If Notepad was minimized, it did not get restored or focussed.

The same happened with SciTE and Notepad2.


Another strangeness:
For SciTE I had to put in the whole window title, eg "test.txt - SciTE",
but for Notepad and Notepad2, only the app name, eg "Notepad".


'''

import ctypes as ct
from win32con import SW_MINIMIZE, SW_RESTORE
from win32ui import FindWindow, error as ui_err
from time import sleep


class cls_KeyBdInput(ct.Structure):
    _fields_ = [
        ("wVk", ct.c_ushort),
        ("wScan", ct.c_ushort),
        ("dwFlags", ct.c_ulong),
        ("time", ct.c_ulong),
        ("dwExtraInfo", ct.POINTER(ct.c_ulong) )
    ]

class cls_HardwareInput(ct.Structure):
    _fields_ = [
        ("uMsg", ct.c_ulong),
        ("wParamL", ct.c_short),
        ("wParamH", ct.c_ushort)
    ]

class cls_MouseInput(ct.Structure):
    _fields_ = [
        ("dx", ct.c_long),
        ("dy", ct.c_long),
        ("mouseData", ct.c_ulong),
        ("dwFlags", ct.c_ulong),
        ("time", ct.c_ulong),
        ("dwExtraInfo", ct.POINTER(ct.c_ulong) )
    ]

class cls_Input_I(ct.Union):
    _fields_ = [
        ("ki", cls_KeyBdInput),
        ("mi", cls_MouseInput),
        ("hi", cls_HardwareInput)
    ]

class cls_Input(ct.Structure):
    _fields_ = [
        ("type", ct.c_ulong),
        ("ii", cls_Input_I)
    ]


def find_window( s_app_name ):

    try:
        window1 = FindWindow(  None, s_app_name,)
        return window1
    except ui_err:
        pass
    except:
        raise

    try:
        window1 = FindWindow( s_app_name, None, )
        return window1
    except ui_err:
        return None
    except:
        raise


def make_input_objects( l_keys ):

    p_ExtraInfo_0 = ct.pointer(ct.c_ulong(0))

    l_inputs = [ ]
    for n_key, n_updown in l_keys:
        ki = cls_KeyBdInput( n_key, 0, n_updown, 0, p_ExtraInfo_0 )
        ii = cls_Input_I()
        ii.ki = ki
        l_inputs.append( ii )

    n_inputs = len(l_inputs)

    l_inputs_2=[]
    for ndx in range( 0, n_inputs ):
        s2 = "(1, l_inputs[%s])" % ndx
        l_inputs_2.append(s2)
    s_inputs = ', '.join(l_inputs_2)


    cls_input_array = cls_Input * n_inputs
    o_input_array = eval( "cls_input_array( %s )" % s_inputs )

    p_input_array = ct.pointer( o_input_array )
    n_size_0 = ct.sizeof( o_input_array[0] )

    # these are the args for user32.SendInput()
    return ( n_inputs, p_input_array, n_size_0 )

    '''It is interesting that o_input_array has gone out of scope
    by the time p_input_array is used, but it works.'''


def send_input( window1, t_inputs, b_minimize=True ):

    tpl1 = window1.GetWindowPlacement()
    was_min = False
    if tpl1[1] == 2:
        was_min = True
        window1.ShowWindow(SW_RESTORE)
        sleep(0.2)

    window1.SetForegroundWindow()
    sleep(0.2)
    window1.SetFocus()
    sleep(0.2)
    rv = ct.windll.user32.SendInput( *t_inputs )

    if was_min and b_minimize:
        sleep(0.3) # if the last input was Save, it may need time to take effect
        window1.ShowWindow(SW_MINIMIZE)

    return rv



# define some commonly-used key sequences
t_ctrl_s = (  # save in many apps
    ( 0x11, 0 ),
    ( 0x53, 0 ),
    ( 0x11, 2 ),
)
t_ctrl_r = (  # reload in some apps
    ( 0x11, 0 ),
    ( 0x52, 0 ),
    ( 0x11, 2 ),
)


def test():

    # file > open; a non-invasive way to test
    t_ctrl_o = ( ( 0x11, 0 ), ( 0x4F, 0 ), ( 0x11, 2 ), )

    # writes "Hello\n"
    # 0x10 is shift.  note that to repeat a key, as with 4C here, you have to release it after the first press
    t_hello = ( ( 0x10, 0 ), ( 0x48, 0 ), ( 0x10, 2 ), ( 0x45, 0 ), ( 0x4C, 0 ), ( 0x4C, 2 ), ( 0x4C, 0 ), ( 0x4F, 0 ), ( 0x0D, 0 ), )


    l_keys = [ ]
    ## l_keys.extend( t_ctrl_o )
    l_keys.extend( t_hello )
    l_keys.extend( t_ctrl_s )

    ## s_app_name = "SciTE"
    ## s_app_name = "(Untitled) - SciTE"
    s_app_name = "test.txt - SciTE"
    ## s_app_name = "Notepad2"
    ## s_app_name = "Notepad"

    window1 = find_window( s_app_name )
    if window1 == None:
        print( "%r has no window." % s_app_name )
        input( 'press enter to close' )
        exit()

    t_inputs = make_input_objects( l_keys )

    n = send_input( window1, t_inputs )

    ## print( "SendInput returned: %r" % n )
    ## print( "GetLastError: %r" % ct.windll.kernel32.GetLastError() )
    ## input( 'press enter to close' )



if __name__ == '__main__':
    test()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows 上 Python 3.1 的 SendKeys 的相关文章

随机推荐

  • 如何在 R 中将因子格式转换为数字格式而不更改值? [复制]

    这个问题在这里已经有答案了 下面是数据帧 df1 我想将其中的 V2 列从因子格式转换为数字 而不更改当前值 0 0 8 5 3 df1 V1 V2 V3 X2 X3 4470 2010 03 28 0 A 21 53675 0 4471
  • 用于逐步删除随机项的首选 Scala 集合?

    我有一个需要多次迭代的算法 每次迭代都会对集合中的项目进行评分并删除得分最高的项目 我可以填充一个Vector与初始种群一起 不断将其替换为var 或者选择一个可变集合作为val 哪个可变集合最符合要求 你可以考虑一个DoubleLinke
  • 获取控制器内的环境

    我的一个控制器中有一种情况 只能通过 AJAX 访问 我有以下代码 if request gt isXmlHttpRequest response new Response response gt setContent AJAX reque
  • 如何隐藏UINavigationBar 1px底线

    我有一个应用程序 有时需要其导航栏才能与内容融为一体 有谁知道如何摆脱或改变这个烦人的小条的颜色 在下图中我遇到的情况 我正在谈论 根视图控制器 下方的这条 1px 高度线 对于 iOS 13 Use the shadowColor htt
  • 一次查找多个地方的纬度和经度

    我有一长串城镇和城市列表 我想为每个城镇添加纬度和经度信息 有谁知道一次生成此信息的最简单方法 也可以看看对多个地址进行地理编码 https stackoverflow com questions 396819 geocode multip
  • 使用scale_fill_binned()时如何使用特定的填充颜色?

    我想使用我自己的填充颜色 例如 c red blue grey50 black 使用函数时scale fill binned 在 ggplot 代码中 我怎样才能做到这一点 这是一个最小的可重现示例 library tidyverse da
  • 接受可变数量参数的函数

    在本文档中 https developer apple com library prerelease ios documentation Swift Conceptual Swift Programming Language GuidedT
  • 我可以用 AngularJS 更改 Accept-Language 请求标头吗

    有没有办法更改或编辑我发送到 API 的接受语言标头 javascript Jquery 或 Angular 有没有办法 我不想发送默认的 而是发送我的 Cookie 的 在 AngularJS 中 您可以使用以下方法设置通用标头 http
  • 如何访问 Gradle 使用的“java.home”?

    gradlew properties显示没有具有以下值的属性 JAVA HOME 并且以下发出错误 指示不存在此类属性 println org gradle java home println gradle java home printl
  • 在 Google Chrome 扩展中使用 jQuery.ajax

    我使用 jquery ajax 函数将数据从 google chrome 扩展发布到我的网络服务 代码如下 ajax type POST url serviceUrl data data success function msg if ty
  • 将季度/年份格式转换为日期

    我创建了一个函数 将季度年格式的向量强制转换为日期向量 quarter to date c Q1 13 Q2 14 1 2013 03 01 2014 06 01 这是我的函数的代码 quarter to date lt function
  • 用鼠标拖动滚动

    我正在尝试制作一个可滚动面板 但没有滚动条 并通过用鼠标垂直拖动来滚动 这是到目前为止有人帮助我做的 private void panel1 MouseEnter object sender EventArgs e panel1 AutoS
  • 哪个更快? ByVal 还是 ByRef?

    在 VB NET 中 使用方法参数速度更快 ByVal or ByRef 另外 哪个在运行时消耗更多资源 RAM 我通读了这个问题 https stackoverflow com questions 290189 best practice
  • 多对多 EF7

    Models public partial class Film public int FilmID get set public virtual ICollection
  • 单例模板作为 C++ 中的基类[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 根据C 单例设计模式 https stackoverflow com questions 1008019 c singleton design
  • 通过 Socket.io 更新 React 状态

    我的 React 组件使用来自 socket io 的数据作为状态 我不确定如何在更新数据时更新状态而不重新渲染整个组件 示例代码 var socket io var data components key name markup sock
  • nginx 将 POST 请求重定向到 GET 请求

    我有 Rails 4 1 应用程序运行puma网络服务器 我使用 nginx 作为代理服务器 几天前 一切都进展顺利 我更新了我的应用程序 突然有些POST请求开始重定向到相同的网址 但作为GET要求 我尝试回滚到以前的工作版本 但没有成功
  • 在 C# 中以编程方式编译打字稿?

    我正在尝试用 C 编写一个函数 该函数接受包含打字稿代码的字符串并返回包含 JavaScript 代码的字符串 有这方面的库函数吗 您可以使用Process要调用编译器 请指定 out file js到临时文件夹并读取编译文件的内容 我做了
  • 如何找到所有兄弟情谊字符串?

    我有一个字符串和另一个包含字符串列表的文本文件 当两个字符串按字母顺序排序后完全相同时 我们将它们称为 兄弟字符串 例如 abc 和 cba 会被排序为 abc 和 abc 所以原来两者是兄弟关系 但 abc 和 aaa 则不然 那么 有没
  • Windows 上 Python 3.1 的 SendKeys

    最新的 Python Sendkeys 模块适用于 Python 2 6 我无法自己升级它 因为它需要重新编译 C 模块 有谁知道将密钥发送到窗口的相当简单的替代方法 使用 win32ui FindWindow 我可以找到正确的窗口 然后使