在 C++ 程序中多次使用 FindWindows?

2024-05-08

我使用以下代码(C++)来获取窗口(另一个应用程序)的句柄并向其中一个按钮发送消息以模拟单击,并且它可以正常工作。

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {

    mdv.test_list[mdv.counter] = hwnd;
    mdv.counter++;

    return TRUE;
}

void MDV::Jog()
{
    HWND WindowHandle;
    WindowHandle = FindWindow(NULL,L"Jog Program");
    EnumChildWindows(WindowHandle, EnumChildProc, 0);
    SendMessage(mdv.test_list[25], BM_CLICK, 0, 0);
}

然而,这会导致一个新的弹出窗口(标题:警告),其中有两个按钮是和否。我想选择“是”并尝试了以下操作

BOOL CALLBACK EnumChildProc_YN(HWND hwnd, LPARAM lParam) {

    mdv.list_yn[mdv.counter_yn] = hwnd;
    mdv.counter_yn++;

    return TRUE;
}

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {

    mdv.test_list[mdv.counter] = hwnd;
    mdv.counter++;

    return TRUE;
}

void MDV::Jog()
{
    HWND WindowHandle;
    WindowHandle = FindWindow(NULL,L"Jog Program");
    EnumChildWindows(WindowHandle, EnumChildProc, 0);
    SendMessage(mdv.test_list[25], BM_CLICK, 0, 0);

    HWND YNHandle;
    YNHandle = FindWindow(NULL, L"Warning");
    EnumChildWindows(YNHandle, EnumChildProc_YN, 0);
    SendMessage(mdv.list_yn[0], BM_CLICK, 0, 0);

}

但它不模拟第二次点击。我对 win32 API 比较陌生。任何帮助表示赞赏。


正如评论指出的那样,您可以使用用户界面自动化 https://learn.microsoft.com/en-us/windows/win32/winauto/entry-uiauto-win32而不是向按钮发送点击消息。 以messagebox的对话框为例:

#include <Windows.h>
#include <iostream>
#include <thread>
#include <tchar.h>
#include <oleacc.h>
#include <UIAutomation.h>
using namespace std;

HWINEVENTHOOK  EventHook = (HWINEVENTHOOK)-1;
IUIAutomation* pClientUIA;
HRESULT click_window(HWND hwnd)
{
    HRESULT hr = S_OK;
    IUIAutomationElement* pElement;
    hr = pClientUIA->ElementFromHandle(hwnd, &pElement);
    if (S_OK != hr)
    {
        printf("ElementFromHandle error: %d\n", GetLastError());
        return hr;
    }

    IInvokeProvider* pPattern;
    hr = pElement->GetCurrentPattern(UIA_InvokePatternId, (IUnknown**)&pPattern);
    if (S_OK != hr)
    {
        printf("GetCurrentPattern error: %d\n", GetLastError());
        return hr;
    }

    hr = pPattern->Invoke();
    if (S_OK != hr)
    {
        printf("Invoke error: %d\n", GetLastError());
        return hr;
    }
    return hr;
}
void __stdcall Wineventproc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD idEventThread, DWORD dwmsEventTime)
{
    if (event == EVENT_OBJECT_CREATE)
    {
        IAccessible* pIAccessible = NULL;
        VARIANT var;
        HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pIAccessible, &var);
        if (SUCCEEDED(hr) && pIAccessible)
        {
            BSTR str;
            hr = pIAccessible->get_accName(var, &str);
            if (S_OK != hr)
            {
                printf("get_accName error: %d\n", GetLastError());
                return;
            }
            wprintf(L"%s\n", str);
            if (wcscmp(str, L"Yes") == 0) // choose the button option you want to click
            {
                hr = click_window(hwnd);
                PostQuitMessage(0);
            }
            SysFreeString(str);
        }
    }
}

DWORD WINAPI SetHook(LPVOID lpParameter)
{
    if (!(EventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, Wineventproc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS)))
    {
        int i = GetLastError();
        cout << "Failed to install MouseHook hook!   " << i << endl;
        return FALSE;
    }
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    UnhookWinEvent(EventHook);
    return TRUE;
}

static HWND hbutton = 0;
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {

    TCHAR name[255] = {};
    SendMessage(hwnd,WM_GETTEXT,255,(LPARAM)name);
    if (_tcscmp(name, L"Button_Name") == 0)
    {
        hbutton = hwnd;
        return FALSE;
    }
    return TRUE;
}

int main()
{
    CoInitialize(0);
    DWORD tid;
    HANDLE hThread = CreateThread(0, 0, SetHook, 0, 0, &tid); // wait for the dialog created event. 
    HRESULT hr;
    hr = CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, IID_IUIAutomation, reinterpret_cast<void**>(&pClientUIA));
    if (S_OK != hr)
    {
        printf("CoCreateInstance error: %d\n", GetLastError());
        return FALSE;
    }

    HWND WindowHandle;
    WindowHandle = FindWindow(NULL, L"Jog Program");
    EnumChildWindows(WindowHandle, EnumChildProc, 0);

    // make sure the event hook has been successfully or failed to set.
    while (EventHook != (HWINEVENTHOOK)-1); 
    if (EventHook)
    {
        click_window(hbutton);
    }
    WaitForSingleObject(hThread, INFINITE);
    CoUninitialize();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C++ 程序中多次使用 FindWindows? 的相关文章

随机推荐

  • Dojo DataGrid (DGrid) 添加复选框列

    我在用DojoDgrid 但是我正在尝试添加一个复选框列 但我不确定该方法 我一直在看的大多数教程都遵循不同的代码结构 我无法创建复选框列 我想创建一个复选框列来选择行 Code 这里还有一个Fiddle http jsfiddle net
  • CodingBat sum67:为什么这个解决方案是错误的?

    我正在解决以下codingbat问题 返回数组中数字的总和 但忽略以 6 开头并延伸到下一个 7 的数字部分 每个 6 后面至少有一个 7 如果没有数字则返回 0 sum67 1 2 2 5 sum67 1 2 2 6 99 99 7 5
  • 从 C++ 文件中删除无用的行

    很多时候 当我调试或重用某些代码时 文件开始获取不执行任何操作的行 尽管它们可能在某一时刻执行了某些操作 像向量和填充然后不再使用之类的东西 定义但从未使用的类 结构 以及声明但从未使用的函数 我知道在很多情况下 其中一些东西并不是多余的
  • 如何通过代码改变Android SlidingDrawer的方向?

    当我从横向模式更改为纵向模式时 我无法找到设置 SlidingDrawer 方向的方法 反之亦然 最初我将 xml 的方向设置为垂直 当手机处于横向模式时 我需要将方向更改为水平 因此我将手柄放在左侧 有人有什么想法吗 我认为按照标准这是不
  • 在 cURL 命令和 postman 中的 Firebase Cloud Messaging 中获取无效令牌

    伙计们 我正在尝试获取有关应用程序实例的信息 并且我还尝试将应用程序实例订阅到 Google Cloud Messaging 主题 但问题是每当我尝试使用server key它给我带来了错误invalid token当我尝试使用web ap
  • 使用 insert into ... select 会导致 select 附近的语法不正确,为什么?

    如何在 INSERT 操作中进行 SELECT insert into tableX a id b id VALUES SELECT service id FROM tableY WHERE id 10 2 但服务器返回语法错误 为什么 S
  • Perl Mongo 查找对象 ID

    你会认为这是一件简单的事情 我有一个集合中的对象 ID 列表 我想根据对象 ID 获取单个记录 谷歌搜索过 但没有任何帮助 所以我有对象 ID 5106c7703abc120a04070b34 my client MongoDB Mongo
  • Python 包?

    好吧 我认为无论我做错了什么 它可能都是显而易见的 但我无法弄清楚 我已经阅读并重新阅读了有关包的教程部分 我唯一能想到的是这不起作用 因为我直接执行它 这是目录设置 eulerproject init py euler1 py euler
  • MySQL CREATE TABLE 语句上的外键错误(错误:150)

    我觉得我已经在一对非常简单的创建表语句上尝试了一切可能的方法 类型匹配 我尝试使用 ENGINE InnoDB 等 但很困惑为什么我收到外键错误 我已经离开 SQL 一段时间了 所以这可能是一个简单的问题 mysql gt CREATE T
  • 如何从 Flutter Web 中的 URL 中删除哈希 (#)

    Flutter Web 项目的默认 URL 定义了包含主题标签的 URL 如下 http localhost 41521 peaple 我想删除这个 如下所示 http localhost 41521 peaple 我怎么解决这个问题 您现
  • 如何验证公钥是由您的私有 CA 颁发的?

    我创建了一个 CA 证书 并用它来颁发公钥 在将来的某个日期 我需要验证加载的证书是否由我的 CA 颁发 如何使用 OpenSSL API c 做到这一点 我已将 verify c 在 openssl apps 中 减少到所需的最少功能 假
  • 如何使用 Relay 发送临时查询?

    我是 Relay 的新手 仍在尝试了解它 根据我的理解 Relay 将查询与组件联系起来 这样 您可以说组件需要从 GraphQL 服务器提供 x y 和 z 据我了解 官方react relay库将在适当的时间分派这些查询 可能是在组件即
  • c - 将 .data 发送到不同的部分

    我想把其中的符号 data为特定 C 文件生成的节并将它们放在不同的节中 例如 mydata 在最终的可执行文件中 例如 normaldata c char my str this should appear in data special
  • 在 Microsoft Sql Server 2008R2 及更高版本上隐藏登录数据库 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 请任何人协助隐藏 sql server 2008R2 或更高版本上的可用数据库 我有一个新的登录用户 已映射到特定数据库 使用特定登录用户登录时 我可
  • 正则表达式匹配非整数?

    尝试创建一个忽略正确整数的正则表达式 1 5 999等 和正斜杠 但在其他所有内容中都找到匹配项 例如 它将找到以下匹配项 test test1 test 1 但忽略了 1 55 7 这是为了模组重写 0 9 我想应该可以解决这个问题 它将
  • JQuery UI Sortable - 将占位符添加到列表中以模拟空白空间

    JQuery UI Sortable 对于没有间隙的列表非常有用 但假设我想渲染有间隙的项目列表 例如 1 2 空 4 5 6 空 8 其中数字表示插槽编号 预期的行为是 如果用户将一个元素拖动到 2 插槽上 则 2 值将被推送到空插槽 3
  • 两组点之间的距离[重复]

    这个问题在这里已经有答案了 因此 在查看了 stackoverflow 上提出的各种问题后 我仍然无法理解 R 中的 dist 函数 甚至无法理解一般的距离矩阵 所以我有两个带有 xy 坐标的数据框 df1 lt data frame x
  • 如何找到每个分类变量的连续变量的平均值

    我想在 y 轴上绘制连续的 BMI 在 x 轴上绘制家庭收入的分类变量 并且我希望该图绘制每个类别的平均 BMI 然而 我不知道如何找到家庭收入每个因素的平均体重指数 Dataset nh 5994 total IDs with Obser
  • Spring Boot,使用 EhCache 进行缓存

    我需要在我的应用程序中缓存一些数据 我正在考虑使用 Ehcache 我有几个问题 Ehcache需要另外一台服务器吗 我需要其他客户端来使用 Ehcache 吗 Ehcache 如何与多个实例配合使用 是否有可能使用 Ehcache 创建类
  • 在 C++ 程序中多次使用 FindWindows?

    我使用以下代码 C 来获取窗口 另一个应用程序 的句柄并向其中一个按钮发送消息以模拟单击 并且它可以正常工作 BOOL CALLBACK EnumChildProc HWND hwnd LPARAM lParam mdv test list