I have an edit control subclassed to allow only hex digits.
The problem is when i paste something to it gets wrong result.
And also what should I correct to allow pasting through ctrl+v.
here is my code (lame?)

EditWndProc PROC hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL BUFF[128]:BYTE
LOCAL tlen:DWORD
.if uMsg==WM_CHAR
mov eax,wParam
.if al>="a" && al<="f"
sub al,20h
.endif
.if (al>="0" && al<="9") || (al>="A" && al<="F") || al==VK_BACK
invoke CallWindowProc,OldEdProc,hEdit,uMsg,eax,lParam
ret
.endif
.elseif uMsg==WM_PASTE
mov tlen,0
invoke CallWindowProc,OldEdProc,hEdit,uMsg,wParam,lParam
invoke GetWindowText,hEdit,addr BUFF,127
invoke SetWindowText,hEdit,addr tlen
push esi
lea esi,BUFF
.while tlen<127
lodsb
invoke SendMessage,hEdit,WM_CHAR,eax,0
inc tlen
.endw
pop esi
ret
.else
invoke CallWindowProc,OldEdProc,hEdit,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
EditWndProc endp
Posted on 2001-08-15 23:47:59 by Yuk
Try changing the WM_PASTE code to this:


.elseif uMsg==WM_PASTE
invoke CallWindowProc, OldWndProc, hEdit, uMsg, wParam, lParam
invoke GetWindowText, hEdit, addr BUFF, 127
mov tlen, eax
invoke SetWindowText, hEdit, NULL

push esi
xor esi, esi
@@: xor eax, eax
mov al, BUFF[esi]
invoke SendMessage, hEdit, WM_CHAR, eax, 0
inc esi
cmp esi, tlen
jnz @B

pop esi

I'm not sure what your problem was. I re-wrote the while loop in a way I understood, and it works!
It also only adds characters up to the length of the text. This may have been part of the problem you were having, but I can't be sure....

I may look at the original code some more if I've got time.

Mirno
Posted on 2001-08-16 06:43:11 by Mirno
Doh!
I am soooo stupid!

Yes the scanning the whole buffer is the problem!

When you declare the buffer it is on the stack.
The contents of this buffer (at initialisation) are whatever was on the stack previously (basically a whole lot of rubbish). Because you scan the entire 128 bytes of the buffer (no matter how long the string is), you go into this unknown stuff in the buffer. Some of it happens to be in the range allowed by your WM_CHAR stuff, and so its added to the edit box.

To avoid this problem using your own code (rather than mine which also does the job, but in a different way), you need to leave the WHILE loop when you read the NULL terminator of the string.


.while tlen < 127
lodsb
.BREAK .IF al == 0
invoke SendMessage, hEdit, WM_CHAR, eax, 0
inc tlen
.endw


The extra line ".BREAK .IF al == 0" performs an extra comparison, and if it is the null terminator will exit your while loop early.

Mirno
Posted on 2001-08-16 06:59:23 by Mirno
Thank you Mirno.
I see. I will try your code.
Btw, My EditControl has a fixed length of 16.
Posted on 2001-08-16 07:33:13 by Yuk
In WM_PASTE
I would open buffer and check in it if the string all characters
are valid.
If not - just exit subproc.
Else call OldProc
Posted on 2001-08-16 08:08:36 by The Svin
You can also do this without the buffer (or the tlen because I used esi & edi instead).

This code does the following:
1) Check the clipboard format (make sure its text)
2) Open the clipboard
3) Gets the data from the clipboard
4) Adds it character by character to the original text.



.ELSEIF uMsg == WM_PASTE
invoke IsClipboardFormatAvailable, CF_TEXT
or eax, eax
jnz @F
xor eax, eax
ret

@@: invoke OpenClipboard, NULL
invoke GetClipboardData, CF_TEXT
push esi
push edi
mov esi, eax

invoke StrLen, esi
mov edi, eax

@@: xor eax, eax
mov al, BYTE PTR [esi]
invoke SendMessage, hEdit, WM_CHAR, eax, 0
inc esi
dec edi
jnz @B

pop edi
pop esi
invoke CloseClipboard


It is better in the sense that it doesn't delete the old data, then reprocess it. With the other algo, the data in edit box was re-processed every time a paste occured. By rights any code in the box needs to be in the correct format, otherwise it couldn't have got in there, so why check it again when you paste?

Unfortunately this code makes no attempt to open the clipboard properly (ie if it fails it carries on reguardless, which is bad).

Mirno
Posted on 2001-08-16 09:38:00 by Mirno
Yuk, this1 works for me fine..



EditProc PROC ;
; Process control messages ;
mov eax, [esp+8] ; message
;........????...................;
cmp eax,WM_PASTE ; Msg
jne EditProc_4 ;
;.WM_PASTE .......????..........;
push CF_TEXT ;
call IsClipboardFormatAvailable
test eax, eax ;
jz EditProc_Ret_0 ;
push hWnd ;
call OpenClipboard ;
test eax, eax ;
jz EditProc_Ret_0 ;
push CF_TEXT ;
call GetClipboardData;
test eax, eax ;
jz EditProc_Ret_0 ;
push eax ; for GlobalUnlock
push eax ;
call GlobalLock ;
test eax, eax ;
jnz EditProc_1 ;
pop eax ;
jz EditProc_Ret_0 ;
EditProc_1: ;
lea edi, Buffer1 ;
mov ebx, 5 ;
xor ecx, ecx ;
xor edx, edx ;
EditProc_2: ;
mov cl, [eax] ;
inc eax ;
test ecx, ecx ;
jz EditProc_3 ;
cmp cl, 30h ; dl = 30h
jl EditProc_2 ;
cmp cl, 39h ; dh = 39h
jg EditProc_2 ;
mov [edi+edx], cl ;
inc edx ;
cmp edx, ebx ; ebx=5
jl EditProc_2 ;
EditProc_3: ;
mov [edi+edx], ch ; ch=0
call GlobalUnlock ;
inc ebx ;
push offset Buffer1 ; [esp+16] lParam
push ebx ; [esp+12] wParam
call CloseClipboard ;
;
mov eax, hEdit ;
push WM_SETTEXT ; [esp+8] message
mov ecx, lpfnEdProc ;
push eax ;
push ecx ;
call CallWindowProc ;
;
push 0 ; [esp+16] lParam
push VK_RETURN ; [esp+12] wParam
mov eax, hEdit ;
push WM_CHAR ; [esp+8] message
mov ecx, lpfnEdProc ;
push eax ;
push ecx ;
call CallWindowProc ;
;
mov eax, 10 ; [esp+16] lParam
mov edx, EM_SETSEL ; [esp+8] message
mov [esp+16],eax ; [esp+16] lParam
mov [esp+12], eax ; [esp+12] wParam
mov [esp+8], edx ; [esp+8] message
jmp EditProc_Call ;
EditProc_4: ;
cmp eax, WM_CHAR ;
jnz EditProc_Call ;
;.. WM_CHAR ....????............;
mov eax, [esp+12] ; wParam
cmp eax, 30h ;
jl EditProc_Call ;
cmp eax, 39h ;
jg EditProc_Call ;
push 0 ; [esp+16] lParam
mov eax, hEdit ;
push 0 ; [esp+12] wParam
push WM_GETTEXTLENGTH; [esp+8] message
mov ecx, lpfnEdProc ;
push eax ;
push ecx ;
call CallWindowProc ;
cmp eax, 4 ; 5-1 No more than 5 numbers
jle EditProc_Call ;
EditProc_Ret_0: ;
xor eax, eax ;
jz EditProc_Ret ;
EditProc_Call: ;
mov eax, [esp+16] ;
mov ecx, [esp+12] ;
mov edx, [esp+8] ;
push eax ;
push ecx ;
mov eax, hEdit ;
push edx ;
mov ecx, lpfnEdProc ;
push eax ;
push ecx ;
call CallWindowProc ;
mov eax, 1 ;
EditProc_Ret: ;
ret 16 ; ret 16
EditProc ENDP ;
Posted on 2001-08-16 10:07:13 by buliaNaza
You can also do this without the buffer (or the tlen because I used esi & edi instead).


If translate in Russian term Clipboard and then litteraly translate in English it would be "exchange buffer" :)
So I meant Clipboard by "buffer" :)
I think bulyNaza understood what I meant since she knows Russian.

A few more things about the task:
Before implementing anything about WM_PASTE we need to know what exactly we want form the control to do with data in Clipboard(buffer).
There may be different scenarios.
After we check it for valid simbols and found invalid ones we can
do one of possible things
1. If there are invalid simbols - cancel the operation
2. If there are invalid simbols - filter them out.

In any case to do the pasting I would use EM_REPLACESEL
to perform final pasting.
In first approach
I search for invalid simbols in Clipboard and if there is none
I send EM_REPLACESEL with address of Clipboard data.
Else - exit doing nothing.
In the second approach I would formate a string filtering out invalid simbols from buffer (or doing it exactly in very Clipboard memory) and then send EM_REPLACESEL if first byte of formated string is not 0 (it would happens if there where no valid characters at all)
Posted on 2001-08-27 06:43:25 by The Svin
Yes I meant a second approach. To filter out unwanted symbols,and paste those which left. But the problem was like this:
let we have this text in clipboard :
"00 11 22 33 44 55 66 FF " two hex digit sequences delimited by spaces. And we should Get : 00112233445566FF after paste.
But thelength of an EDIT is limited to 16 symbols.
So ... hereis the result :(
Posted on 2001-08-27 08:52:09 by Yuk