📄 mask.pas
字号:
inherited MaxLength := 0;
if IsMasked and (FMaxChars > 0) then
inherited MaxLength := FMaxChars;
if HandleAllocated and (GetFocus = Handle) and
not (csDesigning in ComponentState) then
SetCursor(SelStart);
end;
end;
function TCustomMaskEdit.GetMaxLength: Integer;
begin
Result := inherited MaxLength;
end;
procedure TCustomMaskEdit.SetMaxLength(Value: Integer);
begin
if not IsMasked then
inherited MaxLength := Value
else
inherited MaxLength := FMaxChars;
end;
procedure TCustomMaskEdit.GetSel(var SelStart: Integer; var SelStop: Integer);
begin
SendMessage(Handle, EM_GETSEL, Integer(@SelStart), Integer(@SelStop));
end;
procedure TCustomMaskEdit.SetSel(SelStart: Integer; SelStop: Integer);
begin
SendMessage(Handle, EM_SETSEL, SelStart, SelStop);
end;
procedure TCustomMaskEdit.SetCursor(Pos: Integer);
const
ArrowKey: array[Boolean] of Word = (VK_LEFT, VK_RIGHT);
var
SelStart, SelStop: Integer;
KeyState: TKeyboardState;
NewKeyState: TKeyboardState;
I: Integer;
begin
if (Pos >= 1) and (ByteType(EditText, Pos) = mbLeadByte) then Dec(Pos);
SelStart := Pos;
if (IsMasked) then
begin
if SelStart < 0 then
SelStart := 0;
SelStop := SelStart + 1;
if (Length(EditText) > SelStop) and (EditText[SelStop] in LeadBytes) then
Inc(SelStop);
if SelStart >= FMaxChars then
begin
SelStart := FMaxChars;
SelStop := SelStart;
end;
SetSel(SelStop, SelStop);
if SelStart <> SelStop then
begin
GetKeyboardState(KeyState);
for I := Low(NewKeyState) to High(NewKeyState) do
NewKeyState[I] := 0;
NewKeyState [VK_SHIFT] := $81;
NewKeyState [ArrowKey[UseRightToLeftAlignment]] := $81;
SetKeyboardState(NewKeyState);
FSettingCursor := True;
try
SendMessage(Handle, WM_KEYDOWN, ArrowKey[UseRightToLeftAlignment], 1);
SendMessage(Handle, WM_KEYUP, ArrowKey[UseRightToLeftAlignment], 1);
finally
FSettingCursor := False;
end;
SetKeyboardState(KeyState);
end;
FCaretPos := SelStart;
end
else
begin
if SelStart < 0 then
SelStart := 0;
if SelStart >= Length(EditText) then
SelStart := Length(EditText);
SetSel(SelStart, SelStart);
end;
end;
procedure TCustomMaskEdit.CheckCursor;
var
SelStart, SelStop: Integer;
begin
if not HandleAllocated then Exit;
if (IsMasked) then
begin
GetSel(SelStart, SelStop);
if SelStart = SelStop then
SetCursor(SelStart);
end;
end;
procedure TCustomMaskEdit.Clear;
begin
Text := '';
end;
function TCustomMaskEdit.EditCanModify: Boolean;
begin
Result := True;
end;
procedure TCustomMaskEdit.Reset;
begin
if Modified then
begin
EditText := FOldValue;
Modified := False;
end;
end;
function TCustomMaskEdit.CharKeys(var CharCode: Char): Boolean;
var
SelStart, SelStop : Integer;
Txt: string;
CharMsg: TMsg;
begin
Result := False;
if Word(CharCode) = VK_ESCAPE then
begin
Reset;
Exit;
end;
if not EditCanModify or ReadOnly then Exit;
if (Word(CharCode) = VK_BACK) then Exit;
if (Word(CharCode) = VK_RETURN) then
begin
ValidateEdit;
Exit;
end;
GetSel(SelStart, SelStop);
if (SelStop - SelStart) > 1 then
begin
DeleteKeys(VK_DELETE);
SelStart := GetNextEditChar(SelStart);
SetCursor(SelStart);
end;
if (CharCode in LeadBytes) then
if PeekMessage(CharMsg, Handle, WM_CHAR, WM_CHAR, PM_REMOVE) then
if CharMsg.Message = WM_Quit then
PostQuitMessage(CharMsg.wparam);
Result := InputChar(CharCode, SelStart);
if Result then
begin
if (CharCode in LeadBytes) then
begin
Txt := CharCode + Char(CharMsg.wParam);
SetSel(SelStart, SelStart + 2);
end
else
Txt := CharCode;
SendMessage(Handle, EM_REPLACESEL, 0, LongInt(PChar(Txt)));
GetSel(SelStart, SelStop);
CursorInc(SelStart, 0);
end;
end;
procedure TCustomMaskEdit.ArrowKeys(CharCode: Word; Shift: TShiftState);
var
SelStart, SelStop : Integer;
begin
if (ssCtrl in Shift) then Exit;
GetSel(SelStart, SelStop);
if (ssShift in Shift) then
begin
if (CharCode = VK_RIGHT) then
begin
Inc(FCaretPos);
if (SelStop = SelStart + 1) then
begin
SetSel(SelStart, SelStop); {reset caret to end of string}
Inc(FCaretPos);
end;
if FCaretPos > FMaxChars then FCaretPos := FMaxChars;
end
else {if (CharCode = VK_LEFT) then}
begin
Dec(FCaretPos);
if (SelStop = SelStart + 2) and
(FCaretPos > SelStart) then
begin
SetSel(SelStart + 1, SelStart + 1); {reset caret to show up at start}
Dec(FCaretPos);
end;
if FCaretPos < 0 then FCaretPos := 0;
end;
end
else
begin
if (SelStop - SelStart) > 1 then
begin
if ((SelStop - SelStart) = 2) and (EditText[SelStart+1] in LeadBytes) then
begin
if (CharCode = VK_LEFT) then
CursorDec(SelStart)
else
CursorInc(SelStart, 2);
Exit;
end;
if SelStop = FCaretPos then
Dec(FCaretPos);
SetCursor(FCaretPos);
end
else if (CharCode = VK_LEFT) then
CursorDec(SelStart)
else { if (CharCode = VK_RIGHT) then }
begin
if SelStop = SelStart then
SetCursor(SelStart)
else
if EditText[SelStart+1] in LeadBytes then
CursorInc(SelStart, 2)
else
CursorInc(SelStart, 1);
end;
end;
end;
procedure TCustomMaskEdit.CursorInc(CursorPos: Integer; Incr: Integer);
var
NuPos: Integer;
begin
NuPos := CursorPos + Incr;
NuPos := GetNextEditChar(NuPos);
if IsLiteralChar(EditMask, nuPos) then
NuPos := CursorPos;
SetCursor(NuPos);
end;
procedure TCustomMaskEdit.CursorDec(CursorPos: Integer);
var
nuPos: Integer;
begin
nuPos := CursorPos;
Dec(nuPos);
nuPos := GetPriorEditChar(nuPos);
SetCursor(NuPos);
end;
function TCustomMaskEdit.GetFirstEditChar: Integer;
begin
Result := 0;
if IsMasked then
Result := GetNextEditChar(0);
end;
function TCustomMaskEdit.GetLastEditChar: Integer;
begin
Result := GetMaxChars;
if IsMasked then
Result := GetPriorEditChar(Result - 1);
end;
function TCustomMaskEdit.GetNextEditChar(Offset: Integer): Integer;
begin
Result := Offset;
while(Result < FMaxChars) and (IsLiteralChar(EditMask, Result)) do
Inc(Result);
end;
function TCustomMaskEdit.GetPriorEditChar(Offset: Integer): Integer;
begin
Result := Offset;
while(Result >= 0) and (IsLiteralChar(EditMask, Result)) do
Dec(Result);
if Result < 0 then
Result := GetNextEditChar(Result);
end;
procedure TCustomMaskEdit.HomeEndKeys(CharCode: Word; Shift: TShiftState);
var
SelStart, SelStop : Integer;
begin
GetSel(SelStart, SelStop);
if (CharCode = VK_HOME) then
begin
if (ssShift in Shift) then
begin
if (SelStart <> FCaretPos) and (SelStop <> (SelStart + 1)) then
SelStop := SelStart + 1;
SetSel(0, SelStop);
CheckCursor;
end
else
SetCursor(0);
FCaretPos := 0;
end
else
begin
if (ssShift in Shift) then
begin
if (SelStop <> FCaretPos) and (SelStop <> (SelStart + 1)) then
SelStart := SelStop - 1;
SetSel(SelStart, FMaxChars);
CheckCursor;
end
else
SetCursor(FMaxChars);
FCaretPos := FMaxChars;
end;
end;
procedure TCustomMaskEdit.DeleteKeys(CharCode: Word);
var
SelStart, SelStop : Integer;
NuSelStart: Integer;
Str: string;
begin
if ReadOnly then Exit;
GetSel(SelStart, SelStop);
if ((SelStop - SelStart) <= 1) and (CharCode = VK_BACK) then
begin
NuSelStart := SelStart;
CursorDec(SelStart);
GetSel(SelStart, SelStop);
if SelStart = NuSelStart then Exit;
end;
if (SelStop - SelStart) < 1 then Exit;
Str := EditText;
DeleteSelection(Str, SelStart, SelStop - SelStart);
Str := Copy(Str, SelStart+1, SelStop - SelStart);
SendMessage(Handle, EM_REPLACESEL, 0, LongInt(PChar(Str)));
if (SelStop - SelStart) <> 1 then
begin
SelStart := GetNextEditChar(SelStart);
SetCursor(SelStart);
end
else begin
GetSel(SelStart, SelStop);
SetCursor(SelStart - 1);
end;
end;
procedure TCustomMaskEdit.CMEnter(var Message: TCMEnter);
begin
if IsMasked and not (csDesigning in ComponentState) then
begin
if not (msReEnter in FMaskState) then
begin
FOldValue := EditText;
inherited;
end;
Exclude(FMaskState, msReEnter);
CheckCursor;
end
else
inherited;
end;
procedure TCustomMaskEdit.CMTextChanged(var Message: TMessage);
var
SelStart, SelStop : Integer;
Temp: Integer;
begin
inherited;
FOldValue := EditText;
if HandleAllocated then
begin
GetSel(SelStart, SelStop);
Temp := GetNextEditChar(SelStart);
if Temp <> SelStart then
SetCursor(Temp);
end;
end;
procedure TCustomMaskEdit.CMWantSpecialKey(var Message: TCMWantSpecialKey);
begin
inherited;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -