包含winuser.h时出错。它将ChangeMenu定义为ChangeMenuW或ChangeMenuA

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了包含winuser.h时出错。它将ChangeMenu定义为ChangeMenuW或ChangeMenuA相关的知识,希望对你有一定的参考价值。

在Windows上使用Qt应用程序。我只在我的源文件中包含QVboxLayout,这会导致错误,因为它的宏会覆盖我的方法名称。

foo.hpp
class foo
{
    ChangeMenu();
}

foo.cpp
#include "foo.hpp"
#include "QVBoxLayout" // <--- this includes winuser.h

foo::ChangeMenu(){};

现在发生的事情是winuser.h有一个宏

#ifdef UNICODE
#define ChangeMenu  ChangeMenuW
#else
#define ChangeMenu  ChangeMenuA
#endif // !UNICODE

这会将我的函数定义更改为ChangeMenuW,但我的声明仍然是ChangeMenu。

我该怎么解决这个问题? winuser.h如何将这样一个“普通”名称定义为宏?

winuser.h的版本是“windows kits 10 include 10.0.16299.0”

答案

几乎任何处理字符串的Windows API实际上都是一个解析为A或W版本的宏。没有办法,你可以:

  • 避免包括windows.h,但正如你所注意到的那样,它会穿过;
  • 在定义/使用你的函数之前,残酷的#undef宏;这是囤积这种普通和非宏观标识符的合理惩罚,但是繁琐而其他一些代码实际上可能需要Win32功能;
  • 只是接受它作为一个悲伤的生活事实,并避免所有相关的Win32 API名称;如果您使用Qt并遵循其命名约定,它应该很容易,因为Qt函数使用lowerCamelCase(而不是Win32 UpperCamelCase);
  • 在你的标题中明确地直接包括windows.h(可能在#ifdef _WIN32下);这将确保您的标识符将在所有实例中被宏替换,因此即使编译器实际编译具有不同名称的函数,一切都将正常工作;适用于独立项目,不适合图书馆。 (感谢@Jonathan Potter建议这个)
另一答案

您可以不关心这个问题,虽然您的方法名称将与Windows API相同,但系统不会混合它们(只需在定义/调用的位置统一Unicode)。如果你直接打电话给ChangeMenu(),你会打电话给winapi,如果

foo f;
f.ChangeMenu();

要么

foo::ChangeMenu();(静态)

你会打电话给你的方法。

如果你想禁用winapi:

#ifdef ChangeMenu
#undef ChangeMenu
    //code place that you define/call your own ChangeMenu().
#ifdef UNICODE
#define ChangeMenu  ChangeMenuW
#else
#define ChangeMenu  ChangeMenuA
#endif // !UNICODE
#endif

(看起来很乏味。)

以上是关于包含winuser.h时出错。它将ChangeMenu定义为ChangeMenuW或ChangeMenuA的主要内容,如果未能解决你的问题,请参考以下文章

使用 Qt 的 dumpcpp 时重复的函数名称

使用Qt的dumpcpp时重复的函数名称

windows.h是啥头文件

多次显示同一个窗口

使用 PrincipalContext.ValidateCredentials 对本地计算机进行身份验证时出错?

win32 hello