【问题标题】:How to get the class name of a window with C如何用C获取窗口的类名
【发布时间】:2020-10-19 17:40:40
【问题描述】:

目的:用纯C检索当前前台窗口的类名。

我有以下代码来检索类名:

PWSTR win_class = NULL; 

GetClassNameW(hwnd,&win_class,MAX_PATH);

if(win_class != NULL)
   free(win_class);

我收到以下警告:

警告 C4047:“函数”:“LPWSTR”的间接级别不同 来自“PWSTR *”
警告 C4024:“GetClassNameW”:不同类型 对于形参和实参2

我有两个问题:如何解决这些警告,以及我应该如何创建if 条件来验证函数GetClassName 的结果并将win_class 的值设置为“未找到”以防万一函数找不到类名?

【问题讨论】:

  • man page 显示,int GetClassNameW(HWND hWnd, LPWSTR lpClassName, int nMaxCount) 需要一个 LPWSTR 参数来存储类名。 “如果函数成功,则返回值是复制到缓冲区的字符数,不包括终止的空字符。” 另外,我不认为free(win_class); 是完成的方式一个东西。你怎么知道它是由malloc获得的?这是XY problem?

标签: c winapi


【解决方案1】:

GetClassNameW() 函数为返回的类名分配所需的内存 - 必须这样做(或者只是提供自动存储)。

要检查是否成功,只需测试函数的返回值:如果成功,那将是类名字符串的长度(以字符为单位);如果失败,则该值将为零。

这是一个简短的、可运行的程序,用于获取控制台窗口的类名:

#include <Windows.h>
#include <stdio.h>
int main()
{
    HWND hwnd = GetConsoleWindow();
    wchar_t win_class[_MAX_PATH];
    int status = GetClassNameW(hwnd, win_class, _MAX_PATH);
    if (!status) wcscpy(win_class, L"NOT FOUND");
    printf("%ls\n", win_class);
    return 0;
}

【讨论】:

  • 伟大的 MWE 答案。应该是大多数问题的蓝图。
【解决方案2】:

当调用GetClassNameW() 时,您传递的是PWSTR* (wchar_t**),而LPWSTR (wchar_t*) 是预期的。这就是编译器所抱怨的。

GetClassName() 要求您预先分配一个字符缓冲区并传入一个指向它的指针以及缓冲区大小。该函数不会像您期望的那样分配缓冲区并将指针返回给您。它只会根据需要填充您提供的缓冲区。

试试这样的:

WCHAR win_class[256] = {0};
int win_class_len = 0;

HWND hwnd = GetForegroundWindow();
if (!hwnd)
{
    // error handling as needed...
    lstrcpyW(win_class, L"WINDOW NOT FOUND");
    win_class_len = lstrlenW(win_class);
}
else
{
    win_class_len = GetClassNameW(hwnd, win_class, 256);
    if (win_class_len == 0)
    {
        DWORD err = GetLastError();
        // error handling as needed...
        lstrcpyW(win_class, L"CLASS NOT FOUND");
        win_class_len = lstrlenW(win_class);
    }
}

// use win_class as needed, up to win_class_len characters...

【讨论】:

    【解决方案3】:

    TCHAR 是适用于 Unicode 和 ANSI 的通用字符类型。 GetClassName 是替换为GetClassNameAGetClassNameW 的对应函数。如果您需要静态字符串,请使用 TEXT() 宏,例如 TCHAR * s = TEXT("abc");

    TCHAR win_class[MAX_PATH];
    int res = GetClassName( hwnd, win_class, MAX_PATH );
    if ( res > 0 )
       // success
    

    您的错误是 win_class 是未分配 (NULL) 字符串指针。 GetClassName 需要有效的缓冲区内存地址。

    【讨论】:

    • 感谢@i486。我对你的回答很感兴趣。 Getclassname、GetclassnameW 和 GetclassnameA 有什么区别?与C语言一起使用有什么特殊规则吗?。
    • @sergioMoreno GetClassNameW() 适用于 Unicode wchar_t 字符串,GetClassNameA() 适用于 ANSI char 字符串。 TCHAR 是映射到wchar_tchar 的预处理器宏,GetClassName() 是映射到GetClassNameWGetClassNameA 的预处理器宏,这取决于是否分别定义了UNICODE。所有其他 Win32 API A/W 类型/函数都相同。
    • @i486 "您的错误是 win_class 未分配 (NULL) 字符串指针" - 这不是编译器失败的原因。是的,那是错误的,但失败是因为 OP 的代码传递了 PWSTR* (wchar_t**),而 PWSTR (wchar_t*) 是预期的。
    • @sergioMoreno 使用 GetClassName 是“正常方式”——甚至 MSDN 也描述了没有 A/W 后缀的函数。使用TCHAR / LPTSTR 类型和TEXT() 用于字符串常量,您就有了可移植的代码。可以打开winuser.h等头文件,看看它们是如何定义GetClassNameTCHAR等的。
    【解决方案4】:

    您需要检查您的功能是否成功。为此,请打印函数的返回值。

    失败将由值 0 表示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-14
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多