1

私はこの質問を基にして、画像のみを含むボタンを表す単純なImageButtonクラスを作成しています。私はこの回答の提案を実装しました(少なくとも私は実行したと思います)が、このコードではまだ例外が発生しています:

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は、デザイナーで未処理の例外をスローし、無効になっています。

例外:値をnullにすることはできません。パラメータ名:画像

スタックトレース:ImageButton.cs:line48のImageButton.OnPaint(PaintEventArgs e)

48行目は次の行です。

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

が値に設定されていないためにこのエラーがスローされることBackgroundImageはわかりましたが、コードでその方法がわかりません。実際のアプリケーションでは、このクラスはデザイナーに追加されることはなく、プログラムで追加されます。この例外を修正するにはどうすればよいですか?

4

5 に答える 5

5
    this.BackgroundImage = base.BackgroundImage;

はい、確かに、保証された例外です。コンストラクターが実行される前に、誰かがBackgroundImageプロパティを設定していることを期待します。それは不可能です。コンストラクターは、コントロールのプロパティを設定する前に実行されます。

次に問題になるのは、ペイントイベントがデザイナーでも発生することです。これは、フォームにコントロールをドロップした直後に発生します。これはKaboomであり、ユーザーもコードもBackgroundImageプロパティにまだ値を指定していません。したがって、メソッドを修正するだけです。

protected override void OnPaint(PaintEventArgs e)
{
    if (BackgroundImage != null) e.Graphics.DrawImage(BackgroundImage, 0, 0);
}
于 2012-07-30T22:34:05.473 に答える
2

C#はわかりませんが、透明な1x1pxの画像をどこかに保存し、それをinitに割り当てると思います。そうすれば、画像は表示されますが、何も表示されません。

または、次のように、48行目にチェックを追加してみてください。

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

多分このようなものを追加します:

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

さらに別の方法は、DrawImage呼び出しをtry{}ブロック内にカプセル化し、結果の式をキャッチすることです。空catch{}のブロックであれば、安全に使用できるはずです。

于 2012-07-30T22:10:46.173 に答える
2

背景画像を削除するには、次のように記述します。

this.BackgroundImage = null;
于 2014-08-27T14:00:50.433 に答える
0

画像が設定されていないときに描画しない場合は、関数の先頭でbaseも呼び出します。

base.OnPaint(e);
于 2012-07-30T22:11:08.310 に答える
0

実装には冗長なコードがたくさんあります。この改訂版を試してください...

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();
            }
        }
    } 
于 2012-07-30T22:24:02.223 に答える