C Windows-我们可以从鼠标点击某个东西推断出什么;可点击“;?

C Windows-我们可以从鼠标点击某个东西推断出什么;可点击“;?,c,windows,winapi,user-interface,C,Windows,Winapi,User Interface,正如标题所示,我在问,点击屏幕可以发现什么 更准确地说,是否可以检测到对精确元素的单击(可以是用于在通用浏览器上打开新选项卡的+符号,或者是打开的Office文档上的文件,然后另存为…元素)并返回某种类型的已单击内容字符串 通过使用Win32 API,我能够检测鼠标左键是否已被单击: for(character=1; character<=222; character++) { if(GetAsyncKeyState(character) == -32767) {

正如标题所示,我在问,点击屏幕可以发现什么

更准确地说,是否可以检测到对精确元素的单击(可以是用于在通用浏览器上打开新选项卡的
+
符号,或者是打开的Office文档上的
文件
,然后
另存为…
元素)并返回某种类型的已单击内容字符串

通过使用Win32 API,我能够检测鼠标左键是否已被单击:

for(character=1; character<=222; character++) {
    if(GetAsyncKeyState(character) == -32767) {
        ...
        switch(character) {
            case VK_LBUTTON: ...; break;
            ...
        }
    }
}
然而,我不知道点击了什么

你会发现,获取鼠标点击的坐标对我来说毫无用处,除非我知道屏幕上可以点击的所有东西的坐标

我检查了WindowsUI自动化,但大部分都是用C语言编写的,而且,就我个人而言,我更喜欢用C语言编写

很多人告诉我使用web中的一个程序,但正如我所说的,我更喜欢只使用C,而不包括一些外部库


那么:有没有办法通过使用Windows API来确定我是在某些文本编辑器上单击了“新建文件”,还是在VLC上单击了“播放”?

我不是Windows专家,但阅读文档是一种可行的方法:

TCHAR lpClassName[64];
HWND foreground = GetForegroundWindow();
int ret;

ret = GetClassName(foreground, (LPTSTR)lpClassName, 64);
if(ret == 0) {
    // GetLastError and friends...
}
通过这种方式,您应该获得以前使用
RegisterClass()
RegisterClassEx()注册的窗口类的名称。该字符串应该告诉您有关窗口性质的更多信息

注意:由于我不知道/获取Win32数据类型,上面使用的字符数组和/或
GetClassName()
的长度参数可能是错误的


您可以使用
GetClassInfo()
从类中获得更多信息。如需一般参考,请阅读MSDN

您可以在鼠标光标下控制(子)窗口的句柄、文本和类名,逻辑如下:

HWND hWndF = GetForegroundWindow();
if (hWndF != NULL)
{   HWND hWndC;
    TCHAR szClassName[64], szWindowText[256];
    POINT pt;

    GetClassName(hWndF, szClassName, _countof(szClassName));    // main window
    GetWindowText(hWndF, szWindowText, _countof(szWindowText)); // main window

    GetCursorPos(&pt);          // in screen coordinates
    ScreenToClient(hWndF, &pt); // in client coordinates of main window
    hWndC = ChildWindowFromPointEx(hWndF, pt, CWP_ALL);
    if (hWndC != NULL && hWndC != hWndF)
    {   GetClassName(hWndC, szClassName, _countof(szClassName));    // child window
        GetWindowText(hWndC, szWindowText, _countof(szWindowText)); // child window
    }
}

您可以从C使用UI自动化,但这并不是说它会很有趣。无论如何,您都需要这样做,因为Win32通常不知道当您单击时会发生什么。只有应用程序知道这一点。MSDN文档编写得很糟糕;找不到像样的例子。唉,所以我不会用一个文件就把它写出来。c?MSDN文档很好。你只需要知道如何从C中下载COM,一个更为简洁的方法是使用C++。你能加深“C如何使用COM”句吗?为什么你会认为这会产生不同的答案?您已经被告知要使用,但答案没有更改。直到现在,我才设法获取与窗口关联的菜单栏元素数…如果我能够获取已单击菜单栏的哪个元素,那将是一种改进。您是否尝试获取子窗口?也许你点击了标签外的一点。不管怎样,只要菜单是用标签完成的,您就应该在屏幕上找到这些标签(“静态”控件)作为窗口(除非菜单再次关闭)。如果没有任何帮助,您可以使用
GetMenu()
和friends to
GetMenuItemRect()
,这将告诉您屏幕上的菜单位置,您应该能够匹配鼠标单击。但是,我也不认为这是必要的……window类并没有告诉您它的本质。它是一个字符串,由
RegisterClass[Ex]
的调用方(即提供特定窗口类的工具)任意选择。除了
32770
(dialog)和您可以在特殊情况下使用的标准控制类之外,您对这些信息无能为力。例如,您无法查询已接受的控件特定消息。子窗口的
szWindowText
始终为空…如果我获取一个HMENU处理程序并获取菜单的选定项,该怎么办?您只能使用上述逻辑来获取有关子窗口的信息,Humanu不是一个窗口——也要注意,某些应用程序中的一些花哨工具栏在API意义上不是真正的窗口——看起来UI自动化是唯一的出路……那么
PeekMessage
呢?我可以用它来捕获
WM_命令
并对其进行分析您不能使用peek消息来处理属于另一个线程的消息…如果我
hook
这些消息会怎么样?
HWND hWndF = GetForegroundWindow();
if (hWndF != NULL)
{   HWND hWndC;
    TCHAR szClassName[64], szWindowText[256];
    POINT pt;

    GetClassName(hWndF, szClassName, _countof(szClassName));    // main window
    GetWindowText(hWndF, szWindowText, _countof(szWindowText)); // main window

    GetCursorPos(&pt);          // in screen coordinates
    ScreenToClient(hWndF, &pt); // in client coordinates of main window
    hWndC = ChildWindowFromPointEx(hWndF, pt, CWP_ALL);
    if (hWndC != NULL && hWndC != hWndF)
    {   GetClassName(hWndC, szClassName, _countof(szClassName));    // child window
        GetWindowText(hWndC, szWindowText, _countof(szWindowText)); // child window
    }
}