gpt4 book ai didi

c# - 自定义 C# 按钮的 DialogResult 在模态窗体上无法正常工作

转载 作者:行者123 更新时间:2023-11-30 20:49:57 26 4
gpt4 key购买 nike

在制作 Winforms ImageButton 类 (C#) 时遇到了一些麻烦。我的 ImageButton 类实现了 IButtonControl 接口(interface),但是当我将它添加到表单并将按钮的 DialogResult 设置为 'OK' ,然后在表单上调用 ShowDialog() 时,按下按钮不会关闭表单并返回 DialogResult,因为普通的 Winforms Button 控件。

这是我对 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;
}
}
}

对于杂乱的工具箱项目和设计器代码感到抱歉..

我的问题是,是否需要任何特殊的实现方式才能使按钮控件在模式窗体上工作(与普通按钮一样)(注:Form 的 BorderStyle 属性设置为 None,不知道这是否重要)

提前致谢!

最佳答案

您需要实际应用分配的 DialogResult 属性,它不是自动的。通过覆盖 OnClick() 方法来实现:

protected override void OnClick(EventArgs e) {
var form = this.FindForm();
if (form != null) form.DialogResult = dialogResult;
base.OnClick(e);
}

从技术上讲,您还应该将状态更改通知可访问性客户端,目前尚不清楚您是否关心这一点。对于自定义控件,它往往会被跳过,但您通常应该这样做。在 base.OnClick() 调用之前插入这些语句:

    base.AccessibilityNotifyClients(AccessibleEvents.StateChange, -1);
base.AccessibilityNotifyClients(AccessibleEvents.NameChange, -1);

关于c# - 自定义 C# 按钮的 DialogResult 在模态窗体上无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22934573/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com