1

我有一个函数位于与 WinMain 不同的 cpp 文件中,调用时将创建一个窗口。但是,该新窗口的 windows 类已在 WinMain 中声明和注册。现在,当我在单独的函数中创建窗口时,我不得不重新声明 CreateWindowEx 函数的第二个和第三个变量:

_In_opt_  LPCTSTR lpClassName,
_In_opt_  LPCTSTR lpWindowName,

因为实际执行创建的函数的位置无权访问在 WinMain 中创建的那些变量。现在......我的疑问是,我的程序实际上是否使用了我在 WinMain 中注册的窗口类?据我所知,重新声明这些变量并创建远离 WinMain 函数的函数可能会导致编译器采用其他一些标准窗口类。那么,我的程序实际上是在使用我在 WinMain 中注册的窗口类吗?

编辑:提供更多代码

//+++++++++++++++++++++++++++++++++++++++cpp文件与win main:

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

...//previous code made the main window of the program and so forth

const char g_szClassName2[] = "windowClass2";//name of the window class
WNDCLASSEX winClass2;
HWND invisHWnd;

winClass2.cbSize         = sizeof(WNDCLASSEX);
winClass2.style          = 0;
winClass2.lpfnWndProc    = WndProcedure2;
winClass2.cbClsExtra     = 0;
winClass2.cbWndExtra     = 0;
winClass2.hInstance     = hInstance;
winClass2.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
winClass2.hCursor       = LoadCursor(NULL, IDC_ARROW);
winClass2.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
winClass2.lpszMenuName  = NULL;
winClass2.lpszClassName = g_szClassName2;
winClass2.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

RegisterClassEx(&winClass2);

... //other code irrelevant to issue

}

//+++++++++++++++++++++++++++++++++++++++其他cpp文件:

void otherCppFile::creatingWindow()
{

    const char g_szClassName2[] = "windowClass2";//name of the window class
    const char WndName2[] = "winClass2";//name of the window class

    HWND windowHandle = CreateWindowEx(0,
                      g_szClassName2,
                      WndName2,
                      WS_OVERLAPPEDWINDOW,
                      0,
                      0,
                      800,
                      500,
                      NULL,
                      NULL,
                      NULL,
                      NULL);
}

这最后一个函数是否使用在 WinMain 中注册的窗口类,即使它不在 WinMain 中并且在函数中重新声明了一些变量?

4

1 回答 1

2

注册窗口类的全部意义在于它是唯一的,您可以在需要时使用它。当您使用该RegisterClass[Ex]函数注册一个窗口类时,您有两个选项来识别它:

  • 您传递给函数的窗口类名称(字符串)。
  • ATOM由函数返回的(整数值)。

在 99.9% 的情况下,您会忘记ATOM并只使用字符串。您需要该字符串来创建窗口类,因此您不妨跟上该字符串并使用它来创建该类的窗口。

那么,从技术上讲,你正在做的事情是可以的。您有多个变量,但它们都包含完全相同的字符串值,因此一切正常。但这是维护的噩梦,也违反了 DRY(不要重复自己)规则。如果您想更改窗口类的名称怎么办?您必须找到声明它的每个文件并确保更新它。然后你必须永远等待你的整个项目重新编译,因为你已经接触了大量的文件。不好。

相反,您希望在全局范围内声明此变量,使其在创建窗口的项目的每个文件中都可用。把它放在一个通用的头文件中,你将把它包含在你的所有代码文件中,或者制作一个单独的Window.h头文件或类似的东西,并在适当的地方包含它。

一定要确保这个窗口类名被声明为一个常量。没有理由在您的应用程序执行期间对其进行修改。

如果您在 C++ 中声明和/或使用全局常量时遇到困难,您可以查看此问题的答案或在 Stack Overflow 上自行搜索。这部分不是 Windows 编程独有的;它只是基本的 C++。

当然,你会经常听到全局变量不好。这是真的。您正在编写的代码并不是真正的 C++。它是 C。Windows API 是 C API,因此它自然会引导您使用 C++ 编写 C 代码。如果您想真正编写 C++ 代码,则需要找到(或编写自己的)C++ 包装器,围绕基于 C 的 Windows API。例如,您将编写一个表示窗口的类,该类将包含一个静态类级常量,该常量保存您的窗口类的名称。该类将负责创建所有新窗口,因此您无需将该信息或那些实现细节分散到多个代码文件中。

至于窗口名称,这是完全不同的。Windows 不使用它来识别您的窗口。实际上,它是CreateWindow[Ex]函数的完全可选参数。您甚至不必为窗口命名。这实际上是出现在窗口标题栏中的名称。用户使用它来识别窗口。因此,它通常需要本地化,并且应该存储在项目的资源文件中,而不是源代码中。使用该LoadString函数从项目的资源文件中加载字符串。您可以在创建窗口时动态执行此操作:只需加载要用作该特定窗口标题的字符串。

于 2014-08-22T13:28:20.470 回答