C# 自定义C按钮和x27;对话框结果不';在模态形式上不能正确工作

C# 自定义C按钮和x27;对话框结果不';在模态形式上不能正确工作,c#,winforms,modal-dialog,imagebutton,dialogresult,C#,Winforms,Modal Dialog,Imagebutton,Dialogresult,在创建Winforms ImageButton类(C#)时遇到一些问题。ImageButton类实现IButtonControl接口,但当我将其添加到表单中,并将按钮的DialogResult设置为“OK”,然后在表单上调用ShowDialog(),按下按钮不会像普通Winforms按钮控件那样关闭表单并返回DialogResult 这是我对ImageButton的实现,您可以随意使用它 /// <summary> /// A control that displays an ima

在创建Winforms ImageButton类(C#)时遇到一些问题。ImageButton类实现IButtonControl接口,但当我将其添加到表单中,并将按钮的DialogResult设置为“OK”,然后在表单上调用ShowDialog(),按下按钮不会像普通Winforms按钮控件那样关闭表单并返回DialogResult

这是我对ImageButton的实现,您可以随意使用它

/// <summary>
/// A control that displays an image and responds to mouse clicks on the image.
/// </summary>
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[Designer(typeof(ImageButtonDesigner))]
[ToolboxItem(typeof(ImageButtonToolboxItem))]
public class ImageButton : PictureBox, IButtonControl, INotifyPropertyChanged
{
    #region Constructors

    /// <summary>
    /// Initializes a new instance of the ImageButton class using the default initial values.
    /// </summary>
    public ImageButton()
    {
        DoubleBuffered = true;
        BackColor = Color.Transparent;
        SizeMode = PictureBoxSizeMode.AutoSize;
    }

    #endregion

    #region Properties

    /// <summary>
    /// Backing field for the DialogResult property.
    /// </summary>
    private DialogResult dialogResult;

    /// <summary>
    /// Gets or sets a value that is returned to the parent form when the button is clicked.
    /// </summary>
    [Category("Behavior")]
    [Description("The dialog-box result produced in a modal form by clicking the button")]
    public DialogResult DialogResult
    {
        get
        {
            return dialogResult;
        }

        set
        {
            if (Enum.IsDefined(typeof(DialogResult), value))
                dialogResult = value;
            else
                throw new InvalidEnumArgumentException("value", (int)value, typeof(DialogResult));
        }
    }

    /// <summary>
    /// Backing field for the Idle property.
    /// </summary>
    private Image idle;

    /// <summary>
    /// The image that will be displayed on the control when the mouse is not over a visible part of it.
    /// </summary>
    [Category("Appearance")]
    [Description("The image that will be displayed on the Control when the mouse is not over a visible part of it.")]
    public Image Idle
    {
        get
        {
            return idle;
        }

        set
        {
            idle = value;

            NotifyPropertyChanged();
        }
    }

    /// <summary>
    /// Backing field for the Mouseover property
    /// </summary>
    private Image mouseover;

    /// <summary>
    /// The image that will be displayed on the control when the mouse is over a visible part of it.
    /// </summary>
    [Category("Appearance")]
    [Description("The image that will be displayed on the control when the mouse is over a visible part of it.")]
    public Image Mouseover
    {
        get { return mouseover; }

        set
        {
            mouseover = value;

            NotifyPropertyChanged();
        }
    }

    /// <summary>
    /// Backing field for the Mousedown property
    /// </summary>
    private Image mousedown;

    /// <summary>
    /// The image that will be displayed on the control when the left mouse button is held down and the mouse is over a visible part of it.
    /// </summary>
    [Category("Appearance")]
    [Description("The image that will be displayed on the control when the left mouse button is held down and the mouse is over a visible part of it.")]
    public Image Mousedown
    {
        get { return mousedown; }

        set
        {
            mousedown = value;

            NotifyPropertyChanged();
        }
    }

    /// <summary>
    /// Gets or sets the text associated with the control.
    /// </summary>
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [Category("Appearance")]
    [Description("The text associated with the control.")]
    public override string Text
    {
        get
        {
            return base.Text;
        }
        set
        {
            base.Text = value;
        }
    }

    /// <summary>
    /// Gets or sets the font of the text displayed by the control.
    /// </summary>
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [Category("Appearance")]
    [Description("The font used to display text in the control.")]
    public override Font Font
    {
        get
        {
            return base.Font;
        }
        set
        {
            base.Font = value;
        }
    }

    /// <summary>
    /// Gets or sets the image that is displayed by the PictureBox.
    /// </summary>
    [EditorBrowsable(EditorBrowsableState.Never)]
    [Browsable(false)]
    [Category("Appearance")]
    [Description("The image displayed in the PictureBox.")]
    new public Image Image
    {
        get
        {
            return base.Image;
        }

        set
        {
            base.Image = value;
        }
    }

    /// <summary>
    /// Backing field for the ButtonState property.
    /// </summary>
    private ButtonStates buttonState = ButtonStates.None;

    /// <summary>
    /// The current state of the button.
    /// </summary>
    private ButtonStates ButtonState
    {
        get { return buttonState; }

        set
        {
            buttonState = value;

            NotifyPropertyChanged();
        }
    }

    /// <summary>
    /// Gets the default size of the control.
    /// </summary>
    protected override Size DefaultSize
    {
        get
        {
            return new Size(75, 23);
        }
    }

    #endregion

    #region Enums

    /// <summary>
    /// Specifies the current state of a button.
    /// </summary>
    [Flags]
    private enum ButtonStates : byte
    {
        /// <summary>
        /// 
        /// </summary>
        [Description("")]
        None = 0,

        /// <summary>
        /// 
        /// </summary>
        [Description("")]
        Default = 1 << 0,

        /// <summary>
        /// 
        /// </summary>
        [Description("")]
        Mouseover = 1 << 1,

        /// <summary>
        /// 
        /// </summary>
        [Description("")]
        Mousedown = 1 << 2
    }

    #endregion

    #region Events

    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    [Category("Property Changed")]
    [Description("Occurs when a property value changes.")]
    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    #region Methods

    /// <summary>
    /// Raises the System.ComponentModel.PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">the name of the property that changed.</param>
    protected virtual void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        if (propertyName == "Idle")
            Image = Idle;
    }

    /// <summary>
    /// Notifies the button whether it is the default button so that it can adjust its appearance accordingly.
    /// </summary>
    /// <param name="value">true if the button is to have the appearance of the default button; otherwise, false.</param>
    public void NotifyDefault(bool value)
    {
        ButtonState = value ? ButtonState | ButtonStates.Default : ButtonState & ~ButtonStates.Default;
    }

    /// <summary>
    /// Generates a Click event for a button.
    /// </summary>
    public void PerformClick()
    {
        if (CanSelect)
        {
            OnClick(EventArgs.Empty);
        }
    }

    /// <summary>
    /// Raises the System.Windows.Control.TextChanged event.
    /// </summary>
    /// <param name="e">A System.EventArgs that contains the event data.</param>
    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);

        Refresh();
    }

    /// <summary>
    /// Raises the System.Windows.Forms.Paint event.
    /// </summary>
    /// <param name="pe">A PaintEventArgs that contains the event data.</param>
    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);

        if ((!string.IsNullOrEmpty(Text)) && (pe != null) && (base.Font != null))
        {
            SolidBrush drawBrush = new SolidBrush(base.ForeColor);

            // Calculate the size of the text that will be drawn onto the control.
            SizeF drawStringSize = pe.Graphics.MeasureString(base.Text, base.Font);

            // The registration point used to draw the text.
            PointF drawPoint;

            if (base.Image != null)
                drawPoint = new PointF(base.Image.Width / 2 - drawStringSize.Width / 2, base.Image.Height / 2 - drawStringSize.Height / 2);
            else
                drawPoint = new PointF(base.Width / 2 - drawStringSize.Width / 2, base.Height / 2 - drawStringSize.Height / 2);

            pe.Graphics.DrawString(base.Text, base.Font, drawBrush, drawPoint);
        }
    }

    /// <summary>
    /// Raises the System.Windows.Forms.MouseEnter event.
    /// </summary>
    /// <param name="e">A System.EventArgs that contains the event data.</param>
    protected override void OnMouseEnter(EventArgs e)
    {
        base.OnMouseEnter(e);

        ButtonState |= ButtonStates.Mouseover;
        Image = Mouseover;
    }

    /// <summary>
    /// Raises the System.Windows.Forms.MouseLeave event.
    /// </summary>
    /// <param name="e">A System.EventArgs that contains the event data.</param>
    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);

        ButtonState &= ~ButtonStates.Mouseover;
        Image = Idle;
    }

    /// <summary>
    /// Raises the System.Windows.Forms.MouseDown event.
    /// </summary>
    /// <param name="e">A System.Windows.Forms.MouseEventArgs that contains the event data.</param>
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);

        ButtonState |= ButtonStates.Mousedown;
        Image = Mousedown;
    }

    /// <summary>
    /// Raises the System.Windows.Forms.MouseUp event.
    /// </summary>
    /// <param name="e">A System.Windows.Forms.MouseEventArgs that contains the event data.</param>
    protected override void OnMouseUp(MouseEventArgs e)
    {
        base.OnMouseUp(e);

        ButtonState &= ~ButtonStates.Mousedown;
        Image = ((ButtonState & ButtonStates.Mouseover) != 0) ? Mouseover : idle;
    }

    #endregion
}

[Serializable]
internal class ImageButtonToolboxItem : ToolboxItem
{
    public ImageButtonToolboxItem() : base(typeof(ImageButton)) { }

    protected ImageButtonToolboxItem(SerializationInfo info, StreamingContext context)
    {
        Deserialize(info, context);
    }

    protected override IComponent[] CreateComponentsCore(IDesignerHost host)
    {
        ImageButton imageButton = (ImageButton)host.CreateComponent(typeof(ImageButton));

        Assembly assembly = Assembly.GetAssembly(typeof(ImageButton));

        using (Stream streamMouseover = assembly.GetManifestResourceStream("Mvc.Mouseover.png"))
        using (Stream streamMousedown = assembly.GetManifestResourceStream("Mvc.Mousedown.png"))
        using (Stream streamIdle = assembly.GetManifestResourceStream("Mvc.Idle.png"))
        {
            imageButton.Idle = Image.FromStream(streamIdle);
            imageButton.Mouseover = Image.FromStream(streamMouseover);
            imageButton.Mousedown = Image.FromStream(streamMousedown);
        }

        return new IComponent[] { imageButton };
    }
}

internal class ImageButtonDesigner : ControlDesigner
{
    protected override void PostFilterAttributes(System.Collections.IDictionary attributes)
    {
        base.PostFilterAttributes(attributes);

        Attribute dockingBehaviour = new DockingAttribute(DockingBehavior.Never);

        attributes[typeof(DockingAttribute)] = dockingBehaviour;
    }

    public override SelectionRules SelectionRules
    {
        get
        {
            return SelectionRules.Moveable;
        }
    }
}
//
///显示图像并响应鼠标单击图像的控件。
/// 
[权限集(SecurityAction.Demand,Name=“FullTrust”)]
[设计师(类型(ImageButtonDesigner))]
[ToolboxItem(类型(ImageButtonToolboxItem))]
公共类图像按钮:PictureBox、IButtonControl、INotifyPropertyChanged
{
#区域构造函数
/// 
///使用默认初始值初始化ImageButton类的新实例。
/// 
公共图像按钮()
{
双缓冲=真;
背景色=颜色。透明;
SizeMode=PictureBoxSizeMode.AutoSize;
}
#端区
#区域属性
/// 
///DialogResult属性的支持字段。
/// 
私有对话框结果对话框结果;
/// 
///获取或设置在单击按钮时返回到父窗体的值。
/// 
[类别(“行为”)]
[说明(“通过单击按钮以模态形式生成的对话框结果”)]
公共对话框结果对话框结果
{
得到
{
返回对话框结果;
}
设置
{
如果(枚举已定义(类型(DialogResult),值))
对话框结果=值;
其他的
抛出新的InvalidEnumArgumentException(“value”,(int)value,typeof(DialogResult));
}
}
/// 
///空闲属性的备份字段。
/// 
私有镜像空闲;
/// 
///当鼠标不在控件的可见部分时,将在控件上显示的图像。
/// 
[类别(“外观”)]
[说明(“当鼠标不在控件的可见部分上时,将在控件上显示的图像。”)]
公众形象闲置
{
得到
{
返回空闲状态;
}
设置
{
空闲=值;
NotifyPropertyChanged();
}
}
/// 
///Mouseover属性的支持字段
/// 
私人图像鼠标器;
/// 
///当鼠标位于控件的可见部分时,将在控件上显示的图像。
/// 
[类别(“外观”)]
[说明(“当鼠标位于控件的可见部分时,将在控件上显示的图像。”)]
公共图像鼠标器
{
获取{return mouseover;}
设置
{
mouseover=值;
NotifyPropertyChanged();
}
}
/// 
///Mousedown属性的支持字段
/// 
私人图像鼠标向下;
/// 
///当按住鼠标左键且鼠标位于控件的可见部分时,控件上显示的图像。
/// 
[类别(“外观”)]
[说明(“当按住鼠标左键且鼠标位于控件可见部分上方时,控件上将显示的图像。”)]
公众形象鼠标下降
{
获取{return mousedown;}
设置
{
mousedown=值;
NotifyPropertyChanged();
}
}
/// 
///获取或设置与控件关联的文本。
/// 
[可浏览(正确)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[类别(“外观”)]
[说明(“与控件关联的文本”)]
公共重写字符串文本
{
得到
{
返回base.Text;
}
设置
{
base.Text=值;
}
}
/// 
///获取或设置控件显示的文本的字体。
/// 
[可浏览(正确)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[类别(“外观”)]
[说明(“用于在控件中显示文本的字体”)]
公共覆盖字体
{
得到
{
返回base.Font;
}
设置
{
base.Font=值;
}
}
/// 
///获取或设置PictureBox显示的图像。
/// 
[EditorBrowsable(EditorBrowsableState.Never)]
[可浏览(错误)]
[类别(“外观”)]
[说明(“图片框中显示的图像”)]
新公众形象
{
得到
{
返回base.Image;
}
设置
{
基础。图像=值;
}
}
/// 
///ButtonState属性的支持字段。
/// 
私有按钮状态按钮状态=按钮状态。无;
/// 
///按钮的当前状态。
/// 
私人按钮状态按钮状态
{
获取{return buttonState;}
设置
{
按钮状态=值;
NotifyPropertyChanged();
}
}
/// 
///获取控件的默认大小。
/// 
受保护的覆盖大小DefaultSize
{
得到
{
返回新尺寸(75,23);
}
}
#端区
#区域枚举
/// 
///指定按钮的当前状态。
/// 
[旗帜]
私有枚举按钮状态:字节
{
/// 
/// 
/// 
[说明(“”)
无=0,
/// 
/// 
/// 
[说明(“”)

默认值=1您需要实际应用分配的DialogResult属性,它不是自动的。通过重写OnClick()方法来实现:

从技术上讲,您还应该将状态更改通知可访问性客户端,但您是否可以
protected override void OnClick(EventArgs e) {
    var form = this.FindForm();
    if (form != null) form.DialogResult = dialogResult;
    base.OnClick(e);
}
    base.AccessibilityNotifyClients(AccessibleEvents.StateChange, -1);
    base.AccessibilityNotifyClients(AccessibleEvents.NameChange, -1);