如何将屏幕坐标转换为具有嵌入式形式和多显示器 FMX 的控件坐标 Windows
How to convert screen coordinates to control coordinates with embedded form and multiple displays FMX Windows
我需要知道 OnItemClickEx
事件中的鼠标位置以及相对于 ListView 控件的坐标。在多显示器系统中,它适用于在主显示器上显示的应用程序,但在应用程序显示在辅助或第三显示器上时不起作用。
获取鼠标位置的代码如下:
...
var point : TPointF;
...
point := Screen.MousePos;
point := self.ScreenToClient(point): //we obtain wrong local coordinates for the secondary and third monitor with or without this line
point := ListView.AbsoluteToLocal(point);
了解鼠标光标相对于控件(在本用例中为 TListView
)的坐标的正确方法是什么?
更新
在 this 示例中,您可以看到它在第一个表单中工作正常,但在嵌入式表单中它提供了错误的坐标。在10.2和10.3中测试,结果相同
以下代码与 Delphi 10.4.1 完美配合:
procedure TForm1.ListView1ItemClickEx(
const Sender : TObject;
ItemIndex : Integer;
const LocalClickPos : TPointF;
const ItemObject : TListItemDrawable);
var
PtScreen : TPointF;
PtForm : TPointF;
PtListView : TPointF;
begin
PtScreen := Screen.MousePos;
PtForm := ScreenToClient(PtScreen);
PtListView := ListView1.AbsoluteToLocal(PtForm);
Memo1.Lines.Add('ListView1ItemClickEx ' +
PtListView.X.ToString + ', ' + PtListView.Y.ToString);
Memo1.GoToTextEnd;
end;
procedure TForm1.ListView1MouseMove(
Sender : TObject;
Shift : TShiftState;
X, Y : Single);
begin
Memo1.Lines.Add('ListViewMouseMove ' +
X.ToString + ', ' + Y.ToString);
Memo1.GoToTextEnd;
end;
此代码将在鼠标光标在 TListView 内移动时在备忘录中显示鼠标的坐标,并显示从 OnItemClickEx 事件计算的坐标。两者相同,在主显示器或辅助显示器上。
也许您使用的是旧 Delphi 版本,其中存在错误。我不知道。或者错误在您的代码中的其他地方。
如果您从 ListView OnMouseMove 事件处理程序捕获鼠标位置并将其保存在表单的变量中,以便从 OnItemClickEx 事件处理程序中随时可用,您的问题将得到解决:
private
FMouseX : Single;
FMouseY : Single;
procedure TForm1.ListView1MouseMove(
Sender : TObject;
Shift : TShiftState;
X, Y : Single);
begin
FMouseX := X;
FMouseY := Y;
end;
procedure TForm1.ListView1ItemClickEx(
const Sender : TObject;
ItemIndex : Integer;
const LocalClickPos : TPointF;
const ItemObject : TListItemDrawable);
begin
Memo1.Lines.Add('ListView1ItemClickEx ' +
FMouseX.ToString + ', ' + FMouseY.Y.ToString);
Memo1.GoToTextEnd;
end;
最后,经过一些研究和测试,我找到了窍门:
...
var point : TPointF;
...
point := Screen.MousePos;
point := Application.MainForm.ScreenToClient(point); // The calculation should be with the MainForm, not the embedded!!!
point := ListView.AbsoluteToLocal(point);
我需要知道 OnItemClickEx
事件中的鼠标位置以及相对于 ListView 控件的坐标。在多显示器系统中,它适用于在主显示器上显示的应用程序,但在应用程序显示在辅助或第三显示器上时不起作用。
获取鼠标位置的代码如下:
...
var point : TPointF;
...
point := Screen.MousePos;
point := self.ScreenToClient(point): //we obtain wrong local coordinates for the secondary and third monitor with or without this line
point := ListView.AbsoluteToLocal(point);
了解鼠标光标相对于控件(在本用例中为 TListView
)的坐标的正确方法是什么?
更新
在 this 示例中,您可以看到它在第一个表单中工作正常,但在嵌入式表单中它提供了错误的坐标。在10.2和10.3中测试,结果相同
以下代码与 Delphi 10.4.1 完美配合:
procedure TForm1.ListView1ItemClickEx(
const Sender : TObject;
ItemIndex : Integer;
const LocalClickPos : TPointF;
const ItemObject : TListItemDrawable);
var
PtScreen : TPointF;
PtForm : TPointF;
PtListView : TPointF;
begin
PtScreen := Screen.MousePos;
PtForm := ScreenToClient(PtScreen);
PtListView := ListView1.AbsoluteToLocal(PtForm);
Memo1.Lines.Add('ListView1ItemClickEx ' +
PtListView.X.ToString + ', ' + PtListView.Y.ToString);
Memo1.GoToTextEnd;
end;
procedure TForm1.ListView1MouseMove(
Sender : TObject;
Shift : TShiftState;
X, Y : Single);
begin
Memo1.Lines.Add('ListViewMouseMove ' +
X.ToString + ', ' + Y.ToString);
Memo1.GoToTextEnd;
end;
此代码将在鼠标光标在 TListView 内移动时在备忘录中显示鼠标的坐标,并显示从 OnItemClickEx 事件计算的坐标。两者相同,在主显示器或辅助显示器上。
也许您使用的是旧 Delphi 版本,其中存在错误。我不知道。或者错误在您的代码中的其他地方。
如果您从 ListView OnMouseMove 事件处理程序捕获鼠标位置并将其保存在表单的变量中,以便从 OnItemClickEx 事件处理程序中随时可用,您的问题将得到解决:
private
FMouseX : Single;
FMouseY : Single;
procedure TForm1.ListView1MouseMove(
Sender : TObject;
Shift : TShiftState;
X, Y : Single);
begin
FMouseX := X;
FMouseY := Y;
end;
procedure TForm1.ListView1ItemClickEx(
const Sender : TObject;
ItemIndex : Integer;
const LocalClickPos : TPointF;
const ItemObject : TListItemDrawable);
begin
Memo1.Lines.Add('ListView1ItemClickEx ' +
FMouseX.ToString + ', ' + FMouseY.Y.ToString);
Memo1.GoToTextEnd;
end;
最后,经过一些研究和测试,我找到了窍门:
...
var point : TPointF;
...
point := Screen.MousePos;
point := Application.MainForm.ScreenToClient(point); // The calculation should be with the MainForm, not the embedded!!!
point := ListView.AbsoluteToLocal(point);