I would like to split up my message processing procedure (WndProc) into something like:

WndProc proc hWnd:HANDLE,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

Invoke MouseHandler,hWnd,uMsg,wParam,lParam


Invoke DefaultWndProc,hWnd,uMsg,wParam,lParam

Return 0
WndProc endp

However I would like to reduce the Invoke MouseHandler to something like a jmp.

I figured doing something like:

MouseHandler proc hWnd:HANDLE,uMsg:UINT,wParam:WPARAM,lParam:LPARAM


Return 0
MouseHandler endp

and replacing Invoke MouseHandler with a jmp tagMouseHandler would work, but MASM would still put the stackframe generation at the start of MouseHandler, which is wasted code as it won't be used. Is this the best solution to removing the Invoke?
Posted on 2002-04-25 04:37:18 by AmkG
I think what you are writing is a message despatcher which some people like in simple code.

For the mouse handler code, you can just jump to a label in the existing proc and RET back to where you called it from after. This will save you the stack overhead of pushing the 4 parameters that are sent to the Wndproc.

; your code


Posted on 2002-04-25 04:59:29 by hutch--
Jumping outside a proc with a stack frame can be dangerous :).
There's a couple of ways to do it... first would be using a raw label,
and put "leave" and "ret 16" at the end of the code. This should work,
but you will not have symbolic access to the previous proc's variable.

Another way to do it would be setting up a wndproc-like proc description
for your additional handlers, and put a global label as the first thing
in the proc, something like "mousehandler_hack::" (notice the two
colons). You can then jmp to these labels, and access the wndproc
parameters - however you can have no locals.

Hutch, "dispatching" is more useful in larger programs than in "simple"
programs, as it helps split up possibly *large* wndprocs. Ever
digged through a monolitic 3000-line if/elseif wndproc? No joy.
Posted on 2002-04-25 06:25:06 by f0dder

I thought of that solution actually, of course the problems are: 1. As you said, no locals, 2. Masm will still generate some OTHER code which never gets executed, mainly:

push ebp
mov ebp,esp
sub esp,n

I'd like to know if eliminating this extra code is possible. It probably isn't, but that's why I'm asking.

And yeah, by the way MouseHandler is in another source file... helps prevent things from being SO large
Posted on 2002-04-25 17:31:34 by AmkG
there's options for overriding masm's prologue and epilogue, search
around the board :)
Posted on 2002-04-26 07:36:23 by f0dder
My solution was to avoid using PROC for the WndProc.
; At entry:

; [ESP+0] = return address
; [ESP+4] = hWnd
; [ESP+8] = uMsg
; [ESP+12] = wParam
; [ESP+16] = lParam

mov eax,[esp+8] ; put uMsg into disposable register
cmp eax,WM_DESTROY
je OnDestroy ; OnDestroy is coded as a PROC
cmp eax,WM_CREATE
je OnCreate ; OnCreate is coded as a PROC
jmp DefWindowProc ; no need to copy arglist
Posted on 2002-04-26 15:40:36 by tenkey
The typical Message loop for a windows app would be loop(GetMessage/TranslateMessage/DispatchMessage). Is it possible to skip DispatchMessage? After all, when GetMessage fills the MSG structure it should contain hWnd,uMsg,wParam and lParam, right? It makes me wonder why we bother passing all this stuff to our window procedure if we could simply reference it from the MSG structure...

Could we possibly do away with DispatchMessage and replace it with a custom routine? Suppose GetMessage returns a WM_VSCROLL message for a certain window. Knowing the proc to call for scroll messages, could we call that directly and skip a "window procedure" altogether? Just call ScrollProc with a pointer to the MSG structure? Or is this dangerous? Or pointless?

I guess I'm wondering if we can save on a couple calls and stack frame changes...
Posted on 2002-04-27 09:14:50 by chorus