C# - 使用键盘时 TreeView 上下文菜单不合适

C# - TreeView Context Menu Out of Place when using keyboard

在简单的 C# WinForms 应用程序中,如果将上下文菜单分配给 Treeview 控件并且用户用鼠标右键单击节点,则上下文菜单会显示在光标所在节点的下方,但是如果使用键盘上下文菜单键或 shift+F10,则菜单会偏移并按长度显示在树视图的中间。为什么这是默认行为,上下文菜单如何显示在所选节点下?

查看reference source implementation, this seems to be a default implementation for any control (not just TreeView) context menu handling when activated by keyboard, which works fine for TextBox like controls. Interestingly, the documentation for WM_CONTEXTMENU message备注部分包含以下语句

If the context menu is generated from the keyboard—for example, if the user types SHIFT+F10—then the x- and y-coordinates are -1 and the application should display the context menu at the location of the current selection rather than at (xPos, yPos).

显然没有遵循 WinForms TreeView 控件实现。

要获得所需的行为,您需要创建一个 TreeView 子类并自己处理 WM_CONTEXTMENU 消息,如下所示

class MyTreeView : TreeView
{
    const int WM_CONTEXTMENU = 0x007B;
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_CONTEXTMENU && (long)m.LParam == -1 && this.ContextMenu != null)
        {
            var selectedNode = this.SelectedNode;
            if (selectedNode == null) return;
            var rect = selectedNode.Bounds;
            var pt = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
            if (!this.ClientRectangle.Contains(pt)) return;
            this.ContextMenu.Show(this, pt);
            return;
        }
        base.WndProc(ref m);
    }
}