如何将弹出菜单定位到按钮的左侧?

How to position a Popup Menu to the left side of a Button?

我有一个弹出菜单。弹出菜单有两列布局。因此,Buttons是两列对齐的,分别是左列和右列。在里面,有按钮。
单击其中一个按钮后,它将打开一个下拉菜单(使用 ContextMenuStrip 创建)。

弹出菜单及其内容如下所示:

我可以毫无问题地将下拉菜单放在“样式标记”按钮的右侧宽度上。当我尝试将下拉菜单放置在“删除样式”按钮的左侧宽度时出现问题。
下图显示了示例:

“样式标记”按钮右侧宽度的下拉位置工作得很好。

“删除样式”按钮左侧宽度的下拉位置有问题,因为我真的不知道如何编写它的逻辑。
它应该如下所示:


实际上,我已经对遇到问题的部分进行了编码。但是,我不太确定这是传统的编码方式还是专业的编码方式。此外,有时左侧下拉菜单与“删除样式”按钮之间会出现随机间隙。
下面显示了代码示例:

//--global variable--
int removeStyleStripXPos; //to store xPos of left column dropdown menu

//removeStyleStrip -> the left dropdown menu
//styleTokenStrip -> the right dropdown menu
//--global variable--

//--the mouseUp event handler of "Remove style" button--
private void button13_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        removeStyleStrip.Show(button13, new Point(removeStyleStripXPos, 0));
    }
}

//--the mouseUp event handler of "Style token" button--
private void button14_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        styleTokenStrip.Show(button14, new Point(this.button14.DisplayRectangle.Right, 0));
    }
}

//--the load event handler of the two column popup menu--
private void TCPopupMenuFull_Load(object sender, EventArgs e)
{
    removeStyleStripXPos = -(this.removeStyleStrip.Width);
}

那么,请问有没有更好的方法可以将下拉菜单的位置设置到“删除样式”按钮的左端?

感谢@Jimi 的时间和回答。非常感谢您的帮助。

他与我分享了一个答案并且效果很好。事实证明,我只需要调整 button13MouseUp 事件处理程序下的逻辑,即打开 Remove styleContextMenuStrip.

的按钮

代码:

//--the mouseUp event handler of "Remove style" button--
private void button13_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        var screenPos = button13.PointToScreen(Point.Empty);
        removeStyleStrip.Show(new Point(screenPos.X - removeStyleStrip.Width, screenPos.Y));
    }
}

当您不能依赖默认行为时,若要相对于控件定位 ContextMenuStrip,您需要指定屏幕坐标。

Show() method of a ContextMenuStrip (or ToolStripDropDown) has overloads that allow to specify a location based on either absolute Screen coordinates or coordinates relative to a specific Control, translated internally to Screen coordinates in relation to behaviors defined by the ToolStripDropDownDirection参数。

// Position the CMS to the absolute right of the Control
SetCMSPosition(someControl, ToolStripDropDownDirection.Right, true);

// Position the CMS to the left of the Control
SetCMSPosition(someControl, ToolStripDropDownDirection.Left, false);

// [...]

private void SetCMSPosition(Control control, ToolStripDropDownDirection direction, bool absolute)
{
    Point location = Point.Empty;
    if (absolute) {
        switch (direction) {
            case ToolStripDropDownDirection.Right:
            case ToolStripDropDownDirection.AboveRight:
                location = new Point(control.ClientSize.Width, 0);
                break;
            case ToolStripDropDownDirection.BelowRight:
                location = new Point(control.ClientSize.Width, control.Height);
                break;
        }
    }
    [The ContextMenuStrip].Show(control, location, direction);
}

但您也可以指定 ContextMenuStrip 应出现的屏幕坐标,自行计算位置。例如,在控件的左侧或右侧:
(最好像以前一样使用枚举器,而不是布尔值)

// Positions the CMS to the right of a Control
SetCMSPosition2(someControl, true);

// Positions the CMS to the left of a Control
SetCMSPosition2(someControl, false);


private void SetCMSPosition2(Control control, bool toTheRight)
{
    Point location = control.PointToScreen(Point.Empty);
    if (toTheRight) {
        location.X += control.ClientSize.Width + 1;
    }
    else {
        location.X -= [The ContextMenuStrip].Width + 1;
    }

    [The ContextMenuStrip].Show(location);
}

请注意,在这种情况下,嵌套 drop-down 控件没有自动补偿。