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