参考文档: https://blog.csdn.net/u010003835/article/details/47002383
HWND CreateMyWinEx(HINSTANCE hInstance)
{
WNDCLASSEX wndClassex;
wndClassex.cbSize = sizeof(WNDCLASSEX);
wndClassex.style = CS_HREDRAW | CS_VREDRAW;
wndClassex.lpfnWndProc = ::DefWindowProc;
wndClassex.cbClsExtra = 16;
wndClassex.cbWndExtra = 44; //取值范围为0-40 必须是4的倍数 但是=> win10 vs2019 32位应用程序测试这个值超过40也没问题
wndClassex.hInstance = hInstance;
wndClassex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClassex.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClassex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClassex.lpszMenuName = NULL;
wndClassex.lpszClassName = TEXT("mywinex");
wndClassex.hIconSm = NULL;
if (!RegisterClassEx(static_cast<const WNDCLASSEX*>(&wndClassex))) {
MessageBox(NULL, TEXT("Register Class Error"), TEXT("mywinex"), 0);
return 0;
}
HWND hwnd = CreateWindow(
TEXT("mywinex"),
TEXT("Demoex"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
HWND hwnd2 = CreateWindow(
TEXT("mywinex"),
TEXT("jiangkaiex"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
//获取额外内存大小信息
DWORD cl = GetClassLong(hwnd, GCL_CBCLSEXTRA);
DWORD wd = GetClassLong(hwnd, GCL_CBWNDEXTRA);
//设置窗口类额外内存数据
SetClassLongPtr(hwnd, 0, 11);
SetClassLongPtr(hwnd, 4, 22);
SetClassLongPtr(hwnd, 8, 33);
DWORD rescl = GetClassLongPtr(hwnd, 0);
rescl = GetClassLongPtr(hwnd, 4);
rescl = GetClassLongPtr(hwnd, 8);
//与窗口类关联的额外内存 针对所有以该注册窗口类创建的实例窗口的额外内存的值都有效
rescl = GetClassLongPtr(hwnd2, 0);
rescl = GetClassLongPtr(hwnd2, 4);
rescl = GetClassLongPtr(hwnd2, 8);
//更改额外窗口类对应内存,与额外窗口实例对应内存 测试【这个测试暂时没做,这个测试验证的是窗口类额外内存与窗口实例额外内存的分配时机以及是否可以重分配】
{
//原来大小分别是 16 44
SetClassLongPtr(hwnd, GCL_CBCLSEXTRA, 20);
SetClassLongPtr(hwnd, GCL_CBWNDEXTRA, 48);
DWORD cl2 = GetClassLong(hwnd2, GCL_CBCLSEXTRA);//显示没改
DWORD wd2 = GetClassLong(hwnd2, GCL_CBWNDEXTRA);//显示被修改了
wd = GetClassLong(hwnd, GCL_CBCLSEXTRA);//显示没改
wd = GetClassLong(hwnd, GCL_CBWNDEXTRA);//显示被修改了
//修改后重新设置一下
SetClassLongPtr(hwnd, 12, 111);
rescl = GetClassLongPtr(hwnd, 12);//实际修改了 【窗口类关联的额外内存可以被SetClassLongPtr马上动态修改】
rescl = GetClassLongPtr(hwnd2, 12);//实际修改了
//msdn 原文:某些窗口数据会被缓存,所以使用SetWindowLongPtr所做的更改直到调用SetWindowPos函数才会生效。
SetWindowLongPtr(hwnd, 44, 3333333);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);// 但是这里实参无论是否调用 SetWindowPos下面依然无法获取正确数据;此处问题原因应该是前面用SetClassLongPtr去修改窗口实例关联的额外内存时对已经实例化的窗口是无效的;【 msdn上并没有查到此处细节的详细说明】
auto res = GetWindowLongPtr(hwnd, 44);//实际没改
res = GetWindowLongPtr(hwnd2, 44);//实际没改
getchar();
}
//第二参数 index代表的是一个地址偏移量以字节为单位;但是必须是4的倍数;因为存储每次都是以四个字节存储的
SetWindowLongPtr(hwnd, 0, 1);//每次从偏移地址函数写入占用4个字节
SetWindowLongPtr(hwnd, 4, 2);
SetWindowLongPtr(hwnd, 8, 3123);
SetWindowLongPtr(hwnd, 12, 45546);
SetWindowLongPtr(hwnd, 36, 1111111);//cbWndExtra=32 时error
SetWindowLongPtr(hwnd, 40, 2222222);//cbWndExtra=44 时 超过40个字节偏移依然正确获取了
SetWindowLongPtr(hwnd, GWLP_USERDATA, 464);
LONG_PTR res = GetWindowLongPtr(hwnd, 0);//每次从偏移地址函数读取4个字节的值
res = GetWindowLongPtr(hwnd, 4);
res = GetWindowLongPtr(hwnd, 8);
res = GetWindowLongPtr(hwnd, 12);
res = GetWindowLongPtr(hwnd, 36);//cbWndExtra=32 时error 无法获取数据返回0
res = GetWindowLongPtr(hwnd, 40);//cbWndExtra=44 时 超过40个字节偏移依然正确获取了
res = GetWindowLongPtr(hwnd, GWLP_USERDATA);//GWLP_USERDATA是另一个位置为窗口实例预留了4字节空间与cbWndExtra无关
//与窗口实例关联的额外内存 另一个窗口值无任何有效值
res = GetWindowLongPtr(hwnd2, 4);
res = GetWindowLongPtr(hwnd2, 8);
res = GetWindowLongPtr(hwnd2, 12);
res = GetWindowLongPtr(hwnd2, 36);
res = GetWindowLongPtr(hwnd2, 40);
res = GetWindowLongPtr(hwnd2, GWLP_USERDATA);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
ShowWindow(hwnd2, SW_SHOW);
UpdateWindow(hwnd2);
return hwnd;
}