【问题标题】:EnumWindows not workingEnumWindows 不工作
【发布时间】:2017-01-09 12:26:21
【问题描述】:

我正在创建一个 dll 文件。

我的代码:

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);

void test() {
    EnumWindows(EnumWindowsProc, NULL);
}

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    char class_name[80];
    char title[80];
    GetClassName(hwnd, (LPWSTR) class_name, sizeof(class_name));
    GetWindowText(hwnd, (LPWSTR) title,sizeof(title));
    std::string titlas(title);
    std::string classas(class_name);
    Loggerc(titlas);
    Loggerc("Gooing");
    return TRUE;
}

那我就打test()

在日志中,titlas 为空,代码停止。

当我在带有 CodeBlock 的 Win32 应用程序中尝试此代码时,一切正常,所有标题都显示出来。但在 dll 中,它不起作用。

问题出在哪里?

【问题讨论】:

  • 需要注意的一点:char* 不是LPWSTR
  • EnumWindows 有效。您的代码对编译器撒谎,这就是破坏它的原因。你保证你的缓冲区是两倍大小。从那里只会变得更糟。

标签: c++ string winapi unicode vc10


【解决方案1】:
char class_name[80];
char title[80];
GetClassName(hwnd, (LPWSTR) class_name, sizeof(class_name));
GetWindowText(hwnd, (LPWSTR) title,sizeof(title));
std::string titlas(title);
std::string classas(class_name);

考虑到自 VS2005 以来,默认值一直以 Unicode 模式(而不是 ANSI/MBCS)构建,并且您有那些(丑陋的 C 风格)(LPWSTR) 强制转换,我假设您在编译时遇到了编译时错误将基于字符的字符串缓冲区传递给 GetClassName() 和 GetWindowText() 等 API,然后您尝试使用强制转换修复这些错误。
那是错误的。编译器实际上是在帮助您解决这些错误,因此请遵循它的建议,而不是将编译器错误排除在外。

假设 Unicode 构建,您可能希望使用 wchar_tstd::wstring 而不是 charstd::string,和 _countof() 而不是 sizeof() 以获取 wchar_ts 中的缓冲区大小,not 以字节 (chars) 为单位。

例如:

// Note: wchar_t used instead of char
wchar_t class_name[80];
wchar_t title[80];

// Note: no need to cast to LPWSTR (i.e. wchar_t*)
GetClassName(hwnd, class_name, _countof(class_name));
GetWindowText(hwnd, title, _countof(title));

// Note: std::wstring used instead of std::string
std::wstring titlas(title);
std::wstring classas(class_name);

如果您的代码的其他部分确实使用std::string,您可能希望将存储在std::wstring(由Windows API 返回)中的UTF-16 编码文本转换为UTF-8 编码文本并将其存储在@ 987654335@ 个实例。

【讨论】:

  • @EvaldasJankauskas:不客气。希望你吸取了教训,一般来说不要关闭 C++ 编译器警告 :)
  • @EvaldasJankauskas 要吸取的教训是永远不要转换字符串类型。如果您发现自己在转换字符串类型,则代码会自动受到怀疑,并且在大多数情况下是错误的。如果一个函数想要一个WidgetString,你提供一个WidgetString,而不是强制转换的东西。强制转换不会将一种字符串类型转换为另一种 - 有可用的 Windows 函数来进行字符串转换。
  • @PaulMcKenzie:“强制转换不会将一种字符串类型转换为另一种” - 绝对语句很容易被反驳,只有一个反例,例如实现user-defined conversion 运营商。除非需要,否则不应使用铸件。这并不会使它们总是成为错误的工具(尽管 C 风格的强制转换在 C++ 中没有位置)。
  • 要吸取的教训是,除非您完全知道自己在做什么,否则永远不要使用强制转换来隐藏编译器警告。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多