The code below gives the error "Cannot find window class."
Would someone be so kind as to look at it and see if anything stands out as a possible cause.
I apologize for the idiosyncratic programming style. I think I've included everything relevant.
Thank you, ral
;; NEWWIN NEW child WINdow
newwin:
invoke RegisterClassEx, OFFSET LFwcc
or eax, eax
jz germs
mov edx, CW_USEDEFAULT
mov ecx, [hwnd]
xor eax,eax
mov esi, OFFSET ChldClass
mov edi, OFFSET ChildW
invoke CreateWindowEx,eax,esi,edi,chstyle,edx,edx,edx,edx,\
ecx,0,hinst,eax
mov [hcwnd], eax
or eax, eax
jz germs
retn
LFwcc LABEL DWORD ;LFile Window Child Class structure
DD SIZEOF WNDCLASSEX ; 0 wc.cbSize
DD chstyle ; 4 CHild style
DD OF CWProc ; 8 Child WPROC
DD 0,0 ;0C wc.cbClsExtra, wc.cbWndExtra
DD ? ;14 wc.hinst
cicon DD hicon ;18 LoadIcon,0,IDI_APPLICATION
DD hcurs ;1C LoadCursor,NULL,IDC_ARROW
DD hbkbr ;20 CreateSolidBrush,0FF0000h
wccmen DD 0 ;24 wc.lpszMenuName
DD OF ChldClass ;28 wc.lpszClassName
DD hiconsm ;2C wc.hIconS
ChldClass DB "LFChildclass",0
ChildW DB "lfwChild",0
hcwnd DD ?
chstyle EQU CS_HREDRAW or CS_VREDRAW or CS_DBLCLK
germs is a routine that calls GetLastError, and FormatMessage and shows the result.
hwnd is the handle to the main window.
hicon, hcurs, hbkgr, and hiconsm are all pointers to values obtained for the main window.
hi! I had a question about your code;
mov ecx, [hwnd]
is that similar to mov ecx, OFFSET hwnd?
the brackets always confuse me on memory :)
thanks
edit: whoops! we dont need the offset of the handle! thats pointer to pointer isnt it?
shouldnt it be mov ecx, hwnd from http://msdn.microsoft.com/en-us/library/ms632680(v=vs.85).aspx
here is an example of how to register a window class...
in the DATA section...
.DATA
ClassString db 'SomeClassName',0
in the DATA? section...
.DATA?
hInstance dd ?
hCursor dd ?
hIcon dd ?
wc WNDCLASSEX <>
that allocates an empty structure and a few handles
the structure is typically filled with code..
INVOKE GetModuleHandle,NULL
mov hInstance,eax
INVOKE LoadCursor,NULL,IDC_ARROW
mov hCuror,eax
INVOKE LoadIcon,NULL,IDI_APPLICATION
mov hIcon,eax ;EAX = hIcon
mov wc.cbSize,sizeof WNDCLASSEX
mov wc.style,CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc,WndProc
mov wc.cbClsExtra,0
mov wc.cbWndExtra,0
push hInstance
pop wc.hInstance
mov wc.hIcon,eax
push hCursor
pop wc.hCursor
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,offset ClassString
mov wc.hIconSm,eax
INVOKE RegisterClassEx,offset wc
you may test the value of EAX after the call to RegisterClassEx to see if it was successful
if so, you may now reference the registered class by the ClassString
the second parameter of CreateWindowEx is...
offset ClassString
there are a number of variations, but that should get you started
the WNDCLASSEX structure is defined in windows.inc
no need to define it with DD's
you can put the structure in the DATA section and initialize most of the members
.DATA
wc WNDCLASSEX <sizeof WNDCLASSEX,CS_HREDRAW or CS_VREDRAW,WndProc,0,0,?,?,?,COLOR_BTNFACE+1,NULL,ClassString,?>
then fill in hInstance, hCursor, hIcon, and hIconSm with code
doing it that way is probably smaller than doing it all with code :bg
that's a good idea, Ral :U
@Zekyr
mov ecx,[hwnd] ;put contents of address pointed to by hwnd into ecx register ;or say put contents of memory named/labled hwnd into ecx register
mov ecx,hwnd ;put address of hwnd into ecx register
hwnd ;address of
[hwnd] ;contents of
// Like in c
x = *myPtr ; that is like mov ecx,[hwnd] ;x gets value pointed to by myPtr
x = myPtr ; that is like mov ecx, hwnd ;x gets value of myPtr
...
as for the code, I see one line that says
""" DD OF CWProc ; 8 Child WPROC """
shouldn't it say
""" DD OFFSET CWProc """"
unless "OF" is shorthand for OFFSET, or ADDRESS OF, is it??? I haven't seen "OF" before
Quote from: ixuta on August 07, 2011, 05:52:18 AM
...
as for the code, I see one line that says
""" DD OF CWProc ; 8 Child WPROC """
shouldn't it say
""" DD OFFSET CWProc """"
unless "OF" is shorthand for OFFSET, or ADDRESS OF, is it??? I haven't seen "OF" before
Yes. Sorry. I forgot to replace 2 occurrences of "OF" in the WNDCLASSEX. I'm a lazy typist so I have an equate.
Quote from: dedndave on August 07, 2011, 05:50:09 AM
here is an example of how to register a window class...
[snip]
Thanks. I'm digesting this.
@dedndave:
Hmm. Here's how I do it for my main window, and it works fine.
So far I don't see a difference with your code that could be causing the problem.
RegisterClassEx doesn't return an error - it returns 7ffd0000. I'll try using that in CreateWindowEx.
Except that I don't understand the SDK help, which says:
QuotelpClassName [in] Pointer to a null-terminated string or a class atom created by a previous call to the RegisterClass or RegisterClassEx function. The atom must be in the low-order word of lpClassName; the high-order word must be zero. If lpClassName is a string, it specifies the window class name.
In .DATA
LFwc LABEL DWORD ;LFile Window Class structure
DD SIZEOF WNDCLASSEX ; 0 wc.cbSize
DD lfstyle ; 4 wc.style
DD OFFSET WProc ; 8 wc.lpfnWndProc
DD 0,0 ;0C wc.cbClsExtra, wc.cbWndExtra
hinst DD ? ;14 wc.hinst
hicon DD ? ;18 LoadIcon,0,IDI_APPLICATION
hcurs DD ? ;1C LoadCursor,NULL,IDC_ARROW
hbkbr DD ? ;20 CreateSolidBrush,0FF0000h
wcmen DD 0 ;24 wc.lpszMenuName
DD OFFSET ClassName ;28 wc.lpszClassName
hiconsm DD ? ;2C wc.hIconSm
;30 end LFwc
In .CODE
start:
invoke CreateSolidBrush,0FF0000h
mov [hbkbr], eax
invoke LoadIcon,0,IDI_APPLICATION
mov [hicon], eax
mov [hiconsm], eax
invoke LoadCursor,0,IDC_ARROW
mov [hcurs], eax
invoke GetModuleHandle, 0
mov [hinst], eax
and in winmain
WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
LOCAL msg:MSG
invoke RegisterClassEx, OFFSET LFwc
mov edx, CW_USEDEFAULT
xor eax,eax
invoke CreateWindowEx,eax,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,edx,edx,edx,edx,eax,eax,hInst,eax
mov [hwnd], eax
thought it was like
mov eax, [hwnd] ;grab memory pointed to by hwnd and stick it into eax
mov eax, hwnd ;stick handle into eax (which i thought we wanted here)
mov eax, offset hwnd ;stick address of hwnd which has a handle in it, which could be dereferenced into eax
or um
c-example would be like
int * ptr = myptr;
printf("%d %d %d",*ptr , ptr, &ptr);
my apologies for bringing up dumb questions all the time :D
Ral,
the code you posted leaves a few things unclear
for example, i do not know what the value of lfstyle is, as you do not show it
as you have shown it being used, it should be an EQUate that represents a set of valid style bits
as for using the global class atom returned in RegisterClassEx as the lpClassName parameter,
that requires that the atom be converted to a 16-bit local atom - more trouble than it's worth
i think the problem may be that you are attempting to register the same class name twice
each time you register a new class, it must have a unique class name string, unless it is one of the system control classes
you can use the same registered class name string to create more than one window, however
if you need further help, please attach complete code so that we can see all the constants and variables :U
zekyr,
he is using GoAsm, i think
it is a syntax thing specific to that assembler :P
if you want to dereference the handle as an address, it requires 2 instructions
mov eax,SomeLabel
mov eax,[eax]
Quote from: dedndave on August 07, 2011, 01:06:33 PM
Ral,
the code you posted leaves a few things unclear
for example, i do not know what the value of lfstyle is, as you do not show it
as you have shown it being used, it should be an EQUate that represents a set of valid style bits
An oversight - it is defined by an equate: lfstyle EQU CS_HREDRAW or CS_VREDRAW or CS_DBLCLK
Quote
as for using the global class atom returned in RegisterClassEx as the lpClassName parameter,
that requires that the atom be converted to a 16-bit local atom - more trouble than it's worth
Roughly what I had guessed.
Quote
i think the problem may be that you are attempting to register the same class name twice
each time you register a new class, it must have a unique class name string
They do.
Quote
if you need further help, please attach complete code so that we can see all the constants and variables :U
OK. I'll see if I can figure out how to do that. It's posted at www.raleeper.com. Would a link be as good as attaching?
Thanks, ral
Quote from: raleeper on August 07, 2011, 04:21:24 PM
Quote from: dedndave on August 07, 2011, 01:06:33 PM
if you need further help, please attach complete code so that we can see all the constants and variables :U
QuoteOK. I'll see if I can figure out how to do that.
Got it. But if others are going to be looking at it, I'd better start cleaning it up.
[Later] But to clarify, I'm not asking for further help at this point. I had initially hoped that some dumb mistake might be obvious to the Forum experts. As that was not true, I'll double-check and maybe rewrite everything. Only after that will I ask for more help.[/Later]
Thanks, ral
I was using (in effect) addresses instead of values in the class structure. Truly a dumb mistake. It might have taken me longer to get it if not for some early posts.
Now CreateWindowEx returns error (0), but the message is "The operation completed successfully." I'll eventually figure this one out too, after I write the window procedure for the child window.
Thanks, ral
No, a return value of 0 from CreateWindowEx does not mean "operation completed successfully"... If CreateWindowEx returns NULL, you have to call GetLastError to get the correct error code.
ok - that is due to the return value from CWProc
you cannot just use
CWProc:
xor eax,eax
ret
first, it would have to be a RET 16, as there are 4 dword parameters that need to be POP'ed
second, many of the messages sent to the WndProc function must be passed to DefWindowProc
the WndProc function is called during the execution of CreateWindowEx
try this.....
CWProc: JMP DefWindowProc
if your assembler does not like that code, this should work
CWProc: push ebp
mov ebp,esp
INVOKE DefWindowProc,[ebp+8],[ebp+12],[ebp+16],[ebp+20]
pop ebp
ret 16
or even this :P
CWProc: INVOKE DefWindowProc,[esp+16],[esp+16],[esp+16],[esp+16]
ret 16
with some assemblers, you can register DefWindowProc as the lpfnWndProc
then, you don't need a proc :8)
Quote from: Gunner on August 07, 2011, 05:35:32 PM
No, a return value of 0 from CreateWindowEx does not mean "operation completed successfully"... If CreateWindowEx returns NULL, you have to call GetLastError to get the correct error code.
"operation completed successfully" is what I get fron GetLastError.
@dedndave: re "ret" in the w-proc: I had already flagged this mistake, but I appreciate the info as to what's going on.
Thanks, ral
[later] Wait a minute, I did correct it. I had changed "ret" to "retn" before I posted the code. And I still get the error from CreateWindowEx.
But as I said, I'll figure it out.
[Still later] OK, I see (or have come to believe) that the Child W-proc should pretty much mirror my main W-proc, with just the differences appropriate for the different characteristics and functions of the different window types. So I need a message handler and exits via DefWondowProc or InvalidateRectangle oe PostQuitMessage, etc. And, of course, "ret", not "retn". And probably a lot more "SendMessage"s.
try this, Ral....
Quote from: dedndave on August 07, 2011, 08:41:57 PM
try this, Ral....
@dedndave: Yours:
CWProc: push ebp
mov ebp,esp
INVOKE DefWindowProc,[ebp+8],[ebp+12],[ebp+16],[ebp+20]
pop ebp
ret 16
looks like a worthy alternative, but for now I'm going with the code below:
CWProc proc cwp_hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
(lots here)
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
CWProc endp
Too soon to judge whether it works, but it gets rid of the error from CreateWindowEx.
Thanks, ral
[later]
Also, I'm afraid to go into windows with an altered ebp - at least w/o a better understanding of the processes involved.
if you disassemble them, they are exactly the same thing :bg
(well - yours probably uses LEAVE instead of POP EBP)
yours is the right way :U
Quote from: zekyr on August 07, 2011, 10:26:08 AM
mov eax, [hwnd] ;grab memory pointed to by hwnd and stick it into eax
mov eax, hwnd ;stick handle into eax (which i thought we wanted here)
mov eax, offset hwnd ;stick address of hwnd which has a handle in it, which could be dereferenced into eax
Yes, zekyr you are correct ;Im using: MASM, TASM, SofTools
mov eax,[myVar] ;contents of
mov eax,myVar ;addresss of
There are no dumb questions, always blame it on the 'puter :green
Quote from: ixuta on August 08, 2011, 10:00:49 AM
Yes, zekyr you are correct ;Im using: MASM, TASM, SofTools
mov eax,[myVar] ;contents of
mov eax,myVar ;addresss of
Please test your code before posting in the Campus.
include \masm32\include\masm32rt.inc
.data
myvar dd 12345
.code
start:
mov ebx, [myvar]
print str$(ebx), 13, 10
mov ebx, myvar
print str$(ebx), 13, 10
mov ebx, offset myvar
print str$(ebx), 13, 10
inkey "ok?"
exit
end start
12345
12345
4202496
ok?
-
-d 0
13AB:0000 CD 20
-r
AX=0000 BX=0000 CX=0400 DX=0000 SP=00B8 BP=0000 SI=0000 DI=0000
DS=13AB ES=13AB SS=13BB CS=13BB IP=0000 NV UP EI PL NZ NA PO NC
13BB:0000 A10000 MOV AX,[0000] DS:0000=20CD
-t
AX=20CD BX=0000 CX=0400 DX=0000 SP=00B8 BP=0000 SI=0000 DI=0000
DS=13AB ES=13AB SS=13BB CS=13BB IP=0003 NV UP EI PL NZ NA PO NC
13BB:0003 B80000 MOV AX,0000
-t
AX=0000 BX=0000 CX=0400 DX=0000 SP=00B8 BP=0000 SI=0000 DI=0000
DS=13AB ES=13AB SS=13BB CS=13BB IP=0006 NV UP EI PL NZ NA PO NC
wow it's been a while since i've seen that screen :bg