Hi guys, i want ask help because i have problem ALWAYS i want a subclassing : ( and i do not know the reason
i have this code, I created all with CreateWindowEx function, first, I created a dialog ( second main ) ,next,
I created two child dialogs within of second main, next, i want create control within child dialogs, well, i created...
next i want use ShowWindow function for hidde or show a child dialog, it I use a subclassing but the program i does not work and the CPU is accelerates to 50%,
always i have problems with subclassing, I readed a tutorial about subclassing made by Iczelion but a cannot do it, please you could help me guys
my full code, without res, only a main file *.asm
include \MASM32\INCLUDE\MASM32rt.inc
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
.data
ClassName db "MainWinClass",0
AppName db "Main Window",0
classdialog db "#32770",0
classbutton db "Button",0
classname1 db "one",0
classname2 db "two",0
classname3 db "three",0
classname4 db "four",0
handleMAIN dd 0
handledialog1 dd 0
handledialog2 dd 0
handlebutton1 dd 0
handlebutton2 dd 0
subclass dd 0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
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 hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,600,300,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
Myproc proc shWnd:HWND, suMsg:UINT, swParam:WPARAM, slParam:LPARAM
.IF suMsg==WM_COMMAND
mov edx,shWnd
.if edx==handlebutton1
invoke ShowWindow,handlebutton2,SW_HIDE
invoke ShowWindow,handlebutton1,SW_SHOW
.elseif edx==handlebutton2
invoke ShowWindow,handlebutton1,SW_HIDE
invoke ShowWindow,handlebutton2,SW_SHOW
.endif
.elseIF suMsg==WM_DESTROY
invoke SetWindowLong,subclass,GWL_WNDPROC,Myproc
.else
invoke CallWindowProc,subclass,shWnd,suMsg,swParam,slParam
ret
.endif
xor eax,eax
ret
Myproc endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE
;===========================================================================
; create main windows
;===========================================================================
invoke CreateWindowEx,NULL,addr classdialog,addr classname1,10CA2000h, \
CW_USEDEFAULT,CW_USEDEFAULT,500,400,hWnd,NULL,hInstance,NULL
mov handleMAIN,eax
invoke ShowWindow,handleMAIN,SW_SHOW
; create second windows
invoke CreateWindowEx,NULL,addr classdialog,addr classname1,WS_BORDER or WS_VISIBLE or WS_CHILD, \
10,10,300,200,handleMAIN,NULL,hInstance,NULL
mov handledialog1,eax
; create sub controls dialog 1
invoke CreateWindowEx,NULL,addr classbutton,addr classname1,WS_CHILD or WS_VISIBLE,20,30,35,20,handledialog1,NULL,hInstance,NULL
invoke ShowWindow,handledialog1,SW_SHOW
; create second window
invoke CreateWindowEx,NULL,addr classdialog,addr classname2,WS_BORDER or WS_VISIBLE or WS_CHILD, \
310,10,300,200,handleMAIN,NULL,hInstance,NULL
mov handledialog2,eax
; create sub controls dialog 2
invoke CreateWindowEx,NULL,addr classbutton,addr classname2,WS_CHILD or WS_VISIBLE,30,40,35,20,handledialog2,NULL,hInstance,NULL
invoke ShowWindow,handledialog2,SW_HIDE
; create buttons for main windows
invoke CreateWindowEx,NULL,addr classbutton,addr classname3,50010000h, 10,220,35,20,handleMAIN,NULL,hInstance,NULL
mov handlebutton1,eax
invoke CreateWindowEx,NULL,addr classbutton,addr classname4,50010000h, 45,220,35,20,handleMAIN,NULL,hInstance,NULL
mov handlebutton2,eax
invoke SetWindowLong,handleMAIN,GWL_WNDPROC,Myproc
invoke SetWindowLong,handlebutton1,GWL_WNDPROC,Myproc
invoke SetWindowLong,handlebutton2,GWL_WNDPROC,Myproc
mov subclass,eax
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
SetWindowLong is really the old way to subclass controls, you should consider SetWindowSubclass/DefSubclassProc for subclassing, it doesn't require that you save the old procedure address and allows chaining of subclassing procedures. This line in your code is definitely wrong:
invoke SetWindowLong,subclass,GWL_WNDPROC,Myproc
The subclass variable is a pointer to the original procedure not a window handle which is what the API requires. But the big problem is that you're trying to subclass a dialog and two buttons using the same procedure. That in itself is not completely wrong but you are using the same old procedure address for all of them, in this case you use the old procedure from a button. That's OK for the two buttons but will cause all sorts of problems when you try to call it as the default procedure for the dialog (handleMAIN). Next I'm not too familiar with newer versions of MASM but when you set the subclass you should be using OFFSET Myproc, for example:
invoke SetWindowLong,handlebutton2,GWL_WNDPROC,offset Myproc
Edgar
i think the biggest problem, here, is that you are using the same subclass
WndProc for different windows that were created from different classes
the handleMAIN window is created using the class string "#32770"
handlebutton1 and handlebutton2 are created using the class string "Button"
the "#32770" and "Button" classes have different original WndProc's
when you exit "Myproc", you send "#32770" messages to a "Button" WndProc
the best thing to do is probably create BtnProc and DlgProc seperately, to replace MyProc
you could use the same subclass proc, but when you exit,
you would have to point to the correct original WndProc in the CallWindowProc function
it is simpler to use different proc's for different classes
invoke SetWindowLong,handleMAIN,GWL_WNDPROC,DlgProc
mov subclassMAIN,eax
invoke SetWindowLong,handlebutton1,GWL_WNDPROC,BtnProc
invoke SetWindowLong,handlebutton2,GWL_WNDPROC,BtnProc
mov subclass,eax
a similar issue arises when you destroy the window
you point the subclassMAIN class to a button WndProc
--------------------
i see this a lot, and it seems to work ok - i guess - lol
i am surprised it doesn't crash more often - maybe it does, and we just don't realize it
invoke SetWindowLong,handleMAIN,GWL_WNDPROC,DlgProc
mov subclassMAIN,eax
there is a brief moment when the handleMAIN WndProc is pointing to DlgProc, and the return proc is 0 :P
the documentation does not say "we wait for you to store the returned value in a variable before sending messages"
i always prefer to call GetWindowLong to get the original WndProc address and store it before subclassing
invoke GetWindowLong,handleMAIN,GWL_WNDPROC
mov subclassMAIN,eax
invoke SetWindowLong,handleMAIN,GWL_WNDPROC,DlgProc
that way, the CallWindowProc parameter has a proper WndProc before you subclass
i will probably take some flack for this from other forum members
--------------------
another problem is the WM_DESTROY code
.elseIF suMsg==WM_DESTROY
invoke SetWindowLong,subclass,GWL_WNDPROC,Myproc
ok - you un-subclassed the window, but you forgot to destroy it afterward
Quote from: donkey on April 25, 2012, 10:32:33 AMNext I'm not too familiar with newer versions of MASM but when you set the subclass you should be using OFFSET Myproc, for example:
invoke SetWindowLong,handlebutton2,GWL_WNDPROC,offset Myproc
Edgar
nah - masm knows it is a code label and passes the address, rather than the first four bytes of code :P
mov wc.lpfnWndProc,Myproc
is also a valid form
@donkey: those APIs are new for me, thanks donkey, I will check the MSDN for it
@Dave: yeah man, also , i checked the Background.zip project, it helped me ,I saw you used the RegisterClassEx function,
for register of each window, and put all controls on it, i thought do it so, but i want check with subclassing, but always i have problems :/
now, I did the you say, use the SetWindowLong function and it works, it does not accelerates, but does not capture the WM_COMMAND message for the buttons,
those hides or show the child windows, that hard, I will check more subclassing examples :/
is this what you're trying to do ??
when you create a WS_CHILD window or control, the CreateWindowEx hMenu parameter can (and probably should) be a control ID #
agreed.... Just scoring some points while you carry me on your backs. JK
by the way - there was no need to subclass the buttons
but, i did anyways, to demonstrate that the button proc is seperate from the subclassed dialog :P
thanks a lot dave, Is nice ur code, thanks mate
:U