如何在 C++ 中与其他应用程序交互?

Posted

技术标签:

【中文标题】如何在 C++ 中与其他应用程序交互?【英文标题】:How do I interact with other applications in C++? 【发布时间】:2014-01-05 18:45:08 【问题描述】:

我想知道有没有办法改变其他应用程序的定位是C++。我想要做的是在屏幕上移动活动窗口。例如,我想以循环移动方式移动 Firefox。 2:17 http://www.youtube.com/watch?v=TLqPepLhDTY&list=WL8D6E1A188FBFE181 浏览器移动了,怎么办?

【问题讨论】:

【参考方案1】:

您应该首先使用FindWindow() 函数获取窗口的HWND。然后你可以简单地使用 SetWindowPos()MoveWindow() 和找到的 HWND 来改变位置。

【讨论】:

【参考方案2】:

在 linux、mac 和 FreeBSD 上:这是一个快速脚本,它使用 xdotool 沿着某个轨迹滑动 chrome 浏览器:

#!/bin/bash

while read x y
do 
    xdotool search --class google-chrome windowmove $x $y
    sleep 0.001
done <<TRAJECTORY
624 624
634 614
644 624
654 614
664 624
674 614
684 624
694 614
704 624
TRAJECTORY

注意事项

我让轨迹变得很无聊 不过,您可以使用一些基本的三角函数来使运动成为圆形。该示例显示您甚至可以从列表中输入形状 该示例对目标窗口进行硬编码(但您可以使用例如selectwindow 让用户单击任何窗口进行操作) 再次,您的想象力是极限

【讨论】:

很有趣,但是超出了 OP 请求...(这里没有 c++ 和 windows 的东西) @pepper_chico 好吧。我在回答他的问题,而不是标签。通常会涉及到一定程度的X/Y asking。此外,没有什么可以阻止他 (a) 从 c++ 驱动 xdotool 或 (b) 直接从 c++ 使用 xlib+xtst,使用 the source code of xdotool 作为参考。即使对于商业应用程序,许可证似乎也不排除这种情况。 对我来说似乎不是一个干净的解决方案;调用外部程序来解决问题是 IMO 肮脏的。 @Paranaix 我不知道在没有该进程合作的情况下干预另一个进程的窗口位置可能是“干净的”xD 此外,您还没有阅读我评论中的(b) 部分.这是一个非常具体的例子,说明它是如何完成的。如果 OP 喜欢它,他将能够以他喜欢的方式编写代码。 @sehe 一个窗口通常更多地属于一个操作系统作为一个进程,因此有干净的方法来完成这样的任务,即调用提供的操作系统函数。虽然我个人不喜欢这个解决方案,但我接受这一点,它是一个解决方案,因此我也没有否决它。【参考方案3】:

实际上在您没有创建的窗口上使用FindWindow 很困难,因为您需要在该窗口上使用的类名。请改用EnumWindows。这是一个代码示例,用于搜索并关闭名称中包含“Firefox”的任何窗口。持续发送WM_MOVE 而不是 WM_CLOSE 来移动窗口。

#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;

#pragma comment(lib, "user32.lib")

HWND windowHandle;

BOOL CALLBACK MyEnumProc(HWND hWnd, LPARAM lParam)

    TCHAR title[500];
    ZeroMemory(title, sizeof(title));

    //string strTitle;

    GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));

    //_tprintf(_T("Found window: %s\n"), title);

    //strTitle += title; // Convert to std::string
    if(_tcsstr(title, _T("Firefox")))
    
        windowHandle = hWnd;
        return FALSE;
    
    return TRUE;


int main()

    while (true)
    
        windowHandle = NULL;
        EnumWindows(MyEnumProc, 0);

        cout << endl << endl << "Desired window handle: " << windowHandle << endl << "Sending WM_CLOSE message..." << endl;
        SendMessage(windowHandle, WM_CLOSE, NULL, NULL);
    
    return 0;

【讨论】:

可以查类名,FindWindow也可以查名字。 这通常更可靠,因为任何窗口都可以有标题“Firefox” 但是为什么要连续发送 WM_MOVE 而不是一次呢? @gdany 如果您只想移动一次窗口,他们只发送一次。我的印象是您想以某种模式(如圆圈)移动窗口。 是的,我在这方面做了一些工作,我意识到这就是 while 循环存在的原因。 :D【参考方案4】:

哇,谢谢你们,我没想到会这么快回答。我会尝试看看哪个代码最适合使用。它终于按我想要的方式工作了。代码如下所示:

#include <windows.h>
#include <tchar.h>
#include <iostream>

using namespace std;

#pragma comment(lib, "user32.lib")

HWND windowHandle;

BOOL CALLBACK MyEnumProc(HWND hWnd, LPARAM lParam)

    TCHAR title[500];
    ZeroMemory(title, sizeof(title));

    //string strTitle;

    GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));

    //_tprintf(_T("Found window: %s\n"), title);

    //strTitle += title; // Convert to std::string
    if(_tcsstr(title, _T("Firefox")))
    
        windowHandle = hWnd;
        return FALSE;
    
    return TRUE;

int xLoc = 10;
int yLoc = 50;

int getXLoc()
    if(xLoc<70&&yLoc<=30)
        xLoc += 1;
        Sleep(10);
    else if(yLoc>30)
        xLoc -= 1;
        Sleep(10);
    
    return xLoc;

int getYLoc()
    if(yLoc>10&&xLoc<30)
        yLoc -= 1;
        Sleep(10);
    else if(xLoc>=30&&yLoc<70)
        yLoc += 1;
        Sleep(10);
    
    return yLoc;


int main()

    windowHandle = NULL;
    EnumWindows(MyEnumProc, 0);
    while(true)
        MoveWindow(windowHandle, getXLoc(), getYLoc(), 1220, 930, false);
        Sleep(5);
    
    return 0;

【讨论】:

以上是关于如何在 C++ 中与其他应用程序交互?的主要内容,如果未能解决你的问题,请参考以下文章

在 Agora IO 中与参与者共享屏幕共享控件

在 NodeJS 中与 C++ 代码通信

如何在 iOS 应用中与 UIButton 的特定区域进行交互

如何在我的 Rails 应用程序中与亚马逊产品广告 API 交互?

在颤振/飞镖中与图像下的小部件交互

在 Android 应用程序中与远程 MySQL 数据库交互