问题描述
我在使用
获取子字符串时遇到问题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 方法 A2W
和 W2A
,但我建议尽可能使用 std::string
和 std::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
,因此请相应处理。