This is a code snippet from the fasm examples:



start:

invoke GetModuleHandle,0
mov [hinstance],eax
invoke LoadIcon,0,IDI_APPLICATION
mov [wc.hIcon],eax
invoke LoadCursor,0,IDC_ARROW
mov [wc.hCursor],eax
mov [wc.style],0
mov [wc.lpfnWndProc],WindowProc
mov [wc.cbClsExtra],0
mov [wc.cbWndExtra],0
mov eax,[hinstance]
mov [wc.hInstance],eax
mov [wc.hbrBackground],COLOR_BTNFACE+1
mov [wc.lpszMenuName],0
mov [wc.lpszClassName],_class
invoke RegisterClass,wc

invoke CreateWindowEx,0,_class,_title,[ws],100,100,256,128,NULL,NULL,[hinstance],NULL

msg_loop:
invoke GetMessage,msg,NULL,0,0
or eax,eax
jz end_loop
invoke TranslateMessage,msg
invoke DispatchMessage,msg

jmp msg_loop

end_loop:
invoke ExitProcess,[msg.wParam]

proc WindowProc, hwnd,wmsg,wparam,lparam
enter
push ebx esi edi
cmp [wmsg],WM_CREATE
je wmcreate
cmp [wmsg],WM_DESTROY
je wmdestroy
cmp [wmsg],WM_COMMAND
je wmcommand
cmp [wmsg],WM_GETMINMAXINFO
je wmgetminmaxinfo
defwndproc:
invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
jmp finish
wmcreate:
invoke CreateWindowEx,0,_button,_ws_sysmenu,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,16,256,16,[hwnd],ID_SYSMENU,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_thickframe,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,32,256,16,[hwnd],ID_THICKFRAME,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_minimizebox,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,48,256,16,[hwnd],ID_MINIMIZEBOX,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_maximizebox,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,64,256,16,[hwnd],ID_MAXIMIZEBOX,[hinstance],NULL
xor eax,eax
jmp finish


My questions are:

1) Why is an error not generated by the use of hwnd in the WindowProc line since this variable is nowhere declared?

2) If hwnd is the window's handle, why was it not necessary to save eax into it immediately ofter the CreateWindowX. (Notice that hwnd is used in subsequent calls as the window handle argument.)

I have been getting by for over a year without really understanding the above questions, but would really like to understand. It appears that understanding these points may be the key to my other recent posts involving setting the window background color.

Any help appreciated.
Posted on 2004-06-24 22:21:58 by msmith
The hwnd is a stack based variable that is declared as part of the WndProc...

proc WindowProc, [b]hwnd[/b],wmsg,wparam,lparam


It is not necessary to save it when the window is created because Windows will always pass that handle as the first parameter in callbacks to the WndProc. It is actually part of the MSG structure and DispatchMessageA will push the lParam, wParam, msg and hwnd then call the WndProc. This is true for all windows and controls, for example an edit control's DefWindowProc also has the handle of the edit passed as it's first parameter.
Posted on 2004-06-24 22:29:19 by donkey
You could save it immediately after the Createwindowex and most people do it.. and then if you would you would save it into a global variable.

Here the coder just uses the local variable hwnd which is passed by default in the WndProc of the created window

proc WindowProc, hwnd,wmsg,wparam,lparam

It is not necessary to save it immediately in this case as said it is passed on every call to WndProc.
---------
For setting the WIndow Background color you can just do the following: (Not fasm accurate syntax I suppose)

At the beginning:
invoke CreateSolidBrush, 0028D754h
mov,eax

And at the end_loop add following:

end_loop:
invoke DeleteObject,
Posted on 2004-06-24 22:33:23 by JimmyClif
Thanks for the quick reply guys!

I still don't understand all of the details.

For example:



invoke CreateWindowEx,0,!OBMainClass,!title,WS_VISIBLE+WS_OVERLAPPEDWINDOW,0,0,400,300,NULL,NULL,[!hinstance],!OBMain
mov [OBMain],eax
mov dword [!OBMain+44],eax
mov dword [!OBMain+8],eax
invoke SetWindowLong,[OBMain],GWL_USERDATA,!OBMain

!MsgLoop:
invoke GetMessage,msg,NULL,0,0
or eax,eax
jz !EndMsgLoop
invoke TranslateMessage,msg
invoke DispatchMessage,msg
jmp !MsgLoop
!EndMsgLoop:
invoke ExitProcess,[msg.wParam]

proc !WindowProc,hwnd,wmsg,wparam,lparam
enter
push ebx esi edi


compiles without error but produces no wind when executed.

If I change hwnd to OBMain in the Windoproc, it works.
Posted on 2004-06-24 22:49:28 by msmith
Hm, the code looks a bit weird... You have both OBMain and !OBMain - what is the !OBMain variable? What are those arbitrary +44 and +8 offsets?

I can see you pass !OBMain as the lparam to CreateWindowEx, as well as setting it as GWL_USERDATA, so I assume it's some data for the window.

As for the wndproc not working, it's a bit hard to tell why, as you haven't shown more of it's content :)
Posted on 2004-06-25 05:59:06 by f0dder
!OBMain is a descriptor table for use by my compiler and should have no bearing on this discussion.

In the begining of this post I was asking about the hwnd in the WindowProc.

Since hwnd was never declared in that example, I was asking how it worked. The answer had to do with it being a stack variable.

Maybe a better way to ask the question is "what effect does the handle arg have on the WindowProc".
Posted on 2004-06-25 09:11:48 by msmith
Why would it have an effect? It's just the handle of your window passed along for your convenience.

Parts of this snippet of code are redundant:




invoke CreateWindowEx,0,!OBMainClass,!title,WS_VISIBLE+WS
_OVERLAPPEDWINDOW,0,0,400,300,NULL,NULL,[!hinstanc
e],!OBMain
mov [OBMain],eax
mov dword [!OBMain+44],eax
mov dword [!OBMain+8],eax
invoke SetWindowLong,[OBMain],GWL_USERDATA,!OBMain


So, you pass a structure OBMain as Userdata in the call to createwindowex in the last argument.

Then you save the windows handle in the first, the 11 and the 3rd argument.

Next you set the Userdata to OBMain again.

Why would you want to save the handle 3 times and set the Userdata twice to the same value.

But anyway.. this should work, I don't see no reason why not. Maybe post your WM_CREATE handler including your wndproc for us to see what might be wrong.

Just on a sidenote, you can not use the handle of the window you pass in OBMain inside the WindowProc in WM_CREATE or at the DefWindowProc call as the call to CreateWindowEx only returns after WM_CREATE has been called.
Posted on 2004-06-25 09:42:04 by JimmyClif
Hi Jimmy,

The !OBMain stuff is the window's descriptor and has absolutely no bearing on this discussion.


Next you set the Userdata to OBMain again


Not at all, I set the UserData to the address of the descriptor structure.

In that structure, the 8 offset is the owner and the 44 offset is the handle.

None of this has anything to do with my question(s).
Posted on 2004-06-25 11:11:48 by msmith
First of all: I answered your question.

Your question was:

"what effect does the handle arg have on the WindowProc".

And my answer was:

"None, It's just the handle of your window passed along for your convenience."

All the other stuff I told you was purely because I was nice, even if I was wrong on one point. I was just trying to help.


Not at all, I set the UserData to the address of the descriptor structure.


You are right, I confused the lParam of the CreateWindowEx call with UserData.

In that structure, the 8 offset is the owner and the 44 offset is the handle.


Call it what you want, I call it storing the same handle into three different places. How many main windows do you have running through that WndProc to be needing such a structure? One? ;)

None of this has anything to do with my question(s).


Lets try that again. You ask clear to the point questions and we try to answer them. Well I won't but someone else might.

Have a nice day.
Posted on 2004-06-25 12:03:42 by JimmyClif
Hi Jimmy,


All the other stuff I told you was purely because I was nice, even if I was wrong on one point. I was just trying to help.


I'm very sorry if you think I did'nt/don't appreciate your help and efforts. It is very appreciated. I'm not sure what I said to offend you, but if you look at my posts and reponses over the last couple years you will see that I always appreciate the help of others and often express thanks.

You may have sensed my frustration with the subject matter.

I will try to find a simpler example (if possible) to show the problem I am having. I was easier and more accurate to show the example I did because it is the one causing my problem (ie not hypothetical)

For you and one other respondent (and probably others), it is clear that some of the compiler housekeeping is a distraction to the case in point.

In any event thank you very much for your help now, in the past, and in the future.

Perhaps I will be able to help you sometime.

BTW I was looking at your sort problem last night, but it was getting late. I will check to see if someone helped you. If not I will.

Mike
Posted on 2004-06-25 15:45:37 by msmith
Hi Mike,

I am afraid I am not familiar enough with FASM syntax to be specific.

The stack variable hWnd (or whatever) in the WndProc is filled by Windows and is not affected by anything you do in your program. The actual value is written to the WNDCLASSEX structure maintained internally by Windows when you call CreateWindowEx. That handle is passed as the first parameter to the WndProc specified in the WNDCLASSEX structure and is completely independant of your code. Whether you save the handle or not does not effect it, in creating the Window that handle value is also created, you cannot change nor effect it in any way.

You have said that your window is not appearing in some circumstances, what was the value in EAX when this happened ? What error code did GetLastError report ? This information is critical to diagnosing the problem.
Posted on 2004-06-25 21:08:18 by donkey
Hi Donkey,

Always good to hear from you.

I'm too tired to work on it tonight, but I'll try to provide you the info by tomorrow night.

I also have some tests I want to perform in the form of variations to the basic fasm example.

Some of the compiler generated stuff seems to distract people from the actual question I'm am asking. I can appreciate that.

Anyway, I'll be back tomorrow hopefully with answers and better examples.

Thanks,

Mike
Posted on 2004-06-25 21:28:05 by msmith
Ah, finally I have duplicated the situation using only the fasm example shown earlier in the post.

The example below differs from the original in only the following ways:

1) It has the necessesary includes and library defs to allow coloring the window

2) It has saved the handle explicitly from the CreateWindowEx

3) It has used this handle in all references.




; Caption styles manipulation - Win32 example program

format PE GUI 4.0
entry start

include 'includekernel.inc'
include 'includeuser.inc'
include 'includegdi.inc'

include 'includemacrostdcall.inc'
include 'includemacroimport.inc'

section '.data' data readable writeable

hinstance dd 0
OBMain rd 1

msg MSG
wc WNDCLASS

ws dd WS_VISIBLE+WS_CAPTION

_class db 'FCAPTION',0
_button db 'BUTTON',0

_title db 'Caption styles',0
_ws_sysmenu db 'WS_SYSMENU',0
_ws_thickframe db 'WS_THICKFRAME',0
_ws_minimizebox db 'WS_MINIMIZEBOX',0
_ws_maximizebox db 'WS_MAXIMIZEBOX',0

virtual at 0
minmaxinfo MINMAXINFO
end virtual

ID_SYSMENU = 101
ID_THICKFRAME = 102
ID_MINIMIZEBOX = 103
ID_MAXIMIZEBOX = 104

section '.code' code readable executable

start:

invoke GetModuleHandle,0
mov [hinstance],eax
invoke LoadIcon,0,IDI_APPLICATION
mov [wc.hIcon],eax
invoke LoadCursor,0,IDC_ARROW
mov [wc.hCursor],eax
mov [wc.style],0
mov [wc.lpfnWndProc],WindowProc
mov [wc.cbClsExtra],0
mov [wc.cbWndExtra],0
mov eax,[hinstance]
mov [wc.hInstance],eax
mov [wc.hbrBackground],COLOR_BTNFACE+1
mov [wc.lpszMenuName],0
mov [wc.lpszClassName],_class
invoke RegisterClass,wc

invoke CreateWindowEx,0,_class,_title,[ws],100,100,256,128,NULL,NULL,[hinstance],NULL
mov [OBMain],eax

msg_loop:
invoke GetMessage,msg,NULL,0,0
or eax,eax
jz end_loop
invoke TranslateMessage,msg
invoke DispatchMessage,msg

jmp msg_loop

end_loop:
invoke ExitProcess,[msg.wParam]

proc WindowProc, hwnd,wmsg,wparam,lparam
enter
push ebx esi edi
cmp [wmsg],WM_CREATE
je wmcreate
cmp [wmsg],WM_DESTROY
je wmdestroy
cmp [wmsg],WM_COMMAND
je wmcommand
cmp [wmsg],WM_GETMINMAXINFO
je wmgetminmaxinfo
defwndproc:
invoke DefWindowProc,[OBMain],[wmsg],[wparam],[lparam]
jmp finish
wmcreate:
invoke CreateWindowEx,0,_button,_ws_sysmenu,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,16,256,16,[OBMain],ID_SYSMENU,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_thickframe,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,32,256,16,[OBMain],ID_THICKFRAME,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_minimizebox,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,48,256,16,[OBMain],ID_MINIMIZEBOX,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_maximizebox,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,64,256,16,[OBMain],ID_MAXIMIZEBOX,[hinstance],NULL
xor eax,eax
jmp finish
wmcommand:
cmp [wparam],BN_CLICKED shl 16 + ID_SYSMENU
je switch_sysmenu
cmp [wparam],BN_CLICKED shl 16 + ID_THICKFRAME
je switch_thickframe
cmp [wparam],BN_CLICKED shl 16 + ID_MINIMIZEBOX
je switch_minimizebox
cmp [wparam],BN_CLICKED shl 16 + ID_MAXIMIZEBOX
je switch_maximizebox
jmp defwndproc
switch_sysmenu:
invoke CreateSolidBrush,0080FFFFh
invoke SetClassLong,[OBMain],GCL_HBRBACKGROUND,eax
invoke InvalidateRect,[OBMain],NULL,TRUE
invoke UpdateWindow,[OBMain]
mov ebx,WS_SYSMENU
jmp set_flag

switch_thickframe:
mov ebx,WS_THICKFRAME
jmp set_flag
switch_minimizebox:
mov ebx,WS_MINIMIZEBOX
jmp set_flag
switch_maximizebox:
mov ebx,WS_MAXIMIZEBOX
set_flag:
invoke SendMessage,[lparam],BM_GETCHECK,0,0
or eax,eax
jz clear_flag
or [ws],ebx
jmp update_style
clear_flag:
not ebx
and [ws],ebx
update_style:
invoke SetWindowLong,[OBMain],GWL_STYLE,[ws]
invoke RedrawWindow,[OBMain],0,0,RDW_FRAME+RDW_INVALIDATE+RDW_UPDATENOW
xor eax,eax
jmp finish
wmgetminmaxinfo:
mov ebx,[lparam]
mov [ebx+minmaxinfo.ptMinTrackSize.x],192
mov [ebx+minmaxinfo.ptMinTrackSize.y],128
xor eax,eax
jmp finish
wmdestroy:
invoke PostQuitMessage,0
xor eax,eax
finish:
pop edi esi ebx
return

section '.idata' import data readable writeable

library kernel,'KERNEL32.DLL',
user,'USER32.DLL',
gdi,'GDI32.DLL'

kernel:
import GetModuleHandle,'GetModuleHandleA',
ExitProcess,'ExitProcess'

user:
import RegisterClass,'RegisterClassA',
CreateWindowEx,'CreateWindowExA',
DefWindowProc,'DefWindowProcA',
SetWindowLong,'SetWindowLongA',
SetClassLong,'SetClassLongA',
RedrawWindow,'RedrawWindow',
GetMessage,'GetMessageA',
TranslateMessage,'TranslateMessage',
DispatchMessage,'DispatchMessageA',
SendMessage,'SendMessageA',
InvalidateRect,'InvalidateRect',
UpdateWindow,'UpdateWindow',
LoadCursor,'LoadCursorA',
LoadIcon,'LoadIconA',
PostQuitMessage,'PostQuitMessage'

gdi:
import CreateFontIndirect,'CreateFontIndirectA',
CreateSolidBrush,'CreateSolidBrush'



The way the program is given, it will compile without error, but when executed, will return showing no window.

If I change the line:



proc WindowProc, hwnd,wmsg,wparam,lparam


to:



proc WindowProc,OBMain,wmsg,wparam,lparam


all is well.

Since I have explicitly saved the handle after the CreateWindowEx and used this handle everywhere else in the program, AND Windows is simply offering me a convenience by giving me the handle in the WindowProc line the why does this program only work when the handle specified in this line is used?
Posted on 2004-06-27 11:24:32 by msmith
Hi Mike,

Well, I do not have FASM installed and as I said I am not familiar with the syntax but everything looks fine. I would attack the problem by leaving the hwnd in place and verfiying that a WM_CREATE is sent. At that point check the handle value of OBMain and hwnd. I beleive that CreateWindowExA returns *after* it sends the WM_CREATE message so since you are using OBMain in that handler it will be null when WM_CREATE is received. You can ofcourse always assign the value to OBMain in the WM_CREATE handler or use in it's place. In practice I always use in the WndProc and never a global handle...

Posted on 2004-06-27 13:36:54 by donkey
Hi Donkey,

Thanks for your help.

It looks like the problem is that, like you said, the CreateWindowEx returns AFTER a WM_CREATE is sent.

In fact, the docs say:


The WM_CREATE message is sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. (The message is sent before the function returns.) The window procedure of the new window receives this message after the window is created, but before the window becomes visible.


This renders the concept of saving the handle following the CreateWindowEx line to be completely meaningless.

I'll do some more tests, but I think you are correct.

BTW, In a compiler of the type that I am writing, there are a number of occasions where the global handle is needed.

Knowing now what seems to be true about all of this, I think I can code around the situation.

If I always have a separate WindowProc for each window, it seems that I should be able to use the hwnd stack var to set my structure's handle member and that that window should receive only one WM_CREATE msg. Does this sound right to you?

Thanks,

Mike
Posted on 2004-06-27 14:18:05 by msmith
Hi Donkey,

It just keeps getting stranger!

I put the following code at the start of the WM_CREATE event.



mov eax,[!hwnd]
mov [!OBMain+44],eax


(I am using !OBMain+44 as an arg to all of the places where I need the window's handle.)

It does not work.

I remove this code from the WM_CREATE code and put it at the start of the default window proc code and it works fine.

The only way I can see this happening is that there is a WM_COMMAND event PRIOR to the WM_CREATE event because the only dispatch to this code is unprocessed command events.
This problem has been bothering me for about a year and a half and I have been working with work-a-rounds all this time.

Jimmy noticed I was setting 3 vars to the same value in an earlier post. This was part of the work-a-round.

I'll do some more testing, but I think I have it now.

Whole code that now works:




; Caption styles manipulation - Win32 example program

format PE GUI 4.0
entry start

include 'includekernel.inc'
include 'includeuser.inc'
include 'includegdi.inc'

include 'includemacrostdcall.inc'
include 'includemacroimport.inc'

section '.data' data readable writeable

hinstance dd 0
!OBMain rd 500

msg MSG
wc WNDCLASS

ws dd WS_VISIBLE+WS_CAPTION

_class db 'FCAPTION',0
_button db 'BUTTON',0

_title db 'Caption styles',0
_ws_sysmenu db 'WS_SYSMENU',0
_ws_thickframe db 'WS_THICKFRAME',0
_ws_minimizebox db 'WS_MINIMIZEBOX',0
_ws_maximizebox db 'WS_MAXIMIZEBOX',0

virtual at 0
minmaxinfo MINMAXINFO
end virtual

ID_SYSMENU = 101
ID_THICKFRAME = 102
ID_MINIMIZEBOX = 103
ID_MAXIMIZEBOX = 104

section '.code' code readable executable

start:

invoke GetModuleHandle,0
mov [hinstance],eax
invoke LoadIcon,0,IDI_APPLICATION
mov [wc.hIcon],eax
invoke LoadCursor,0,IDC_ARROW
mov [wc.hCursor],eax
mov [wc.style],0
mov [wc.lpfnWndProc],WindowProc
mov [wc.cbClsExtra],0
mov [wc.cbWndExtra],0
mov eax,[hinstance]
mov [wc.hInstance],eax
mov [wc.hbrBackground],COLOR_BTNFACE+1
mov [wc.lpszMenuName],0
mov [wc.lpszClassName],_class
invoke RegisterClass,wc

invoke CreateWindowEx,0,_class,_title,[ws],100,100,256,128,NULL,NULL,[hinstance],NULL

msg_loop:
invoke GetMessage,msg,NULL,0,0
or eax,eax
jz end_loop
invoke TranslateMessage,msg
invoke DispatchMessage,msg

jmp msg_loop

end_loop:
invoke ExitProcess,[msg.wParam]

proc WindowProc, !hwnd,wmsg,wparam,lparam
enter
push ebx esi edi
cmp [wmsg],WM_CREATE
je wmcreate
cmp [wmsg],WM_DESTROY
je wmdestroy
cmp [wmsg],WM_COMMAND
je wmcommand
cmp [wmsg],WM_GETMINMAXINFO
je wmgetminmaxinfo
defwndproc:
mov eax,[!hwnd]
mov [!OBMain+44],eax
invoke DefWindowProc,[!OBMain+44],[wmsg],[wparam],[lparam]
jmp finish
wmcreate:
invoke CreateWindowEx,0,_button,_ws_sysmenu,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,16,256,16,[!OBMain+44],ID_SYSMENU,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_thickframe,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,32,256,16,[!OBMain+44],ID_THICKFRAME,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_minimizebox,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,48,256,16,[!OBMain+44],ID_MINIMIZEBOX,[hinstance],NULL
invoke CreateWindowEx,0,_button,_ws_maximizebox,WS_VISIBLE+WS_CHILD+BS_AUTOCHECKBOX,16,64,256,16,[!OBMain+44],ID_MAXIMIZEBOX,[hinstance],NULL
xor eax,eax
jmp finish
wmcommand:
cmp [wparam],BN_CLICKED shl 16 + ID_SYSMENU
je switch_sysmenu
cmp [wparam],BN_CLICKED shl 16 + ID_THICKFRAME
je switch_thickframe
cmp [wparam],BN_CLICKED shl 16 + ID_MINIMIZEBOX
je switch_minimizebox
cmp [wparam],BN_CLICKED shl 16 + ID_MAXIMIZEBOX
je switch_maximizebox
jmp defwndproc
switch_sysmenu:
invoke CreateSolidBrush,0080FFFFh
invoke SetClassLong,[!OBMain+44],GCL_HBRBACKGROUND,eax
invoke InvalidateRect,[!OBMain+44],NULL,TRUE
invoke UpdateWindow,[!OBMain+44]
mov ebx,WS_SYSMENU
jmp set_flag

switch_thickframe:
mov ebx,WS_THICKFRAME
jmp set_flag
switch_minimizebox:
mov ebx,WS_MINIMIZEBOX
jmp set_flag
switch_maximizebox:
mov ebx,WS_MAXIMIZEBOX
set_flag:
invoke SendMessage,[lparam],BM_GETCHECK,0,0
or eax,eax
jz clear_flag
or [ws],ebx
jmp update_style
clear_flag:
not ebx
and [ws],ebx
update_style:
invoke SetWindowLong,[!OBMain+44],GWL_STYLE,[ws]
invoke RedrawWindow,[!OBMain+44],0,0,RDW_FRAME+RDW_INVALIDATE+RDW_UPDATENOW
xor eax,eax
jmp finish
wmgetminmaxinfo:
mov ebx,[lparam]
mov [ebx+minmaxinfo.ptMinTrackSize.x],192
mov [ebx+minmaxinfo.ptMinTrackSize.y],128
xor eax,eax
jmp finish
wmdestroy:
invoke PostQuitMessage,0
xor eax,eax
finish:
pop edi esi ebx
return

section '.idata' import data readable writeable

library kernel,'KERNEL32.DLL',
user,'USER32.DLL',
gdi,'GDI32.DLL'

kernel:
import GetModuleHandle,'GetModuleHandleA',
ExitProcess,'ExitProcess'

user:
import RegisterClass,'RegisterClassA',
CreateWindowEx,'CreateWindowExA',
DefWindowProc,'DefWindowProcA',
SetWindowLong,'SetWindowLongA',
SetClassLong,'SetClassLongA',
RedrawWindow,'RedrawWindow',
GetMessage,'GetMessageA',
TranslateMessage,'TranslateMessage',
DispatchMessage,'DispatchMessageA',
SendMessage,'SendMessageA',
InvalidateRect,'InvalidateRect',
UpdateWindow,'UpdateWindow',
LoadCursor,'LoadCursorA',
LoadIcon,'LoadIconA',
PostQuitMessage,'PostQuitMessage'

gdi:
import CreateFontIndirect,'CreateFontIndirectA',
CreateSolidBrush,'CreateSolidBrush'
Posted on 2004-06-27 15:07:37 by msmith
WM_CREATE is not the first message sent to the window. From MSDN:

For overlapped, pop-up, and child windows, CreateWindow sends WM_CREATE, WM_GETMINMAXINFO, and WM_NCCREATE messages to the window


Apparently, it sends WM_GETMINMAXINFO, then WM_NCCREATE and then WM_CREATE (I could be wrong though).
Obviously, you shouldn't rely on your global handle copy in your WndProc.
Outside of your WndProc, you can use the global handle copy. Since it is returned by the window creation function, this shouldn't be a problem.
Posted on 2004-06-27 15:31:54 by death
Hi death

Actually it sends an NC_CALCSIZE not a WM_GETMINMAXINFO.

Hi Mike,

I will download and install FASM later tonight to test your code as I am not sure what's up with it. I am almost absolutely sure that you *must* use the parameter of the WndProc in the DefWindowProc call otherwise it will lead to problems. I remember having a similar problem once and that was the solution.
Posted on 2004-06-27 15:44:54 by donkey
Hi donkey,
I believe you mean WM_NCCALCSIZE. It might send this message as well, but the first message I got when I created a window was WM_GETMINMAXINFO, and MSDN clearly states that it is being sent.
Posted on 2004-06-27 20:20:23 by death
Hi death,

Yeah, WM_NCCALCSIZE, no, MSDN does not say that it is sent before CreateWindowEx returns, the quote you posted is not accurate. However, the WMGETMINMAXINFO is sent if you do not handle the WM_NCCALCSIZE message I believe. The actual page says...

The CreateWindowEx function sends WM_NCCREATE, WM_NCCALCSIZE, and WM_CREATE messages to the window being created.


CreateWindowEx
Posted on 2004-06-27 20:39:20 by donkey