假设你不明白什么
#define ID_BUTTON 1
甚至:
#define、const、constexpr 和 enum 语句不创建变量;他们创建cconstants。变量和常量都是标识符,它们引用程序中的值。区别在于常量不能在运行时改变,而变量可以。
#define 不创建任何普通常量,但是。它实际上告诉编译器的一部分称为预处理器,将源代码中的文本ID_BUTTON 实际替换 为字符串1。这可能很有用,这是您必须为 C 做的事情,但在 C++ 中,constexpr(在 C++11 中引入)通常更理想。有关更多信息,请参阅 Christian Hackl 的回答。
如果您打算使用常量将值传递给 API,这是您计划使用 ID_BUTTON 执行的操作,API 通常会告诉您它期望的类型,因此您可以使用该类型而不是让编译器确定工作的最佳类型。但是,请参阅下面关于 Windows 中的控件标识符的讨论,因为 ID_BUTTON 的特定情况有一个问题。
如果您可以控制类型,则必须花更多的心思来确定要使用的类型。在某些情况下,语言的类型提升规则可以让你在没有类型的情况下只说1,但如果你要创建已知的小整数或大整数、位字段或浮点数,你需要使用适当的类型名称或限定符(short、long、unsigned、float、double 等)。弄清楚去哪里需要一点时间,但是一旦你做的足够多,你就会自然而然地去做。
假设您不了解 Windows 中的控件标识符的工作原理:
大部分采用控制标识符的API函数,如GetDlgItem(),将控制标识符作为int;因此,您的控件标识符应具有 int 类型。
但是,CreateWindow() 和 CreateWindowEx() 期望控件标识符作为倒数第三个参数。此参数的类型为HMENU。 C++ 不会让您将int 推入HMENU,因此您必须使用演员表:(HMENU) ID_BUTTON。 (可能有一个等效的 C++ 风格的演员表,但我不知道/忘记它是什么。)
此外,如果您要使用资源文件,则必须使用#define 语句来创建ID_xxx 常量名称,因为资源文件格式没有没有const、constexpr 或enum。在这种情况下,继续使用 #define 作为标识符,将这些 #defines 放入它们自己的包含文件中,并将 #include 从 C++ 源文件和资源文件中放入该文件。
如果您不使用资源文件,则根本不必担心使用控件标识符;只需对每个控件直接使用HWND。如果您需要在窗口中进行选项卡导航或其他对话框消息处理,您仍然应该分配控件标识符,但除此之外,您可以直接使用HWNDs。 (我忘记了标签导航中是否涉及控件标识符。)
最后,有许多对对话管理器具有特殊意义的预定义控件标识符。这是来自微软的 winuser.h:
/*
* Dialog Box Command IDs
*/
#define IDOK 1
#define IDCANCEL 2
#define IDABORT 3
#define IDRETRY 4
#define IDIGNORE 5
#define IDYES 6
#define IDNO 7
#if(WINVER >= 0x0400)
#define IDCLOSE 8
#define IDHELP 9
#endif /* WINVER >= 0x0400 */
您自己的控件标识符应避免与这些冲突;您的 ID_BUTTON 与 IDOK 冲突。 (如果它们确实发生冲突,您会看到奇怪的事情,例如,您的控件在对话框管理器知道的键盘快捷键上激活。)此问题的规范解决方案是在 100 开始对控件标识符进行编号(我相信Visual Studio 对此负责,但我不确定)。