Use a RichEdit control instead of an Edit control. Use the EM_SETCHARFORMAT
message to mark individual characters, or ranges of characters, as "protected". Use the EM_SETEVENTMASK
message to register for EN_PROTECTED
notifications from the RichEdit. That way, if a user tries to modify one or more protected characters for any reason, the RichEdit will ask for your permission before allowing the modification.
WinApi - set part of a text as non editable in edit control (semi readonly Editbox)
-
07-12-2021 - |
Question
I have a little problem. I want to have an Edit control in which is a text (something like this: "ABC@") . This string must be non editable so that the user shouldn't be able to delete it. The user should be able to type a text after the sign '@' only. I know how to make text readonly in editbox. I use EM_SETREADONLY message
//global variables
#define ID_TEXTBOX 1
static HWND hwndTextBox;
//in WndProc function
case WM_CREATE:
{
hwndTextBox = CreateWindow(TEXT("EDIT"),TEXT("abc@"),WS_VISIBLE | WS_CHILD | WS_BORDER ,70,100, 200,25,hWnd,(HMENU)ID_TEXTBOX,NULL,NULL);
if(!hwndTextBox )
{
MessageBox(hWnd,"Failed","Failed",MB_OK);
return FALSE;
}
SendMessage(hwndTextBox,EM_SETREADONLY,TRUE ,NULL);
break;
}
but the code makes whole text readonly and of course does not solve my problem.
Solution
OTHER TIPS
This is probably not what you're looking for, but it may mimic the required functionality with just a bit of code overhead.
You can subclass the edit control and then through WM_CHAR message capture any of the user input that may modify the edit box contents. Once the message is received by your procedure, you detect the current selection (that is the caret position) in the edit box and if it's anywhere inside the first four characters you simply don't allow the change. This is a bit crude method, but it should work.
Example in assembly, sorry I'm not proficient enough in C and C is such a drag :D
invoke SetWindowLong,hEditBox,GWL_WNDPROC,offset EditProc
mov DefEditProc,eax
...
EditProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
cmp uMsg,WM_CHAR
je @WM_CHAR
cmp uMsg,WM_KEYUP
je @WM_KEYUP
@DEFAULT:
invoke CallWindowProc,DefEditProc,hWnd,uMsg,wParam,lParam
ret
@EXIT:
xor eax,eax
ret
;=============
@WM_KEYUP:
mov eax,wParam ; you will need this if you want to process the delete key
cmp ax,VK_DELETE
je @VK_DELETE
jmp @DEFAULT
;=============
@WM_CHAR:
mov eax,wParam
cmp ax,VK_BACK ; this is for the backspace key
je @BACKSPACE
cmp ax,VK_0
jb @EXIT ; if null is returned, the char will not be passed to the edit box
cmp ax,VK_9
ja @EXIT
jmp @NUMBER
;---
@VK_DELETE:
@NUMBER:
invoke SendMessage,hWnd,EM_GETSEL,offset start,0 ; the caret position through text selection, we just need the starting position
cmp start,3
ja @DEFAULT ; if the caret is placed somewhere past the 4th charater, allow user input
jmp @EXIT
;---
@BACKSPACE:
invoke SendMessage,hWnd,EM_GETSEL,offset start,0
cmp start,4
ja @DEFAULT ; since you're deleting one character to the left, you need to factor that in for backspace
jmp @EXIT
EditProc endp
It's very cut, you hopefully get the gist of it. This example only allows the digits (0-9), the DEL and BACKSPACE keys through. You can expand to meet your needs.
Regards