0

在 Visual Studio 创建 Win32 项目时生成的默认代码中,有一个名为MyRegisterClass的函数,其注释为:

//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    ...
    return RegisterClassEx(&wcex);
}

但是这个函数使用了Windows 95之前不存在的RegisterClassEx。我真的不明白评论。它们是什么意思?

拥有MyRegisterClass功能的主要目的是什么,为什么它对于与早期版本的 Windows 兼容如此必要?

4

1 回答 1

3

MyRegisterClass函数是一个辅助函数。它封装了对 API 函数的调用RegisterClass[Ex],因为为了进行调用,需要完成很多杂乱的参数设置。完整的函数定义如下所示:

ATOM MyRegisterClass(HINSTANCE hInstance)
{
  WNDCLASSEX wcex;

  wcex.cbSize         = sizeof(WNDCLASSEX);
  wcex.style          = CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc    = WndProc;
  wcex.cbClsExtra     = 0;
  wcex.cbWndExtra     = 0;
  wcex.hInstance      = hInstance;
  wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYAPP));
  wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
  wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_MYAPP);
  wcex.lpszClassName  = szWindowClass;
  wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

  return RegisterClassEx(&wcex);
}

将其提取到一个辅助函数中——而不是内联它——可以使你的代码保持干净和更具可读性。就性能而言,如果合适的话,编译器会自动内联它。

将其作为辅助函数有意义的另一个原因是历史原因,这就是评论中所描述的:

//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.

你看,ExAPI 上的后缀表示“扩展”。该RegisterClassEx功能是在 32 位 Windows(API v4.0,Windows 95)中引入的。回到 16 位 Windows,只有RegisterClass. 32 位 Windows 支持这两种变体,以实现向后兼容,但RegisterClassEx添加的“扩展”是设置小图标的能力。如果你想要漂亮的小图标(而不是丑陋的,由大图标的低质量拉伸算法生成),你需要调用RegisterClassEx. 但是如果你想针对 16 位 Windows,你不能调用RegisterClassEx; 你需要坚持RegisterClass。因此,如果您将调用封装RegisterClass[Ex]在帮助函数中,您可以轻松修改代码,更改它调用的 API 函数,从而更改您的应用程序可以定位的 Windows 版本。

该评论试图传达此信息,但在表达自己方面做得相对较差。

你今天可以完全忽略这一点。没有人再针对 16 位 Windows。总是打电话RegisterClassExRegisterClass甚至忘记它的存在。这并没有消除将此代码封装在函数中以提高可读性的优势。

此外请注意,与 Visual Studio 捆绑的默认 Win32 项目模板将小图标和大图标分隔在单独的 ICO 文件中,从而为它们分配单独的资源 ID。这可能是出于同样的历史原因,因此您可以针对 16 位 Windows 进行编译而不会出现小图标,但今天再次完全没有必要。您可以将两个图标组合成一个 ICO 文件,并有选择地加载它们:

ATOM MyRegisterClass(HINSTANCE hInstance)
{
  WNDCLASSEX wcex;

  wcex.cbSize         = sizeof(wcex);
  wcex.style          = CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc    = WndProc;
  wcex.cbClsExtra     = 0;
  wcex.cbWndExtra     = 0;
  wcex.hInstance      = hInstance;
  wcex.hIcon          = (HICON)LoadImage(hInstance,
                                         MAKEINTRESOURCE(IDI_MYAPP),
                                         IMAGE_ICON,
                                         GetSystemMetrics(SM_CXICON),
                                         GetSystemMetrics(SM_CYICON),
                                         LR_DEFAULTCOLOR | LR_SHARED);
  wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_MYAPP);
  wcex.lpszClassName  = szWindowClass;
  wcex.hIconSm        = (HICON)LoadImage(hInstance,
                                         MAKEINTRESOURCE(IDI_MYAPP),
                                         IMAGE_ICON,
                                         GetSystemMetrics(SM_CXSMICON),
                                         GetSystemMetrics(SM_CYSMICON),
                                         LR_DEFAULTCOLOR);

  return RegisterClassEx(&wcex);
}
于 2019-03-05T01:49:35.637 回答