7

我想要有关winapi中使用的成员cbClsExtracbWndExtra WNDCLASSEX成员的更多详细信息。RegisterClassEx

MSDN表示此成员可用于设置将分配给类和每个窗口实例的额外字节的大小。

MSDN

系统将字节初始化为零。

1)这是否意味着字节被初始化为零值或系统默认分配零(无)字节?

2)最重要的问题是如何使用这些额外的字节(请提供使用winapi的示例)以及它们最常见的使用方式?

提前致谢。

4

2 回答 2

7

这是否意味着字节被初始化为零值或系统默认分配零(无)字节?

初始化总是在变量上完成,所以这意味着将分配的额外内存设置为 0。

最重要的问题是如何使用这些额外的字节(请提供使用 winapi 的示例)以及它们是如何最常用的?

做到这一点的唯一方法是通过GetClassLongPtrandGetWindowLongPtr函数,这些函数非常简单,不需要示例(调用Get*以获取值,并Set*设置值,传递类ATOM或窗口HWND)。

于 2012-11-11T11:02:58.807 回答
3

我想这是一个非常古老的问题,这个人已经继续生活,但我认为它应该得到一个正确的答案,因为我正在努力解决这个问题,而答案并没有太大帮助。是的,它说明了如何设置额外的内存和唯一要使用的功能;但更多的细节是必要的。

你看,有经验的人认为事情是显而易见的和常识,但我不敢苟同。Win32 API 不是一个非常直观的 API。一旦你学会了它,你就会理解某些模式,但后来发现 API 的某些部分与某些部分非常不同。例如,为您的窗口设置字体,与在编辑控件中设置字体不同;对于 Rich Edit Control,这令人惊讶地非常不同。

因此,我总是参考 MSDN 文档,当我无法获得那里的信息时;问堆栈溢出。

///______我的解决方案_________

这是您使用 cbWndExtra 的方法,它是您可以分配给该类的每个窗口实例的额外字节。我不知道 cbClassExtra。

注意我使用 cbWndExtra 作为 GWL_USERDATA 的替代品。对于后者,我将创建一个指向我的特殊结构的新指针并将其设置为 GWL_USERDATA。该结构具有管理窗口对象所需的所有状态。

但是我一直在尝试 cbWndExtra 以避免在堆上创建内存。对于简单的原始变量。

步骤 1. 创建 windowProc.def 文件。这包含用于以类型安全的方式访问窗口字节的枚举和函数。

#include <windows.h>

  #define LINE_NUM_VIEW_WIDTH 0
  #define CODE_EDITOR_EDITOR 0
  #define CODE_EDITOR_LINE_VIEW (CODE_EDITOR_EDITOR + sizeof(HWND))
  #define CODE_EDITOR_HEIGHT (CODE_EDITOR_LINE_VIEW + sizeof(HWND))
  #define CODE_EDITOR_RESIZABLE (CODE_EDITOR_HEIGHT + sizeof(LONG))

  #define LINE_NUMBER_VIEW_WND_EXTRA_BYTES sizeof(LONG)
  #define CODE_EDITOR_WND_EXTRA_BYTES (CODE_EDITOR_RESIZABLE + sizeof(LONG))

#define getLineNumberViewWidth( hwnd) GetWindowLong(hwnd,LINE_NUM_VIEW_WIDTH)
#define setLineNumberViewWidth( hwnd, n) SetWindowLong(hwnd,LINE_NUM_VIEW_WIDTH,n)

#define getTextEditor( hwnd) ((HWND)GetWindowLongPtr(hwnd,CODE_EDITOR_EDITOR))
#define getLineNumberView( hwnd) ((HWND)GetWindowLongPtr(hwnd,CODE_EDITOR_LINE_VIEW))

#define setCodeEditorHeight(hwnd,n) SetWindowLong(hwnd,CODE_EDITOR_HEIGHT,n)
#define getCodeEditorHeight(hwnd) GetWindowLong(hwnd,CODE_EDITOR_HEIGHT)
#define isCodeEditorResizable(hwnd) GetWindowLong(hwnd,CODE_EDITOR_RESIZABLE)
#define setCodeEditorResizable(hwnd, yes) SetWindowLong(hwnd,CODE_EDITOR_RESIZABLE,yes)

请注意 GetWindowLong、GetWindowLongPtr 的技巧。将 GetWindowLong 用于 Long、int、bool 等。使用 GetWindowLongPtr 作为指针。还要注意名称中的 Long。该函数返回 sizeof(LONG) 并存储 sizeof(Long)。并且 msdn 声明有效范围是 0 到 cbWndExtra - sizeof(Long)。因此,即使您可以分配 1 个字节的 cbWndExtra,不要!分配 LONG 的倍数。还要记住 GetWindowLongPtr 存储和检索 sizeof(LONG_PTR)。有效范围 0 - cbWndExtra - sizeof(LONG_PTR)。LONG_PTR 和 LONG 在 64 位窗口上的大小不同。

这真的很简单。GetWindowLong 将始终尝试检索 Long。因此,如果您分配 12 个字节并尝试检索索引 10;这是一个错误,因为只能检索 2 个字节。也许 Windows 会给你带来麻烦,但就我而言,这是未定义的行为。我远离未定义的行为。

请注意,还有 GetWindowWord。从来没有用过。没有 GetWindowByte、Short、Bool 或任何获取和设置 1 字节或 2 字节的机制。因此为所有布尔值分配一个 Long 块。

步骤 2. 创建 windowProc.cpp

#include <stdio.h>
#include "windowProc.def"

LRESULT CALLBACK windowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
    switch(msg)
    {
     case WM_CREATE:
           setCodeEditorHeight(hwnd,100); // from windowProc.def
           printf("%i",getCodeEditorHeight(hwnd)); // from windowProc.def
        return 0;

     default: return DefWindowProc(hwnd, msg, wparam, lparam);
    }
}

ATOM registerMainWindow()
{
 WNDCLASSEX wincl = {0};

 wincl.cbSize = sizeof(WNDCLASSEX);
 wincl.hInstance = (HINSTANCE)0x400000;
 wincl.lpszClassName = "JavWindowProc";
 wincl.lpfnWndProc = windowProc;
 wincl.hCursor = LoadCursor(NULL,IDC_IBEAM);
 wincl.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+1);
 wincl.cbWndExtra = CODE_EDITOR_WND_EXTRA_BYTES; // Safely set the size with our enumeration from windowProc.def

 return (LPCSTR)RegisterClassEx(&wincl);
}

HWND createMainWindow(const char *title,int width,int height)
{
 static auto className = registerMainWindow();

 return CreateWindowExA(
           0,                   // Extended possibilites for variation
           className,
           title,
           WS_CHILD,
           0,0,width,height,
           HWND_DESKTOP,
           0,
           (HINSTANCE)0x400000,
           NULL                 // No Window Creation data// The alternative to cbWndExtra
         );
}

步骤 3 显然,使用您的消息循环创建您的主要功能。

希望这对某人有帮助。

于 2020-12-04T19:33:44.560 回答