After wanting to better learn the Masm macroing system,
I started to play around with some ideas I had floating
around.

So far, there is no documentation and not all the controls
are supported, but it gives a fairly good representation of
what I would like to see this library achieve. I dont think
it will be hard reading in any case. So far it is still fairly
simple.

Check out the example program provided and let me know
what yall think. It uses a hybrid high speed dispatcher/
linked list approach. Still rather fast, but allows multiple
hooks per hWnd/ message.

Note: Currently I am more interested in optimizing the
macro code, but any feedback will be appriciated.
:alright:
Posted on 2003-09-04 22:24:13 by Graebel
I have worked off and on with a simular class object that does this sorta thing. I think this is good work, but since its macros is not dynamic (run time useable functions). As well, it appears that you are only able to register one window, correct me if im wrong here..

However, i like the work you have done, and i might borrow from it with the work im doing, if you do not mind.

Regards,
:NaN:
Posted on 2003-09-13 22:00:45 by NaN

I think this is good work, but since its macros is not dynamic (run time useable functions).


I am perhaps a little confused about this point. Perhaps you might clarify it some
so I can understand your meaning?


As well, it appears that you are only able to register one window, correct me if im wrong here..


The library itself only registers one window class, as far as I know thats all it needs.

You can however create as many top level or child windows as you like. The call to WinMain
is to start the message loop and know which window will close the application.

I decided to code it this way on purpose, because if you register another windows class
with a different WndProc you will not be able to hook events which is the main thrust of
this macro library (besides easy use and control creation) :cool:

Did I overlook something perhaps?


and i might borrow from it with the work im doing, if you do not mind.


Borrow away, or take, or anything else :) . I am posting no claims of property, ownership,
or anything else. Its completely free for any use.
Posted on 2003-09-13 22:54:51 by Graebel

I am perhaps a little confused about this point. Perhaps you might clarify it some
so I can understand your meaning?


LOL, yup. Im missing my point here too... well at least as written ;) . I was trying to get at the fact that macros are compile time tools. If you needed to dynamically create a child window at run time, by say a user inputing a set of parameters, your static macros wont work. However, i realize work arounds can be done to limit user imput to selection constraints, and doing if/else case structures to choose the correct macro.

This was my only point here.


As for the multiple registering of windows. Typically you do only register one, but i have made some programs where you register multpile windows. Typically custom controls, where each custom control you are using is also a window, and hence needs to be registered with in that process.


Lastly, thanks for sharing it. I find your work very clean an tidy to follow...
:NaN:
Posted on 2003-09-14 09:27:54 by NaN

Typically you do only register one, but i have made some programs where you register multpile windows. Typically custom controls, where each custom control you are using is also a window, and hence needs to be registered with in that process.


Ahh, its a custom control question.

It should be obvious from the way it is set up that the end user will miss the WM_CREATE message.
During window creation I am posting to the loop a ML_CREATE message that can be captured
as im sure you noticed. During the processing of this message, you can set up the hooks needed
for a custom control to work. This is assuming of course youll have only one instance of such a
control.

For more complicated work or custom controls, I would register a seperate class with its own
WndProc for the fine processing and at the end of WM_CREATE reset the WndProc to the Macro
Libs one. All the code could be in an include file at the top and as a bonus, you can set up another
handler for the creation so it would look like any other control. Am I a little fuzzy on this point,
but I believe (not tried it yet) that the DefWindowProc would continue to call the original proc
you set up. Maybe not. I have been busy with other things lately and havnt really tested this
code along those lines as yet. Perhaps superclassing would be a better option if it didnt work as
I am expecting it will.
Posted on 2003-09-14 11:26:39 by Graebel
Now I remember =)

Just register your own class as normal with its own WndProc and dont worry
about resetting it. As long as the custom control passes along pertinate
information along it would work like any other control.

ie. Make use of WM_COMMAND and perhaps custom message handlers
and just pass them along to thier respective parent windows. They should
in all repects act and feel like any other control.
Posted on 2003-09-14 11:33:37 by Graebel
I dont know bout structure macro. Please explan for me
Example: i have macro

macro pushd arg
{ if _#arg in <_addr arg,_ADDR arg>
local ..arg,..op //identifi ..arg,..op
label ..arg at arg //label ..arg at arg
virtual at 0 // what is it mean?
mov eax,..arg
load ..opcode from 0 // what is it mean?
end virtual
if ..opcode = 0A1h
push arg
else
lea edx,..arg
push edx
end if
else if arg eqtype ""
local ..continue
call ..continue
db arg,0
..continue:
else
push arg
end if }

Please help me....
Posted on 2003-09-26 21:06:46 by boysoledad
Graebel,

Did I overlook something perhaps?


Yes, I think you have. Every window in a multiple window program may have local variables. If the window does, it should use its stack for local storage in order for each window to be multitasking, because each window owns its own stack. This is usually done by a SUB ESP,4*(# of local variables) at the beginning of each windows dispatcher, and a ADD ESP,4*(# of local variables) to balance the stack at the end of the dispatcher. I see no provision for this to happen in your one-dispatcher-fits-all implementation.

Below is your dispatcher code:
How does the dispatcher get to the InitCommonControls call with a RET instruction before it?
Why do you return back to the dispatcher and search again after a handler is found and CALLed?

mlWndProc proc uses ebx hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD

mov eax, uMsg
mov ebx, DWORD PTR [mlMsgs+eax*4]
cmp ebx, 0
jne DISPATCH
DEFAULT:
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
invoke InitCommonControls
DISPATCH:
mov ecx, hWnd
cmp (mlMSGS PTR [ebx]).hWnd, ecx
je DOMESSAGE
cmp (mlMSGS PTR [ebx]).Next, 0
je DONE
mov ebx, (mlMSGS PTR [ebx]).Next
jmp DISPATCH
DOMESSAGE:
push lParam
push wParam
push uMsg
push hWnd
call (mlMSGS PTR [ebx]).Handler
cmp (mlMSGS PTR [ebx]).Next, 0
je DONE
mov ebx, (mlMSGS PTR [ebx]).Next
jmp DISPATCH
DONE:
ret
mlWndProc endp


Getting rid of the redundancies, spaghetti, and PROC directives (they're evil). I would write it this way: Ratch



mlMSGS struct
hWnd DWORD ?
Handler DWORD ?
mlMSGS ends
mlWndProc:
mov eax, [ESP+8] ; uMsg
mov ebx, [mlMsgs+eax*4]
cmp ebx, 0
JE DefWindowProc
DISPATCH:
mov ECX,[ESP+4] ; hWnd
cmp [mlMSGS.hWnd+EBX],ECX
JNE @F
JMP [mlMSGS.Handler+EBX]
@@:
cmp DWORD PTR [TYPE mlMSGS+EBX], 0
JE @F
ADD EBX, TYPE mlMSGS
jmp DISPATCH
@@:
RET 4*DWORD
Posted on 2003-10-20 07:37:48 by Ratch

I see no provision for this to happen in your one-dispatcher-fits-all implementation.


Well it was not intended as such. Although I am sure it could eventually be if someone
worked on it. I only posted the code to get feedback on the macros actually. What the
code itself did was interesting (I thought), but not the main thrust of what I was looking
for...


Below is your dispatcher code:
How does the dispatcher get to the InitCommonControls call with a RET instruction before it?


Good eye, it does not actually. I cant off the top of my head recall where I read it (perhaps
Iczelions great tuts?), but InitCommonControls itself (it seems) does not actually need to
be called. When the linker see's InitCommonControls it will make sure the DLL is loaded.
Actually calling it is a waste of time.


Why do you return back to the dispatcher and search again after a handler is found and CALLed?


Mainly for convenience and custom controls (of a different type).

Say I have a main app window and capture its WM_SIZE message (to size a window to its client
area or something). Later on - say I add a status bar, it also might need to capture the exact
same message from the same window. Of course I *could* have just added the code to the end
of the first procedure. I chose this method so I could seperate out each controls code to their own
seperate include file for both readability and maintenance purposes.


Getting rid of the redundancies, spaghetti, and PROC directives (they're evil). I would write it this way: Ratch


Probably closer to the way I usually code things (for myself), but per above I need the redundancies and spaghetti :tongue:
Posted on 2003-10-21 23:52:48 by Graebel