GetWindowText 和子字符串

问题描述

我在使用

获取子字符串时遇到问题
strstr(a,b);

检查“FiveM”名称是否出现在窗口的标题栏中,因为通常在这个游戏中标题栏也包含更新等

所以我在谷歌上搜索并找到了 GetwindowText 函数

我已经运行了这段代码


    HWND foreground = GetForegroundWindow();
    char window_title[7];

    if (foreground)
    {
        GetwindowText(foreground,(LPWSTR)window_title,7);
    }



    auto output = strstr(window_title,"FiveM");

    printf("%d",output);

没有输出,一切都是 0,但是当我使用函数 GetwindowTextA() 时一切正常,所以我在谷歌上搜索了更多关于这个 getwindow 函数的信息,我发现了这个 sub-workflow 并且我看到了这个

#define GetwindowText GetwindowTextA


in a non-unicode build,GetwindowText and GetwindowTextA are the same thing. [...]

而且我的构建是 unicode 所以这是我必须在最后添加 A 的问题,为什么,以及为什么当我使用 GetwindowTextW aka GetwindowText 获取窗口文本时,一个字符需要更多空间,我想是因为我的方法正确

    char window_title[7];

    if (foreground)
    {
        GetwindowTextW(foreground,7);
        
    }

我也很困惑为什么 strstr() 函数在将输出值打印到控制台时会增加 memory violation 而只是简单地读取它不会引发任何内存冲突

解决方法

GetWindowTextW 以 unicode 宽字符串的形式提供输出。请注意,您可能会超出数组的末尾,因为 nMaxCount 参数是字符数,而不是字节数。这将解释为什么您会看到内存冲突,因为 UTF-16 宽字符包含 2 个字节;您实际上是在告诉 GetWindowTextW 缓冲区可以容纳 14 个字节,而实际上它只有 7 个字节长。

您需要向它传递一个 wchar_t 数组,然后完全在宽字符串(例如 wcslen)中工作或从宽字符串转换为字符串,如下所示: C++ Convert string (or char*) to wstring (or wchar_t*)

您可以使用 MSVC ATL 方法 A2WW2A,但我建议尽可能使用 std::stringstd::wstring


当你在宽字符串上使用字符串方法时,它们行为不正常,因为宽字符串通常包含零作为编码的高字节,字符串方法将其解释为空终止符(例如,在十六进制内存视图中,您可能会看到一些东西像 48 00 45 00 4C 00 4C 00 4F 00 00 00 - 字符串方法将其解释为“H”)


如果您查看 GetWindowText 的声明,您会发现如下内容:

    #ifdef _UNICODE
        #define GetWindowText GetWindowTextW
    #else
        #define GetWindowText GetWindowTextA
    #endif

这解释了为什么在非 Unicode 构建中 GetWindowText 与 GetWindowTextA 相同


另一种可能是使用 GetWindowTextA 并使用字符串完成整个操作,但该选项可能对您不开放。

,

您在处理 Unicode(又名宽)和 ANSI(又名窄)字符串方面非常混乱。您应该选择一种变体并坚持下去。在这种情况下,由于您是为 Unicode 构建的,宽字符串是自然的选择。

所以,代码应该看起来像这样:

HWND foreground = GetForegroundWindow();

if (foreground)
{
    WCHAR window_title[256];
    GetWindowText(foreground,window_title,_countof (window_title));
    const WCHAR *output = wcsstr (window_title,L"FiveM");
    ... 
}

注意事项(排名不分先后):

  • 窗口标题肯定会超过 6 个字符,因此在检索时要留出足够的空间。

  • 为避免代码中出现“幻数”,请在适当的时候使用 _countof

  • strstr(或等价物,wcsstr)的返回类型是 char *(或 WCHAR *),而不是 int ,因此请相应处理。