Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cbClsExtra and cbWndExtra

Tags:

window

winapi

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.

like image 845
Demion Avatar asked Nov 11 '12 10:11

Demion


2 Answers

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).

like image 183
Necrolis Avatar answered Nov 06 '22 02:11

Necrolis


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.

like image 35
user13947194 Avatar answered Nov 06 '22 02:11

user13947194