lengyue869 发表于 2023-9-1 11:18:51

怎么输出控件的名字


我想根据"Import Excel"名字来定位到对应的按钮,然后点击该按钮,但是根据以下代码输出的"控件文本:"都是空的
怎么输出所有控件的名字,或者有什么其他的办法可以定位到这个按钮


import win32gui,time
import win32api,win32con

def get_window_controls_info(window_name):
    control_info_list = []

    def callback(hwnd, _):
      control_info = {}
      control_info['hwnd'] = hwnd
      control_info['class_name'] = win32gui.GetClassName(hwnd)
      control_info['text'] = win32gui.GetWindowText(hwnd)
      control_info['rect'] = win32gui.GetWindowRect(hwnd)

      control_info_list.append(control_info)

      return True

    # 查找窗口句柄
    hwnd = win32gui.FindWindow(None, window_name)

    # 遍历窗口的子控件并获取信息
    win32gui.EnumChildWindows(hwnd, callback, None)

    return control_info_list

time.sleep(3)
# 调用函数获取窗口上所有控件的信息
window_name = "出货及开票明细报表"
controls_info = get_window_controls_info(window_name)
for control_info in controls_info:
    print("控件句柄:", control_info['hwnd'])
    print("控件类名:", control_info['class_name'])
    print("控件文本:", control_info['text'])
    print("控件位置和大小:", control_info['rect'])
    print()


输出结果如下:
控件句柄: 328926
控件类名: Afx:58990000:0:00010003:00000010:00000000
控件文本:
控件位置和大小: (14, 38, 1426, 69)

控件句柄: 394330
控件类名: ComboBox
控件文本:
控件位置和大小: (54, 43, 196, 65)

控件句柄: 394066
控件类名: Edit
控件文本:
控件位置和大小: (57, 46, 174, 62)

控件句柄: 263398
控件类名: AfxWnd110
控件文本:
控件位置和大小: (14, 38, 14, 38)

控件句柄: 920052
控件类名: AfxWnd110
控件文本:
控件位置和大小: (14, 38, 14, 38)

控件句柄: 1180760
控件类名: AfxWnd110
控件文本:
控件位置和大小: (14, 69, 1426, 78)


isdkz 发表于 2023-9-1 11:19:37

在你的代码中,你使用了win32gui.GetWindowText(hwnd)来获取控件的文本,但是输出的结果都是空的。这是因为这个方法只能获取到控件的可见文本,而不是控件的名字。控件的名字通常是在创建控件时指定的,可以通过win32gui.GetClassName(hwnd)来获取。但是在你的代码中,获取到的控件类名都是一些系统默认的类名,而不是控件的名字。

要获取控件的名字,你可以使用win32gui.GetDlgItemText(hwnd, control_id)方法。其中hwnd是窗口的句柄,control_id是控件的ID。控件的ID通常是在创建控件时指定的,你可以查看控件的创建代码来获取ID。

在你的情况下,你可以尝试使用Spy++这个工具来查看窗口的控件树和控件的属性,从而找到"Import Excel"按钮的ID。然后,使用win32gui.GetDlgItemText(hwnd, control_id)方法来获取按钮的名字。

以下是修改后的代码示例:

import win32gui
import win32api
import win32con

def get_window_controls_info(window_name):
    control_info_list = []

    def callback(hwnd, _):
      control_info = {}
      control_info['hwnd'] = hwnd
      control_info['class_name'] = win32gui.GetClassName(hwnd)
      control_info['text'] = win32gui.GetDlgItemText(hwnd, control_id)# 修改这里
      control_info['rect'] = win32gui.GetWindowRect(hwnd)

      control_info_list.append(control_info)

      return True

    hwnd = win32gui.FindWindow(None, window_name)
    control_id = 1234# 修改这里,将1234替换为"Import Excel"按钮的ID

    win32gui.EnumChildWindows(hwnd, callback, None)

    return control_info_list

window_name = "出货及开票明细报表"
controls_info = get_window_controls_info(window_name)
for control_info in controls_info:
    print("控件句柄:", control_info['hwnd'])
    print("控件类名:", control_info['class_name'])
    print("控件文本:", control_info['text'])
    print("控件位置和大小:", control_info['rect'])
    print()


请注意,你需要将1234替换为"Import Excel"按钮的实际ID。你可以使用Spy++等工具来查看按钮的ID。

lengyue869 发表于 2023-9-1 11:57:06

本帖最后由 lengyue869 于 2023-9-1 13:40 编辑

isdkz 发表于 2023-9-1 11:19
在你的代码中,你使用了win32gui.GetWindowText(hwnd)来获取控件的文本,但是输出的结果都是空的。这是因为 ...

报错了......




---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-d0f2e59699fe> in callback(hwnd, _)
   11         control_info['class_name'] = win32gui.GetClassName(hwnd)
---> 12         control_info['text'] = win32gui.GetDlgItemText(hwnd, control_id)# 修改这里
   13         control_info['rect'] = win32gui.GetWindowRect(hwnd)

TypeError: an integer is required (got type str)

The above exception was the direct cause of the following exception:

SystemError                               Traceback (most recent call last)
<ipython-input-9-d0f2e59699fe> in <module>
   25
   26 window_name = "出货及开票明细报表"
---> 27 controls_info = get_window_controls_info(window_name)
   28 for control_info in controls_info:
   29   print("控件句柄:", control_info['hwnd'])

<ipython-input-9-d0f2e59699fe> in get_window_controls_info(window_name)
   20   control_id = "0000009C"# 修改这里,将1234替换为"Import Excel"按钮的ID
   21
---> 22   win32gui.EnumChildWindows(hwnd, callback, None)
   23
   24   return control_info_list

SystemError: <built-in function EnumChildWindows> returned a result with an error set

阿奇_o 发表于 2023-9-1 17:41:56

看你需求,如果不复杂的话,只是点击几个可见按钮,更简单的方式,可以用 opencv 基于图片直接识别出来按钮,再用pyautogui点击即可

ps: 反正我已经试过你的这个 Import Excel按钮,用opencv-python库是可以很快识别到的,加上点击,也总共才十来行代码

lengyue869 发表于 2023-9-2 19:52:06

阿奇_o 发表于 2023-9-1 17:41
看你需求,如果不复杂的话,只是点击几个可见按钮,更简单的方式,可以用 opencv 基于图片直接识别出来按钮 ...

这个是数据查询完成之后的界面,我其实想根据出现Import Excel这个按钮来判断数据是否加载完成,然后用pyautogui点击导出数据,
之所以不用图片识别是因为要最终程序要打包成exe发给别人用,要把图片打包进去,然后还存在不同的显示器分辨率可能导致图片识别不准

阿奇_o 发表于 2023-9-2 23:14:21

lengyue869 发表于 2023-9-2 19:52
这个是数据查询完成之后的界面,我其实想根据出现Import Excel这个按钮来判断数据是否加载完成,然后用pyau ...

这样呀。。 如果 没具体程序来试验,那还真不好搞。。

另外对Windows视窗UI等,不熟悉的,也增加了开发难度。。

还有,Spy++能监测到,pywin32不一定都能。。

so, 你自己再琢磨琢磨吧,暂时帮不了你^_^
页: [1]
查看完整版本: 怎么输出控件的名字