cbClsExtra和cbWndExtra

Dem*_*ion 7 winapi window

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

MSDN 说这个成员可以用来设置将为类和每个窗口实例分配的额外字节的大小.

MSDN

系统将字节初始化为零.

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

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

提前致谢.

Nec*_*lis 7

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

初始化总是在变量上完成,因此它意味着将分配的额外内存设置为0.

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

唯一的方法是通过GetClassLongPtrGetWindowLongPtr函数,这些函数很简单,不需要示例(调用Get*获取值,并Set*设置值,传递类ATOM或窗口HWND).


use*_*194 6

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

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

因此,当我无法获取其中的信息时,我总是参考 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)
Run Code Online (Sandbox Code Playgroud)

请注意 GetWindowLong、GetWindowLongPtr 的技巧。对于 Long、int、bool 等,请使用 GetWindowLong。使用 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 给了你一个 bly,但就我而言,这是未定义的行为。我远离未定义的行为。

请注意,还有 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
         );
}
Run Code Online (Sandbox Code Playgroud)

步骤 3 显然,使用消息循环创建主函数。

希望这对某人有帮助。