If you don't have the MASM32 package (includes samples, header files, pre made libs etc) get it from MASM32
We are going to use Subclassing to accomplish this fairly easy task. What is subclassing? Well, windows sends many different messages to your app. Each control has its own internal message handler to handle different messages like painting, coloring, mouse clicks just to name a few.
Without Subclassing, windows "Dispatches" the messages (events) to the controls handler and we are stuck with the default way the edit control works...
Now enter subclassing... We are basically telling windows we want to be the "middle man". Windows will dispatch the message, we get it before the control does, so we can process the messages and act on the ones we want then send the message on to the controls handler, for the ones we don't want to process, we just pass them on so the control can process them. In our case, we will discard any characters we don't want. We won't pass them on.
Complete source is attached.
First we create an edit control the normal way:
;##### Hex Edit invoke CreateWindowEx, WS_EX_CLIENTEDGE, offset szWndClsEdit, NULL, WS_CHILD or WS_VISIBLE or WS_TABSTOP, 5, 200, 285, 20, hWin, 0, hInst, 0
Next we will subclass the control and tell windows to send all messages to our procedure.
invoke SetWindowLong, eax, GWL_WNDPROC, addr SubClassNumbers
That is it, we will now be the "middle man", but we need the address of the original procedure for the control, so we can pass messages to it. Lucky for us, the return value of SetWindowLong with the style GWL_WNDPROC is the address of the original proc!
So save it...
mov lpNumberProc, eax
Now we need to have to make a callback proc called SubClassNumbers in this example:
SubClassNumbers proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM mov eax,uMsg .if eax == WM_CHAR mov eax, wParam .if (al >= 48 && al <= 57) || al == 8 ;##### Only allow 0 - 9 and backspace keys invoke CallWindowProc, lpUpperProc, hWin, uMsg, eax, lParam ret .endif .else invoke CallWindowProc, lpNumberProc, hWin, uMsg, wParam, lParam ret .endif CharNotWanted: xor eax, eax ret SubClassNumbers endp
Now, we will get all the messages meant for this instance of the Edit control first!
Ah, ok I will break it down...
We only want to handle the WM_CHAR message so, the first .if we check to see if it is, if it is not, we pass it on to the original edit proc in the .else handler by passing on uMsg, wParam, lParam all unchanged
The character code is in wParam, so that is what we want...
.if eax == WM_CHAR mov eax, wParam .if (al >= 48 && al <= 57) || al == 8 ;##### Only allow 0 - 9 and backspace keys invoke CallWindowProc, lpUpperProc, hWin, uMsg, eax, lParam ret .endif
Now, the character code (wParam) is in the lower 8 bits of eax, which is al.. so we do our comparisons on al.
So, what the above does is: if the key pressed is 0 - 9 or the backspace key, we pass it on to the original edit proc for display (we modify wParam and pass it on)
If the key pressed is anything else, we discard it, so the original edit proc won't even get it or know it was pressed.
The attached code we have 4 edit controls, one just numbers, one only uppercase, one only lowercase, and one only hex (0-9, A-F and H)
Wait, how about using masks? Ah, that will be another tutorial
Subclassing is a very powerful tool to have.
Number of downloads: 334
This post has been edited by GunnerInc: 31 July 2011 - 05:20 PM