单击其他程序工具栏中的按钮
Posted
技术标签:
【中文标题】单击其他程序工具栏中的按钮【英文标题】:Click Button in Toolbar of Other Program 【发布时间】:2020-10-19 14:48:32 【问题描述】:我正在尝试自动化我没有源代码的遗留应用程序上的一些东西。所以我实际上是在尝试使用 Windows API 来单击我需要的按钮。
有一个msvb_lib_toolbar
类型的工具栏,如下所示:
我可以通过使用以下代码来处理它(我认为):
IntPtr window = FindWindow("ThunderRT6FormDC", "redacted");
IntPtr bar = FindWindowEx(window, IntPtr.Zero,"msvb_lib_toolbar",null);
查看文档,看来我应该可以使用 SendMessage
和 TB_PRESSBUTTON
消息来单击这些按钮:
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
但是,我不确定如何设置 wParam
和 lParam
以单击栏上的所需按钮。文档似乎也没有多大帮助。
您能建议吗?
基于cmets,我也试过UIAutomation
。我可以使用以下代码找到工具栏:
AutomationElement mainWindow = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Migration Expert"));
AutomationElement toolbar = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ClassNameProperty, "msvb_lib_toolbar"));
但是从这里开始,我不确定该怎么做,因为 Spy++ 没有显示该对象的更多子对象:
看着这个AutomationElement
的Current
属性,我看不到任何东西跳出来,但BoundingRectangle
似乎表明我找到了正确的元素。
使用inspector.exe
也不表示工具栏上有任何子项。
【问题讨论】:
***.com/questions/43083781/… 我不知道长度或宽度是否真的很重要。我的窗户会在短时间内出现并关闭,大小无关紧要。请参阅:pinvoke.net/default.aspx/user32/… 这是您的问题和解决方案:You can't simulate keyboard input with PostMessage。 @IInspectable 我不想模拟键盘输入 @RitaHan-MSFT 是的,它把整个工具栏看作一个东西,没有选择按钮 【参考方案1】:不是一个真正理想的解决方案,但我使用 pywinauto
和 pyautogui
的组合得到了一些快速而肮脏的工作。
import pyautogui
import subprocess
import sys
import time
import os
from os import path
from glob import glob
from subprocess import check_output
from pywinauto import application
def click_at_image(image):
location = pyautogui.locateOnScreen(image)
buttonx, buttony = pyautogui.center(location)
pyautogui.click(buttonx, buttony)
def get_dcf_filepaths():
files = []
start_dir = redacted
pattern = "*.DCF"
for dir, _, _ in os.walk(start_dir):
files.extend(glob(os.path.join(dir, pattern)))
return files
def get_csv_paths(paths):
csv_paths = []
for p in paths:
csv_paths.append(p.replace(redacted,redacted).replace("DCF","csv").replace("dcf","csv"))
return csv_paths
def main():
app = application.Application().start(redacted)
files = get_dcf_filepaths()
csv_paths = get_csv_paths(files)
time.sleep(3)
click_at_image("new_button.png") #Open new project
for i in range(0, len(files)):
if (path.exists(csv_paths[i])):
#os.remove(csv_paths[i])
continue
time.sleep(1)
# Click on nxt icon in dialog
click_at_image("nxt_button.png")
# Enter file path into OFD
app.Open.Edit.SetText(files[i])
pyautogui.press('enter')
pyautogui.press('enter')
time.sleep(1)
# Click on m2c icon in toolbar
click_at_image("m2c_button.png")
# Wait for Excel to open
time.sleep(6)
# Open Save as dialog and browse
pyautogui.press('alt')
pyautogui.press('f')
pyautogui.press('a')
pyautogui.press('o')
time.sleep(2)
pyautogui.press('backspace')
# Enter file path
pyautogui.write(csv_paths[i], interval=0.01)
#click_at_image("dummy.png")
# Change file type to CSV and ignore any popups
click_at_image("dd.png")
time.sleep(1)
click_at_image("csv.png")
pyautogui.press('enter')
pyautogui.press('enter')
pyautogui.press('enter')
time.sleep(2)
# Kill excel
pyautogui.hotkey('alt', 'f4')
# Pull main window back to top
app.top_window().set_focus()
time.sleep(1)
# New project
click_at_image("new_button.png")
time.sleep(0.50)
# Don't save last one
click_at_image("no.png")
if __name__ == "__main__":
main()
基本上我不得不求助于使用屏幕抓取来单击不可访问的按钮。如果这是为了需要更健壮的东西,我会在C#
中直接使用Win32
API 来完成此操作,除了屏幕抓取以及一些额外的检查以等待窗口出现而不是使用愚蠢的计时器.
话虽如此,这很有效,可能对未来的读者有所帮助。
【讨论】:
以上是关于单击其他程序工具栏中的按钮的主要内容,如果未能解决你的问题,请参考以下文章
excel总出现正在等待其他某个应用程序以完成对象链接与嵌入操作,然后卡死
如何使用 Qt Creator 将按钮单击信号(“触发”信号)与工具栏中的用户按钮的动作/插槽功能连接起来?