I want more detailed information about cbClsExtra
and cbWndExtra
WNDCLASSEX
members that are used in RegisterClassEx
winapi.
MSDN
says that this members can be used to set size of extra bytes that will be allocated for class and for each window instance accordingly.
MSDN
says
The system initializes the bytes to zero.
1) Does this mean that bytes are initialized with zero value or system allocates zero (none) bytes by default?
2) The most important question is how to use this extra bytes (provide examples please with winapi used) and how they are used most common?
Thanks in advance.
Does this mean that bytes are initialized with zero value or system allocates zero (none) bytes by default?
initialization is always done on variables, so it means to sets the allocated extra memory to 0.
The most important question is how to use this extra bytes (provide examples please with winapi used) and how they are used most common?
The only way to do this is via the GetClassLongPtr
and GetWindowLongPtr
functions, these functions are simple enough to not need examples (call Get*
to get the value, and Set*
set set the value, passing either the class ATOM
or window HWND
).
I guess this is a really old question and the person already went on with life, but I think it deserves a proper answer as I was struggling with it and the answer wasn't much help. Yes it stated how to set the extra memory and the ONLY functions to use; but much much more detail was NECESSARY.
You see, experience persons thinks things are obvious and common sense, but I beg to differ. Win32 API is not a very intuitive API. Once you learn it you get to understand certain patterns, but later discover that some parts of the API is very different from some. Example, Setting font for your window, is different from setting font in an Edit control; which is surprisingly very very different for Rich Edit Control.
Thus I always refer to MSDN documentation and when I cant get the information there; ask Stack Overflow.
///______MY SOLUTION _________
Here is how you use cbWndExtra, which is extra bytes you can allocate to each Window Instance of that class. I know not about cbClassExtra.
Note I use cbWndExtra as an alternative to GWL_USERDATA. With the latter I would create and new pointer to my special structure and set it to GWL_USERDATA. This struct has all state I need to manage the window object.
However I have been trying out cbWndExtra to avoid creating memory on the heap. For simple primitive variables.
Step 1. Create windowProc.def file. This contains enumerations and functions for accessing the window bytes in a type safe way.
#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)
Note the trick with GetWindowLong, GetWindowLongPtr. Use GetWindowLong for Long, int, bool, and the likes. Use GetWindowLongPtr for pointers. Also notice the Long in the name. the function returns sizeof(LONG) and stores sizeof(Long). And msdn states valid range is 0 to cbWndExtra - sizeof(Long). Thus even though you can allocate 1 byte of cbWndExtra, DONT! Allocate multiples of LONG. And also remember that GetWindowLongPtr stores and retrieves sizeof(LONG_PTR). valid range 0 - cbWndExtra - sizeof(LONG_PTR). LONG_PTR and LONG are different size on 64 bit windows.
It is really simple. GetWindowLong will always try retrieve Long. Thus if you allocate 12 bytes and try to retrieve index 10; that is a mistake as only 2 bytes can be retrieved. Maybe windows gives you a bly, but as far as I am concernes that is undefined behaviour. And I stay clear of undefined behaviour.
Note there is GetWindowWord as well. Never used it. There is no GetWindowByte, Short, Bool or any mechanism getting and setting 1 byte or 2 byte. Thus allocate one Long block for all your bools.
Step 2. create 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
);
}
Steps 3 Obviously create your main function with your message loop.
Hope this was a help to somebody.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With