Having a tree view in right-to-left reading mode (RTL), how to get node that was clicked knowing just the click coordinates ? Here is an interposed class, that makes the tree view to use the RTL display and that contains a click handler in which you can see the problem:
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.
The problem with this code (or better to say with such tree view in RTL mode) is, that when you click the node (or wherever), the GetNodeAt method never returns a valid node (always nil). For those, who don't have Delphi, the GetNodeAt method internally calls the TreeView_HitTest macro which when the tree view is in RTL mode, returns NULL like there won't be any item. I am passing to that macro the coordinates obtained through the GetCursorPos function calculated relatively to the control by the ScreenToClient function.
My question is, how to get the clicked node knowing just the mouse coordinates ? How to make a hit test with the tree view in RTL mode ? Should I for instance calculate the mouse horizontal position from right, and if so, how ?
From ScreenToClient documentation:
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
MapWindowPoints. For more information, see "Window Layout and Mirroring" in Window Features.
The corrected code could be like:
  ..
  Point := Mouse.CursorPos;
  MapWindowPoints(0, Handle, Point, 1);
  Node := GetNodeAt(Point.X, Point.Y);
  ..
Also see: Window Layout and Mirroring
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With