Координаты мыши для положения каретки в компоненте Firemonkey TMemo
Обработка событий мыши / перетаскивания в Firemonkeys Компонент TMemo предлагает координаты курсора мыши. Есть ли способ рассчитать CaretPosition из координат мыши?
Я хочу перетащить текст в TMemo, и этот текст должен быть вставлен в текущих координатах MouseCoordinates.
2 ответа
Решение
Попробуйте позвонить GetPointPosition
,
К сожалению, это, кажется, было удалено из TMemo в XE3. В качестве быстрого и грязного обходного пути, вы можете попробовать это:
function GetPointPosition(Memo: TMemo; Pt: TPointF; RoundToWord: Boolean = False): TCaretPosition;
var
I, LPos: Integer;
Rgn: TRegion;
begin
Result.Line := -1;
Result.Pos := -1;
for I := 0 to Memo.Lines.Count - 1 do
begin
if Memo.Lines.Objects[I] is TTextLayout then
begin
LPos := TTextLayout(Memo.Lines.Objects[I]).PositionAtPoint(Pt, RoundToWord);
if LPos >= 0 then
begin
if LPos > 0 then
begin
Rgn := TTextLayout(Memo.Lines.Objects[I]).RegionForRange(TTextRange.Create(LPos, 1), RoundToWord);
if (Length(Rgn) > 0) and (Rgn[0].Top > Pt.Y) then
Dec(LPos);
end;
Result.Line := I;
Result.Pos := LPos;
Break;
end;
end;
end;
end;
Решение применимо в XE10 с использованием RTTI:
procedure TMyForm.MemoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
var Obj: IControl;
af: TPointf;
cp: TCaretPosition;
aName: string;
LVar: TStyledMemo;
LClass: TRttiInstanceType;
aLines: TObject;
aMethod: TRttiMethod;
aValue: TValue;
pointValue, boolValue: TValue;
begin
af := TPointF.Create(Panel1.Position.X + X, panel4.Height + Y);
Obj := ObjectAtPoint(ClientToScreen(af));
if Assigned(Obj) then
begin
LVar := TStyledMemo(Obj);
LClass := LContext.GetType(TStyledMemo) as TRttiInstanceType;
aLines := LClass.GetField('FLineObjects').GetValue(LVar).AsObject;
af := TPointF.Create(X,Y);
pointValue := TValue.From<TPointF>(af);
boolValue := TValue.From<Boolean>(false);
LClass := LContext.GetType(aLines.ClassType) as TRttiInstanceType;
aMethod := LClass.GetMethod('GetPointPosition');
aValue := aMethod.Invoke(aLines, [pointValue, boolValue]);
cp := aValue.AsType<TCaretPosition>;
end;
end;