if a > 0 then begin Canvas.Font.Assign(ControlFont); if PasswordKind <> pkNone then begin if a <= Length(Text) then Result := Result + (a - FFirstVisibleChar + 1) * GetPasswordCharWidth else Result := Result + (Length(Text) - FFirstVisibleChar + 1) * GetPasswordCharWidth; end else begin if a <= Length(Text) then Result := Result + Canvas.TextWidth(Copy(Text, FFirstVisibleChar, a - FFirstVisibleChar + 1)) //Result := Result + TextWidth(Canvas, Copy(Text, FFirstVisibleChar, a - FFirstVisibleChar + 1), DT_NOPREFIX) else Result := Result + Canvas.TextWidth(Copy(Text, FFirstVisibleChar, Length(Text) - FFirstVisibleChar + 1)); //Result := Result + TextWidth(Canvas, Copy(Text, FFirstVisibleChar, Length(Text) - FFirstVisibleChar + 1), DT_NOPREFIX); end; end;
EditRectWidth := GetEditRect.Right - GetEditRect.Left; if WholeTextWidth < EditRectWidth then case TextAlignment of taRightJustify: Result := Result + (EditRectWidth - WholeTextWidth); taCenter: Result := Result + ((EditRectWidth - WholeTextWidth) div 2); end; end;
function TSeCustomEdit.GetCoordinatePosition(x: integer): integer; var CurX : double; TmpX, WholeTextWidth, EditRectWidth : integer; begin Result := FFirstVisibleChar - 1; if Length(Text) = 0 then Exit;
EditRectWidth := GetEditRect.Right - GetEditRect.Left; TmpX := x; if WholeTextWidth < EditRectWidth then case TextAlignment of taRightJustify: TmpX := x - (EditRectWidth - WholeTextWidth); taCenter: TmpX := x - ((EditRectWidth - WholeTextWidth) div 2); end;
if PasswordKind <> pkNone then begin Result := Result + (TmpX - GetEditRect.Left) div GetPasswordCharWidth; if Result < 0 then Result := 0 else if Result > Length(Text) then Result := Length(Text); end else begin Canvas.Font.Assign(ControlFont); {CurX := GetEditRect.Left + TextWidth(Canvas, Text[FFirstVisibleChar], DT_NOPREFIX) / 2; } CurX := GetEditRect.Left + Canvas.TextWidth(Text[FFirstVisibleChar]) / 2; while (CurX < TmpX) and (Result + 1 <= Length(Text)) and (CurX < GetEditRect.Right) do begin //CurX := CurX + TextWidth(Canvas, Text[Result + 1], DT_NOPREFIX) / 2; CurX := CurX + Canvas.TextWidth(Text[Result + 1]) / 2; if Result + 1 + 1 <= Length(Text) then //CurX := CurX + TextWidth(Canvas, Text[Result + 1 + 1], DT_NOPREFIX) / 2; CurX := CurX + Canvas.TextWidth(Text[Result + 1 + 1]) / 2; Result := Result + 1; end; end; end;
function TSeCustomEdit.GetEditRect: TRect; begin with Result do begin Result := GetBorderRect;
function TSeCustomEdit.GetAlignmentFlags: integer; begin case FTextAlignment of taCenter: Result := DT_CENTER; taRightJustify: Result := DT_RIGHT; else Result := DT_LEFT; end; end;
procedure TSeCustomEdit.KeyDown(var Key: word; Shift: TShiftState); var TmpS : WideString; OldCaretPosition : integer; begin inherited KeyDown(Key, Shift); OldCaretPosition := CaretPosition; case Key of VK_END: CaretPosition := Length(Text); VK_HOME: CaretPosition := 0; VK_LEFT: if ssCtrl in Shift then CaretPosition := GetPrivWordBeging(CaretPosition) else CaretPosition := CaretPosition - 1; VK_RIGHT: if ssCtrl in Shift then CaretPosition := GetNextWordBeging(CaretPosition) else CaretPosition := CaretPosition + 1; VK_DELETE, 8: {Delete or BackSpace key was pressed} if not ReadOnly then begin if SelLength <> 0 then begin if Shift = [ssShift] then CutToClipboard else ClearSelection; end else begin TmpS := Text; if TmpS <> '' then if Key = VK_DELETE then begin FActionStack.FragmentDeleted(CaretPosition + 1, TmpS[CaretPosition + 1]); Delete(TmpS, CaretPosition + 1, 1); end else begin {BackSpace key was pressed} if CaretPosition > 0 then FActionStack.FragmentDeleted(CaretPosition, TmpS[CaretPosition]); Delete(TmpS, CaretPosition, 1); CaretPosition := CaretPosition - 1; end; Text := TmpS; end; end; VK_INSERT: if Shift = [ssCtrl] then CopyToClipboard else if Shift = [ssShift] then PasteFromClipboard; Ord('c'), Ord('C'): if Shift = [ssCtrl] then CopyToClipboard; Ord('v'), Ord('V'): if Shift = [ssCtrl] then PasteFromClipboard; Ord('x'), Ord('X'): if Shift = [ssCtrl] then CutToClipboard; Ord('z'), Ord('Z'): if Shift = [ssCtrl] then UnDo; end;
if Key in [VK_END, VK_HOME, VK_LEFT, VK_RIGHT] then begin if ssShift in Shift then begin if SelLength = 0 then FSelStart := OldCaretPosition; FSelStart := CaretPosition; FSelLength := FSelLength - (CaretPosition - OldCaretPosition); end else FSelLength := 0; Invalidate; end; UpdateCaretePosition; end;
procedure TSeCustomEdit.KeyPress(var Key: Char); begin inherited KeyPress(Key);
if (Ord(Key) >= 32) and not ReadOnly then InsertChar(charToWideChar(Key)); end;
procedure TSeCustomEdit.MouseDown(Button: TMouseButton; Shift: TShiftState; x, y: integer); begin inherited; if Button = mbLeft then FLMouseSelecting := true;
SetFocus;
if Button = mbLeft then begin CaretPosition := GetCoordinatePosition(x); SelLength := 0; end; end;
procedure TSeCustomEdit.PaintBuffer; var R : TRect; begin R := GetEditRect; R.Bottom := FHeight - R.Top;
PaintBackground(R, Canvas);
if (Self is TSeCustomComboBox) and (TSeCustomComboBox(Self).ComboStyle = kcsDropDownList) then Exit;
if Focused or not HideSelection then FillRect(Canvas, GetSelRect, clHighlight);
PaintText;
if Focused or not HideSelection then PaintSelectedText; end;
procedure TSeCustomEdit.PaintBackground(Rect: TRect; Canvas: TCanvas); begin FillRect(Canvas, Rect, Color); end;
procedure TSeCustomEdit.PaintText; var TmpRect : TRect; CurChar : integer; LPWCharWidth : integer; begin TmpRect := GetEditRect;
if PasswordKind <> pkNone then begin LPWCharWidth := GetPasswordCharWidth; for CurChar := 0 to Length(Text) - FFirstVisibleChar + 1 - 1 do DrawPasswordChar(Rect(CurChar * LPWCharWidth + GetCharX(0), TmpRect.Top, (CurChar + 1) * LPWCharWidth + GetCharX(0), TmpRect.Bottom), false); end else begin Canvas.Font.Assign(ControlFont); DrawText(Canvas, Copy(Text, FFirstVisibleChar, Length(Text) - FFirstVisibleChar + 1), TmpRect, GetAlignmentFlags or DT_NOPREFIX); end; end;
procedure TSeCustomEdit.UpdateFirstVisibleChar; var LEditRect : TRect; begin if FFirstVisibleChar >= (FCaretPosition + 1) then begin FFirstVisibleChar := FCaretPosition; if FFirstVisibleChar < 1 then FFirstVisibleChar := 1; end else begin LEditRect := GetEditRect;
if PasswordKind <> pkNone then while ((FCaretPosition - FFirstVisibleChar + 1) * GetPasswordCharWidth > LEditRect.Right - LEditRect.Left) and (FFirstVisibleChar < Length(Text)) do Inc(FFirstVisibleChar) else begin Canvas.Font.Assign(ControlFont); {while (TextWidth(Canvas, Copy(Text, FFirstVisibleChar, FCaretPosition - FFirstVisibleChar + 1), DT_NOPREFIX) > LEditRect.Right - LEditRect.Left) and (FFirstVisibleChar < Length(Text)) do Inc(FFirstVisibleChar); } while (Canvas.TextWidth(Copy(Text, FFirstVisibleChar, FCaretPosition - FFirstVisibleChar + 1)) > LEditRect.Right - LEditRect.Left) and (FFirstVisibleChar < Length(Text)) do Inc(FFirstVisibleChar); end; end; Invalidate; end;
procedure TSeCustomEdit.MouseMove(Shift: TShiftState; x, y: integer); var OldCaretPosition : integer; TmpNewPosition : integer; begin inherited; if FLMouseSelecting then begin TmpNewPosition := GetCoordinatePosition(x); OldCaretPosition := CaretPosition; if (x > GetEditRect.Right) then CaretPosition := TmpNewPosition + 1 else CaretPosition := TmpNewPosition; if SelLength = 0 then FSelStart := OldCaretPosition; FSelStart := CaretPosition; FSelLength := FSelLength - (CaretPosition - OldCaretPosition); end; end;
procedure TSeCustomEdit.CopyToClipboard; var Data : THandle; DataPtr : Pointer; Size : Cardinal; S : WideString; begin if PasswordKind = pkNone then if Length(SelText) > 0 then begin S := SelText; if not IsWinNT then begin Clipboard.AsText := S; end else begin Size := Length(S); Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, 2 * Size + 2); try DataPtr := GlobalLock(Data); try Move(PWideChar(S)^, DataPtr^, 2 * Size + 2); Clipboard.SetAsHandle(CF_UNICODETEXT, Data); finally GlobalUnlock(Data); end; except GlobalFree(Data); raise; end; end; end; end;
procedure TSeCustomEdit.PasteFromClipboard; var Data : THandle; Insertion : WideString; begin if ReadOnly then Exit;
if Clipboard.HasFormat(CF_UNICODETEXT) then begin Data := Clipboard.GetAsHandle(CF_UNICODETEXT); try if Data <> 0 then Insertion := PWideChar(GlobalLock(Data)); finally if Data <> 0 then GlobalUnlock(Data); end; end else Insertion := Clipboard.AsText;
InsertText(Insertion); end;
procedure TSeCustomEdit.PaintSelectedText; var TmpRect : TRect; CurChar : integer; LPWCharWidth : integer; begin TmpRect := GetSelRect;
if PasswordKind <> pkNone then begin LPWCharWidth := GetPasswordCharWidth; for CurChar := 0 to Length(GetVisibleSelText) - 1 do DrawPasswordChar(Rect(CurChar * LPWCharWidth + TmpRect.Left, TmpRect.Top, (CurChar + 1) * LPWCharWidth + TmpRect.Left, TmpRect.Bottom), true); end else begin Canvas.Font.Assign(ControlFont); Canvas.Font.Color := clHighlightText; DrawText(Canvas, GetVisibleSelText, TmpRect, GetAlignmentFlags or DT_NOPREFIX) end; end;
function TSeCustomEdit.GetVisibleSelText: WideString; begin if SelStart + 1 >= FFirstVisibleChar then Result := SelText else Result := Copy(SelText, FFirstVisibleChar - SelStart, Length(SelText) - (FFirstVisibleChar - SelStart) + 1); end;
procedure TSeCustomEdit.BuildPopupMenu; var TmpItem : TSeCustomItem; begin FPopupMenu := CreatePopupMenu(Self);
if FPopupMenu = nil then Exit;
TmpItem := CreatePopupMenuItem(FPopupMenu); with TmpItem do begin Caption := SEditUndo; OnClick := DoUndo; end; FPopupMenu.Items.Add(TmpItem);