【问题标题】:How do I set the background image to None, or some other default value, in an image button?如何在图像按钮中将背景图像设置为无或其他默认值?
【发布时间】:2012-07-30 22:03:20
【问题描述】:

我正在构建 this question 并创建一个简单的 ImageButton 类,该类表示一个仅包含图像的按钮。我实现了(至少我相信我做到了)this answer 中的建议,但我仍然遇到此代码异常:

public class ImageButton : Button
{
    // Overrides the property
    public override Image BackgroundImage
    {
        get { return base.BackgroundImage; }
        set
        {
            base.BackgroundImage = value;
            if (value != null) this.Size = value.Size;
        }
    }

    // Shadows the property (note the -new- keyword)
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new Size Size
    {
        get
        {
            return base.Size;
        }
        set
        {
            base.Size = value;
        }
    }

    public ImageButton()
    {
        this.BackgroundImage = base.BackgroundImage;
        this.BackgroundImageChanged += new EventHandler(ImageButton_BackgroundImageChanged);
    }

    void ImageButton_BackgroundImageChanged(object sender, EventArgs e)
    {
        this.Size = this.BackgroundImage.Size;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.DrawImage(BackgroundImage, 0, 0); // <-- Error occurs here
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // Do nothing
    }
}

当我尝试将此控件添加到设计器时,我得到了

控件 ImageButton 在 设计师并已被禁用。

异常:值不能为空。参数名称:图片

堆栈跟踪:ImageButton.OnPaint(PaintEventArgs e) in ImageButton.cs:line48

第 48 行是这一行:

e.Graphics.DrawImage(BackgroundImage, 0, 0);

我意识到引发此错误是因为 BackgroundImage 未设置为值,但我不确定如何在代码中执行此操作。在实际应用中,这个类永远不会添加到设计器中,而是以编程方式添加。如何解决此异常?

【问题讨论】:

    标签: c# winforms button


    【解决方案1】:
        this.BackgroundImage = base.BackgroundImage;
    

    是的,当然,保证例外。您希望有人在构造函数运行之前 设置了 BackgroundImage 属性。这是不可能的,构造函数会在控件上的任何属性被设置之前运行。

    接下来的问题是在设计器中也会引发 Paint 事件。在您将控件放在表单上后立即发生这种情况。这是一个 Kaboom,用户和您的代码都没有给 BackgroundImage 属性赋值。所以只需修复方法:

    protected override void OnPaint(PaintEventArgs e)
    {
        if (BackgroundImage != null) e.Graphics.DrawImage(BackgroundImage, 0, 0);
    }
    

    【讨论】:

    • BackgroundImage ! null 是否等同于 BackgroundImage != null?我现在不在我的工作电脑前测试这个,但我很好奇,因为我以前没有见过那个符号。
    • 那不叫语法,那叫拼写错误;)是时候清理我的笔记本电脑屏幕了。
    【解决方案2】:

    我不知道 C#,但我的猜测是在某处存储一个透明的 1x1px 图像并在初始化时分配它。这样一来,就会有图像,但什么都看不到。

    或者您可以尝试在第 48 行附近添加一些检查,如下所示:

    if(BackgroundImage!=null){
        e.Graphics.DrawImage(BackGroundImage,0,0);
    }
    

    也许可以添加如下内容:

    else{ //No background image
        //Draw some dummy/placeholder
    }
    

    另一种方法是将DrawImage 调用封装在try{} 块中并捕获结果表达式。如果是这样的话,您应该可以安全地使用空的 catch{}block。

    【讨论】:

      【解决方案3】:

      删除背景图片只需写:

      this.BackgroundImage = null;
      

      【讨论】:

        【解决方案4】:

        如果没有设置图片不画怎么办,在函数开头也调用base。

        base.OnPaint(e);
        

        【讨论】:

          【解决方案5】:

          您的实现中有很多冗余代码:试试这个修订版...

          public class ImageButton : Button
              {
                  public ImageButton()
                  {
                      this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
                      this.SetStyle(ControlStyles.UserPaint, true);
                  }
          
                  protected override void OnPaint(PaintEventArgs pevent)
                  {
                      //base.OnPaint(pevent); <-- NO LONGER NEEDED (WE DO NOT WANT THE SYSTEM TO PAINT THE BUTTON);
                      if (this.BackgroundImage != null)
                      {
                          pevent.Graphics.DrawImage(this.BackgroundImage, 0, 0);
                      }
                      else
                      {
                          //Just fill in black (for example)
                          pevent.Graphics.FillRectangle(new SolidBrush(Color.Black), this.ClientRectangle);
                      }
                  }
          
                  protected override void OnPaintBackground(PaintEventArgs pevent)
                  {
                      base.OnPaintBackground(pevent);
                      pevent.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
                  }
          
                  public override Image BackgroundImage
                  {
                      get
                      {
                          return base.BackgroundImage;
                      }
                      set
                      {
                          base.BackgroundImage = value;
                          this.Size = base.BackgroundImage.Size;
                          this.Refresh();
                      }
                  }
              } 
          

          【讨论】:

            猜你喜欢
            • 2013-09-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-09-12
            • 1970-01-01
            相关资源
            最近更新 更多