Home > Net >  How to position a popup menu to the left width of a button in C#?
How to position a popup menu to the left width of a button in C#?

Time:03-18

I have a popup menu. The popup menu has a two-column layout. Therefore, the buttons are aligned in two columns, which are the left column and the right column. Inside it, there are buttons. Upon clicking one of the buttons, it will open a dropdown menu(created using ContextMenuStrip).

This is how the popup menu and its contents look like:
popupMenu

I have no problem to place the dropdown menu on the right width of the "Style token" button. The problem occurs when I'm trying to place the dropdown menu on the left width of the "Remove style" button. Below shows the examples:

The dropdown location on the right width of the "Style token" button works just fine. rightColumn

The dropdown location on the left width of the "Remove style" button is problematic as I don't really know how to code the logic of it. It should look as shown below:
leftColumn


Actually, I've coded the part I'm having an issue with. However, I'm not really sure if this is the conventional or professional way of coding it. Also, there are times there will be a random gap between the left dropdown menu with the "Remove Style" button. Below shows the code example:

//--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);
}

So, may I know how are the better ways of coding the positioning of the dropdown menu in the left width of the "Remove style" button, please?

CodePudding user response:

Thanks for the time and answer, @Jimi. I really appreciate all your helps.

He shared me an answer and it worked very well. It turns out I just need to tweak the logic under the MouseUp event handler of the button13, the button that opens the Remove style's ContextMenuStrip.


Codes:

//--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));
    }
}

CodePudding user response:

To position a ContextMenuStrip in relation to a Control when you cannot rely on the default behavior, you need to specify Screen coordinates.

The 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 parameter.

// 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);
}

But you can also specify the Screen coordinates where the ContextMenuStrip should appear, calculating the location yourself. For example, to the Left or Right of a Control:
(it would be better to use an Enumerator, as before, rather than a boolean)

// 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;
    }

    cmsSelectDataSource.Show(location);
}

Note that in this case, there's no automatic compensation for nested drop-down controls.

  • Related