Scan message map is a routine that puts a different twist on applications windows processes as follows
This is an excerpt taken from the program I used to test algorithm
00000014 00000000 MainMap dd 0
00000018 0001 dw (MapEnd - MainMap) / 6 - 1
0000001A 0002 dw WM_DESTROY
0000001C 00000187 R dd QuitApp
00000020 = 00000020 MapEnd equ $
; #################################################
0000017B WndProc proc
0000017B 33 DB xor ebx, ebx
0000017D BE 00000014 R mov esi, offset MainMap
00000182 E9 00000000 E jmp ScanMap
00000187 WndProc endp
00000187 QuitApp proc
00000187 6A 00 push 0
00000189 E8 00000000 E call PostQuitMessage
0000018E F9 stc
0000018F C3 ret
00000190 QuitApp endp
Reasons for this method
1: Ease of code maintenance where it isn't mixed with everything else as in QuitApp
2: Sharing same code with common windows such as text boxes that require only numerical input for example
3: If MainMap is declared in .data program can modify characteristics at runtime by changing entry points
NOTE I haven't tested the sub or superclassed procedure part yet
; SCANMAP.ASM 4:35 PM 2007.11.24
; written by Peter F. Hinteregger
; pfhinter@gmail.com
.686
.model flat, stdcall
option casemap:none
DefWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD
DefWindowProc equ <DefWindowProcA>
CallWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
CallWindowProc equ <CallWindowProcA>
includelib user32.lib
.code
; ============================================================================================
; ENTRY: ESI = Message Map for window
; MAP FORMAT 00 - Default procedure if window is sub or super classed
; 04 - Number of messages in map
; ; Each map definition is a set of six bytes each
; 06 - WORD API #'s WM_NULL > WM_WINPENLAST
; 08 - DWORD Pointer to handler
; --------------------------------------------------------------------------------------------
ScanMap PROC
; Initialize registers EBX = Pointer to default procdure if subclassed, else NULL
; ECX = Number of handlers for this window
; EDX = API number from OS
lodsd ; Get default procedures address if specified
mov ebx, eax ; Save for later if required
lodsw ; Get number of messages in map
xor ecx, ecx ; So MSB's are zero'ed
mov cx, ax ; Save number of messages in map
and ecx, ecx ; Is empty map
jz DefProc ; Not usually the case, but could be
mov edx, [esp + 8] ; Get API number from OS
; Loop through all definitions until match found or end of list
@@: lodsw ; Get application defined API number
cwde ; Sign extend to 32 bits
cmp eax, edx ; Establish equality
lodsd ; Get pointer to handler
jz Handle ; Do handler if matched
loop @B ; Continue until list exhausted
; Default procedure entry point if list is empty or application defined handler
; requires default processing reguardless
DefProc: and ebx, ebx
jnz @F ; Not subclassed
; At this point the stacks contents are:
; 00 - Return address to kernel
; 04 - hWnd
; 08 - uMsg
; 0C - wParam
; 10 - lParam
jmp DefWindowProc ; Drop into default processing
; Sub or superclassed processing requires on additonal prarameter to make
; stacks contents conform to calls expectations
@@: xchg ebx, [esp] ; Swap addresses
push ebx ; Push kernel return address again
jmp CallWindowProc ; Do sub or super classed processing
; This is where registers are setup for applications defined handler
Handle: push ebx ; Just in case
lea esi, [esp + 24] ; Coherse ESI to point to wParam
mov edx, [esp + 8] ; hWnd because so many events need this
call eax ; execute handler
pop ebx
jnc DefProc ; Do if CY = 0
; Default return value for application handled messages
xor eax, eax
ret 16
;
ScanMap ENDP
END