Delphi の TToolBar 上でPopupMenuの表示位置下にあるコントロールを取得

 Delphi の TToolBar 上でPopupMenuの表示位置下にあるコントロールを取得
今回は TToolBar 上に TToolButton.Style を tbsButton と tbsSeparator で配置したもの

TToolBar には、指定位置のコントロールを取得する ScreenToClient があるのだが、tbsSeparator のコントロール上で取得しても nil しか返ってこない
procedure TForm1.PopupMenuItem1Click(Sender: TObject);
var
    Point: TPoint;
    Ctrl: TControl;
begin
    if (Sender is TMenuItem) then begin
        Point := ToolBar1.ScreenToClient(TPopupMenu(TMenuItem(Sender).GetParentMenu).PopupPoint);
        
        Ctrl := ToolBar1.ControlAtPos(Point, True);
        // ToolButton.Style が tbsSeparator のコントロールは Ctrl = nil が返る
    end;
end;
そのため Toolbar 上のコントロールを探して一致するものを取得(例は横軸しか判定してません)
procedure TForm1.PopupMenuItem1Click(Sender: TObject);
var
    Point: TPoint;
    Ctrl: TControl;
    I: Integer;
begin
    if (Sender is TMenuItem) then begin
        Point := ToolBar1.ScreenToClient(TPopupMenu(TMenuItem(Sender).GetParentMenu).PopupPoint);

        for I := ToolBar1.ControlCount - 1 downto 0 do begin
        	Ctrl := ToolBar1.Controls[I];
            if (Point.X > Ctrl.Left) and (Point.X < Ctrl.Left + Ctrl.Width) then begin
            	// 該当
                Break;
            end;
        end;

    end;
end;
画面右端で PopupMenu を表示させた場合、右クリック位置とは違う場所にメニューが表示されるが、PopupPoint は最初に右クリックした位置が入っているようす

Controls に入っている順番は、Left等からの昇順ではなく ToolBar へ登録された順番となるため、ToolButton 等を動的に作成する時に Tag へ index 等を保存しておくとよいかも

コメント