TLa*_*ama 7 delphi winapi delphi-2009
拥有从右到左阅读模式(RTL)的树视图,如何获取被点击的节点只知道点击坐标?这是一个插入的类,它使树视图使用RTL显示,并包含一个单击处理程序,您可以在其中查看问题:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, CommCtrl;
type
TTreeView = class(ComCtrls.TTreeView)
protected
procedure CNNotify(var Msg: TWMNotify); message CN_NOTIFY;
procedure CreateParams(var Params: TCreateParams); override;
end;
type
TForm1 = class(TForm)
TreeView1: TTreeView;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TTreeView }
procedure TTreeView.CNNotify(var Msg: TWMNotify);
var
Node: TTreeNode;
Point: TPoint;
begin
inherited;
if Msg.NMHdr.code = NM_CLICK then
begin
Point := ScreenToClient(Mouse.CursorPos);
Node := GetNodeAt(Point.X, Point.Y);
if Assigned(Node) then
ShowMessage('This message never shows...');
end;
end;
procedure TTreeView.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style or TVS_RTLREADING;
Params.ExStyle := Params.ExStyle or WS_EX_LAYOUTRTL or WS_EX_RIGHT;
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
Node: TTreeNode;
begin
Node := TreeView1.Items.AddChild(nil, 'Item 1');
TreeView1.Items.AddChild(Node, 'SubItem 1');
end;
end.
Run Code Online (Sandbox Code Playgroud)
此代码的问题(或者更好地说,在RTL模式下使用此类树视图)是,当您单击节点(或任何位置)时,该GetNodeAt方法永远不会返回有效节点(始终nil).对于那些没有Delphi的人,该GetNodeAt方法在内部调用TreeView_HitTest宏,当树视图处于RTL模式时,返回NULL就像没有任何项目一样.我将通过GetCursorPos函数获得的坐标相对于函数的控制传递给该宏ScreenToClient.
我的问题是,如何让点击的节点只知道鼠标坐标?如何在RTL模式下使用树视图进行命中测试?我应该从右边计算鼠标水平位置,如果是,如何计算?
Ser*_*yuz 12
来自ScreenToClient文档:
在镜像情况下,即从左到右布局更改为从右到左布局时,请勿使用ScreenToClient.相反,使用
MapWindowPoints.有关更多信息,请参见窗口功能中的"窗口布局和镜像".
更正后的代码可以是:
..
Point := Mouse.CursorPos;
MapWindowPoints(0, Handle, Point, 1);
Node := GetNodeAt(Point.X, Point.Y);
..
Run Code Online (Sandbox Code Playgroud)
另请参阅:窗口布局和镜像