简体   繁体   English

单击其他程序工具栏中的按钮

[英]Click Button in Toolbar of Other Program

I'm trying to automate some stuff on a legacy application that I don't have the source to.我正在尝试在我没有来源的遗留应用程序上自动化一些东西。 So I'm essentially trying to use the Windows API to click the buttons I'll need on it.所以我实际上是在尝试使用 Windows API 来单击我需要的按钮。

There is a toolbar of type msvb_lib_toolbar that looks like this:有一个msvb_lib_toolbar类型的工具栏,如下所示:

工具栏

I can get a handle to it (I think) by using this code:我可以通过使用以下代码来处理它(我认为):

IntPtr window = FindWindow("ThunderRT6FormDC", "redacted");
IntPtr bar = FindWindowEx(window, IntPtr.Zero,"msvb_lib_toolbar",null);

Looking at the docs, it seems I should be able to use SendMessage and the TB_PRESSBUTTON message to click these buttons:查看文档,似乎我应该能够使用SendMessageTB_PRESSBUTTON消息来单击这些按钮:

[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);

However, I'm not sure how to go about setting the wParam and lParam to click the wanted button on the bar.但是,我不确定如何设置wParamlParam以单击栏上的所需按钮。 The documentation doesn't seem to be helping much either.该文档似乎也没有太大帮助。

Could you please advise?您能否提一些建议?


Based on comments, I've also tried UIAutomation .根据评论,我也尝试过UIAutomation I can locate the toolbar using the following code:我可以使用以下代码找到工具栏:

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"));

But from here, I'm not sure what to do as Spy++ shows no further children of this object:但是从这里开始,我不确定该怎么做,因为 Spy++ 没有显示此 object 的其他子代:

间谍++

Loking at the Current property of this AutomationElement I can't seen anything jumping out at me but the BoundingRectangle does seem to indicate that I've found the right element.看着这个AutomationElementCurrent属性,我看不到任何东西跳出来,但BoundingRectangle似乎确实表明我找到了正确的元素。

调试器

Using inspector.exe also doesn't indicate any children on the toolbar.使用inspector.exe也不表示工具栏上有任何子项。

督察

Not really an ideal solution but I got something quick and dirty working using a combination of pywinauto and pyautogui .不是一个真正理想的解决方案,但我使用pywinautopyautogui的组合得到了一些快速而肮脏的工作。

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()

Essentially I had to resort to using screenscraping to click the non-accessible buttons.本质上,我不得不求助于使用屏幕抓取来单击不可访问的按钮。 If this was for something that needed to be more robust, I'd have done this in C# using the Win32 API directly for everything except the screen scraping with some additional checks to wait for windows to appear rather than using dumb timers.如果这是为了需要更强大的东西,我会在C#中使用Win32 API 直接针对所有内容执行此操作,除了屏幕刮擦并进行一些额外的检查以等待 Z0F4137ED1502B5045D6083AA258B 出现,而不是使用愚蠢的计时器出现。

That being said, this works and may be helpful for future readers.话虽如此,这很有效,可能对未来的读者有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM