【问题标题】:How to toggle a ContextMenuStrip display using a button click but also allowing it to close normally (menu item clicks, lost focus etc)如何使用按钮单击切换 ContextMenuStrip 显示,但也允许它正常关闭(菜单项单击、失去焦点等)
【发布时间】:2013-06-26 17:01:05
【问题描述】:

我创建了一个简单的用户控件,由标签和上下文菜单条组成。我使它的功能类似于 ComboBox,但我显示的是 ContextMenuStrip,而不是下拉菜单。

我有它的工作,但有一些我无法弄清楚的棘手问题。

我正在尝试使标签 ComboButton 的工作方式与 ComboBox 相同。单击按钮,出现下拉菜单。再次单击该按钮,它将收回。问题是,ContextMenu 在任何鼠标单击时都会消失。所以当我第二次点击按钮收回菜单时,菜单先消失,然后点击事件触发,再次显示菜单。

我仍然希望菜单在用户选择菜单项时以及当他们像普通上下文菜单一样单击表单上的任意位置时消失。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Windows.Forms.VisualStyles;
using System.Diagnostics;

namespace Controls
{
    public partial class CMenu : UserControl
    {
        ButtonState _buttonState = ButtonState.Normal;

        public CMenu()
        {
            InitializeComponent();
        }

        private void lblSelect_Paint(object sender, PaintEventArgs e)
        {
            base.OnPaint(e);
            ControlPaint.DrawComboButton(e.Graphics, getLabelRect(), _buttonState);
        }

        private bool IsDropdownHit(MouseEventArgs e)
        {
            Rectangle cursor = new Rectangle(e.X, e.Y, 1, 1);
            if (e.Button == MouseButtons.Left && cursor.IntersectsWith(getLabelRect()))
            {
                return true;
            }
            return false;
        }

        private void lblSelect_MouseUp(object sender, MouseEventArgs e)
        {
            if (!IsDropdownHit(e))
                return;

            if (!cmsItems.Visible)
                lblSelect.ContextMenuStrip = cmsItems;
                cmsItems.Width = lblSelect.Width;
                cmsItems.Show(lblSelect, 0, lblSelect.Height);
        }

        private Rectangle getLabelRect()
        {
            return new Rectangle(lblSelect.Width - 20, 0, 20, lblSelect.Height);
        }
    }
}

【问题讨论】:

    标签: c# winforms user-controls contextmenustrip


    【解决方案1】:

    所以,我稍微重写了你的 mouseUp:

    private void lblSelect_MouseUp(object sender, MouseEventArgs e)
        {
            if (IsDropdownHit(e) && cmsItems.Tag == null)
            {
                cmsItems.Width = lblSelect.Width;
                cmsItems.Show(lblSelect, 0, lblSelect.Height);
                cmsItems.Tag = "Shown";
            }
            else
            {
                cmsItems.Hide();
                cmsItems.Tag = null;
            }
        }
    

    现在,它会关闭。但是 - 如果您不使用按钮关闭,下次您必须单击两次才能打开它。

    此“错误”的解决方法:

    void cmsItems_Closed(object sender, ToolStripDropDownClosedEventArgs e)
        {
            Point c = PointToClient(Cursor.Position);
            if (!IsDropdownHit(new MouseEventArgs(MouseButtons.Left, 1, c.X - lblSelect.Location.X, c.Y - lblSelect.Location.Y, 0)))
                cmsItems.Tag = null;
        }
    

    根据您设计表单的方式,您可能必须调整 MouseEventArgs 坐标,才能成功确定 Dropdownhits。我刚刚将 CMenu 控件添加到一个空窗体中。

    对于解决方法,不要忘记将处理程序添加到 CMenu.cs 的构造函数中:

    cmsItems.Closed += cmsItems_Closed;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-10
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多