News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

how to access WNDCLASSEX.cbClsExtra and cbWndExtra?

Started by xandaz, November 04, 2020, 07:45:31 PM

Previous topic - Next topic

xandaz

   I'm having ouble with this. Where do i get the pointers for cbWndExtra and cbClsExtra? Can someone help me out?

Vortex

Hello,

Classical window template :

WinMain PROC hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD

LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND

    mov     wc.cbSize,SIZEOF WNDCLASSEX
    mov     wc.style, CS_HREDRAW or CS_VREDRAW
    mov     wc.lpfnWndProc, OFFSET WndProc
    mov     wc.cbClsExtra,NULL
    mov     wc.cbWndExtra,NULL
    push    hInst
    pop     wc.hInstance


https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexa

    lea eax,wc.cbClsExtra

xandaz


xandaz

   Sorry. Isnt cbClsExtra and cbWndExtra a byte count?

Vortex

Hello,

Each of those items have a size of 4 bytes :

main PROC

LOCAL wc:WNDCLASSEX

    invoke  crt_printf,ADDR str1,\
            sizeof wc.cbClsExtra,\
            sizeof wc.cbWndExtra


4 4

xandaz


jj2007

The question is here "what for?". Both cbClsExtra and cbWndExtra just say "there is a buffer after my WNDCLASSEX structure". You can fill it, of course, but why so complicated? Any global buffer db 100 dup(?) is easier to handle. IMHO cbClsExtra and cbWndExtra are among the most useless "features" of Windows :cool:

TouEnMasm

 wc.cbClsExtra and  wc.cbWndExtra are useful in MDI with a particular instruction (Multiple Windows).
If you don't need MDI you don't need also those data,there used had been replaced by
The use of the fuctions setprop getprop.
Fa is a musical note to play with CL

hutch--

They serve a very useful purpose as memory that is specifically associated with a Window. If the Window is used multiple times as with a custom control, you have data that is unique to each window without having any scope problems where using a GLOBAL imposes severe restrictions with multiple copies of a Window. Its there if you need it but a vast amount of software never uses it.

xandaz

   So after all cbClsExtra and cbWndEstra are buffers. How to get the pointers to them?

jj2007

Quote from: hutch-- on November 05, 2020, 01:05:29 AMyou have data

Excuse my ignorance: how do you access these data? Attached a demo how to access user data, that works fine (and instead of the string, that could be a pointer to megabytes of data uniquely associated with the control), but I still haven't found examples on the web showing how to access the extra members.

include \masm32\MasmBasic\Res\MbGui.asm
  GuiControl BigEdit, "richedit", Cat$(Left$(MbExeFolder$)+":\Masm32\examples\exampl01\bmbutton\bmbutton.asm"), w700
  GuiControl SmallEdit, "edit", "A small edit control", x700, w300
  GuiControl Status, "statusbar"
  invoke SetWindowLong, hBigEdit, GWL_USERDATA, wRec$("Введите текст здесь")
  invoke SetWindowLong, hSmallEdit, GWL_USERDATA, wRec$("Click into the richedit control")

Event Command
  .if nCode==EN_SETFOCUS
invoke GetWindowLong, lParam_, GWL_USERDATA
wSetWin$ hStatus=eax
  .endif
GuiEnd

fearless

I use the cbWndExtra to declare extra space for the associated control (window) like for example in the ModernUI controls: https://github.com/mrfearless/ModernUI/blob/master/Controls/ModernUI_Button/ModernUI_Button.asm#L372
To access the data you can use GetWindowLong and SetWindowLong. (GetWindowLongPtr and SetWindowLongPtr for x64 asm)

For example if i alloc 8 as the cbWndExtra i can read the first dword with:
Invoke GetWindowLong, hWin, 0
and the 2nd dword with:

Invoke GetWindowLong, hWin, 4
And similar to set the appropriate value using SetWindowLong using the correct offset 0/4 for the dword to set (based on allocating only 8 bytes in cbWndExtra).
Of interest is the potential issue of allocating over 40 bytes for cbWndExtra:
https://app.gitbook.com/@fearless/s/creating-controls-in-assembler/control-properties



Vortex

Quote from: xandaz on November 05, 2020, 02:47:22 AM
   So after all cbClsExtra and cbWndEstra are buffers. How to get the pointers to them?

Hi xandaz,

They are not buffers. The two expressions are the members of the structure WNDCLASSEXA  :

WNDCLASSEXA STRUCT
  cbSize            DWORD      ?
  style             DWORD      ?
  lpfnWndProc       DWORD      ?
  cbClsExtra        DWORD      ?
  cbWndExtra        DWORD      ?
  hInstance         DWORD      ?
  hIcon             DWORD      ?
  hCursor           DWORD      ?
  hbrBackground     DWORD      ?
  lpszMenuName      DWORD      ?
  lpszClassName     DWORD      ?
  hIconSm           DWORD      ?
WNDCLASSEXA ENDS
.
.

IFDEF __UNICODE__
    WNDCLASSEX  equ  <WNDCLASSEXW>
ELSE
    WNDCLASSEX  equ  <WNDCLASSEXA>
ENDIF

jj2007

Thanks, fearless - you enlightened me!!!

GWL_WNDPROC                          equ -4
GWL_HINSTANCE                        equ -6
GWL_HWNDPARENT                       equ -8
GWL_STYLE                            equ -16
GWL_EXSTYLE                          equ -20
GWL_USERDATA                         equ -21
GWL_ID                               equ -12


So GetWindowLong with a positive value simply returns the address of the data... wow! That's so lousily documented by Micros**t that I understand why almost nobody uses it. Still, GWL_USERDATA is easier to handle IMO.

fearless

:D
Yeh the GWL_USERDATA can be handy to use.

I usually allocate enough memory (twice) for the control and then save the pointer to one of the cbWndExtra 'spaces' - I internally use the 0 offset to represent a pointer to memory used for 'internal' properties for the control and 4 offset for the 'external' properties that the end user can change. In the past i just used a large buffer for cbWndExtra - like 196 bytes or so and occasionaly noticed some weird crashes or things not working - it didnt happen often but enough that when i read the info in the RegisterClassEx about the memory potentially not being allocated if over 40 bytes, i then changed my methodology to just use 8 bytes for the cbWndExtra and alloc the mem myself during wm_create/wm_ncreate