The main idea is to make user defined message procedures without subclassing windows, but using modified message loop. Here is only part of the message loop, ilustrating the idea:
The user can then attach user message procedure to every window, simply by using:
...and to stop the processing with:
User message procedure doesn't have to preserve any register and if it returns CF=1, default message procedure will be invoked by DispatchMessage.
What you think about this approach? Any hidden problems, I missed?
Regards.
.translate:
invoke TranslateMessage, esi
invoke GetProp, [esi+MSG.hwnd], propUserWinProc
test eax, eax
jz .default ; there is no user procedure...
; call user procedure if any...
push esi
stdcall eax, [esi+MSG.hwnd], [esi+MSG.message], [esi+MSG.wParam], [esi+MSG.lParam]
pop esi
jnc .msg_loop
.default:
invoke DispatchMessage, esi
jmp .msg_loop
propUserWinProc db 'UserWinProc', 0
The user can then attach user message procedure to every window, simply by using:
invoke SetProp, [.hwnd], propUserWinProc, ptrToMyUserProc
...and to stop the processing with:
invoke RemoveProp, [.hwnd], propUserWinProc
User message procedure doesn't have to preserve any register and if it returns CF=1, default message procedure will be invoked by DispatchMessage.
What you think about this approach? Any hidden problems, I missed?
Regards.
It doesn't work when a message is sent using SendMessage from within the same thread. This causes the appropriate window procedure to be called directly.
It doesn't work when a message is sent using SendMessage from within the same thread. This causes the appropriate window procedure to be called directly.
Yes, but especially for user program, that can be fixed with something like in the message loop:
proc MySendMessage, .hwnd, .wmsg, .wparam, .lparam
begin
invoke GetProp, [esi+MSG.hwnd], propUserWinProc
test eax, eax
jz .direct ; there is no user procedure...
; call user procedure if any...
push esi
stdcall eax, [.hwnd], [.wmsg], [.wparam], [lparam]
pop esi
jnc .finish
.direct:
invoke SendMessage, [.hwnd], [.wmsg], [.wparam], [lparam]
.finish:
return
So, the question is whether the OS sends direct messages with SendMessage, or not?
BTW, even normal subclassing is very simple using SetProp and GetProp functions:
proc SubclassWindow, .hwnd, .ptrUserProc
begin
invoke GetWindowLong, [.hwnd], GWL_WNDPROC
invoke SetProp, [.hwnd], propOldWinProc, eax
invoke SetProp, [.hwnd], propUserWinProc, [.ptrUserProc]
invoke SetWindowLong, [.hwnd], GWL_WNDPROC, UniversalWinProc
return
endp
proc UniversalWinProc, .hwnd, .wmsg, .wparam, .lparam
begin
invoke GetProp, [.hwnd], propUserWinProc
test eax, eax
jz .oldproc
push ebx esi edi
stdcall eax, [.hwnd], [.wmsg], [.wparam], [.lparam]
pop edi esi ebx
jnc .finish
.oldproc:
invoke GetProp, [.hwnd], propOldWinProc
invoke CallWindowProc, eax ,[.hwnd],[.wmsg],[.wparam],[.lparam]
.finish:
return
endp
propOldWinProc db 'OldWinProc', 0
propUserWinProc db 'UserWinProc', 0
Here the user procedure does not heve to call old windows procedure and does not have to preserve registers, it uses the convention from the example in my first post.
The OS sends quite a few messages with SendMessage. Many APIs cause messages to be sent (for example SetFocus, EnableWindow, SetWindowPos) and controls also send messages.