描述:
具有从右到左阅读模式(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.
此代码的问题(或者更好地说,在RTL模式下使用此类树视图)是,当您单击节点(或任何位置)时,GetNodeAt
方法永远不会返回有效节点(始终为nil).对于那些没有Delphi的人,GetNodeAt
方法在内部调用TreeView_HitTest
宏,当树视图处于RTL模式时,返回NULL,就像没有任何项目一样.我将通过GetCursorPos
函数获得的坐标相对于ScreenToClient
函数的控制计算得到.
题:
我的问题是,如何让点击的节点只知道鼠标坐标?如何在RTL模式下使用树视图进行命中测试?我应该从右边计算鼠标水平位置,如果是这样,怎么样?
解决方法
从
ScreenToClient
文档:
Do not use ScreenToClient when in a mirroring situation,that is,when
changing from left-to-right layout to right-to-left layout. Instead,
use 07001. For more information,see “Window Layout and
Mirroring” in Window Features.
更正后的代码可能如下:
.. Point := Mouse.CursorPos; MapWindowPoints(0,Handle,Point,1); Node := GetNodeAt(Point.X,Point.Y); ..