且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

淡化面板 - Windows 窗体

更新时间:2023-12-06 10:10:58

这在 Winforms 中非常可行,只需看起来就像一个淡入淡出.一种技术是使用 Control.DrawToBitmap() 创建控件的位图.然后使用计时器从背景位图混合到前景位图.

This is quite do-able in Winforms, it only has to look like a fade. One technique is to use Control.DrawToBitmap() to create a bitmap of the control. And then blend from a background bitmap to the foreground bitmap with a timer.

我将使用 UserControl 而不是 Panel,以便您可以使用 Winforms 设计器设计控件.然而,该代码可以在任何类型的控件中工作.向您的项目添加一个新类并粘贴如下所示的代码.编译.使用 Project + Add New Item、Windows Forms 节点、继承的用户控件"模板创建您自己的 UserControl,然后从弹出列表中选择 FadeControl.正常设计用户控件.

I'll use a UserControl instead of a Panel so you can design the control with the Winforms designer. The code will however work in any kind of control. Add a new class to your project and paste the code shown below. Compile. Create your own UserControl from this one with Project + Add New Item, Windows Forms node, "Inherited User Control" template and pick FadeControl from the popup list. Design the user control as normal.

正如所写的那样,只要您将控件添加到父级,该控件就会自动从父级的 BackColor 淡入控件内容.调用 FadeOut() 使其混合回背景.如果您想在完成淡入淡出时自动处理控件,请传递 true.您可以使用 FadeIn() 和 Faded 属性手动控制淡入淡出.您可以调整注释为//可调整的行中的数字以调整动画.如果父级具有非不透明背景,则需要进行额外的工作.

As written, the control will automatically fade from the parent's BackColor to the control content as soon as you add the control to the parent. Call FadeOut() to make it blend back to the background. Pass true if you want to automatically dispose the control when it is done fading. You can use FadeIn() and the Faded property for manual control of the fading. You can adjust the numbers in the lines commented with // tweakable to adjust the animation. Additional work is needed if the parent has a non-opaque background.

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

class FadeControl : UserControl {

    public FadeControl() {
        pbox = new PictureBox();
        pbox.BorderStyle = BorderStyle.None;
        pbox.Paint += new PaintEventHandler(pbox_Paint);
        fadeTimer = new Timer();
        fadeTimer.Interval = 15;   // tweakable
        fadeTimer.Tick += new EventHandler(fadeTimer_Tick);
    }

    public bool Faded {
        get { return blend < 0.5f; }
    }
    public void FadeIn() {
        stopFade(false);
        createBitmaps();
        startFade(1);
    }
    public void FadeOut(bool disposeWhenDone) {
        stopFade(false);
        createBitmaps();
        disposeOnComplete = disposeWhenDone;
        startFade(-1);
    }

    private void createBitmaps() {
        bmpBack = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
        using (var gr = Graphics.FromImage(bmpBack)) gr.Clear(this.Parent.BackColor);
        bmpFore = new Bitmap(bmpBack.Width, bmpBack.Height);
        this.DrawToBitmap(bmpFore, this.ClientRectangle);
    }
    void fadeTimer_Tick(object sender, EventArgs e) {
        blend += blendDir * 0.02F;   // tweakable
        bool done = false;
        if (blend < 0) { done = true; blend = 0; }
        if (blend > 1) { done = true; blend = 1; }
        if (done) stopFade(true); 
        else pbox.Invalidate();
    }
    void pbox_Paint(object sender, PaintEventArgs e) {
        Rectangle rc = new Rectangle(0, 0, pbox.Width, pbox.Height);
        ColorMatrix cm = new ColorMatrix();
        ImageAttributes ia = new ImageAttributes();
        cm.Matrix33 = blend;
        ia.SetColorMatrix(cm);
        e.Graphics.DrawImage(bmpFore, rc, 0, 0, bmpFore.Width, bmpFore.Height, GraphicsUnit.Pixel, ia);
        cm.Matrix33 = 1F - blend;
        ia.SetColorMatrix(cm);
        e.Graphics.DrawImage(bmpBack, rc, 0, 0, bmpBack.Width, bmpBack.Height, GraphicsUnit.Pixel, ia);
    }

    private void stopFade(bool complete) {
        fadeTimer.Enabled = false;
        if (complete) {
           if (!Faded) this.Controls.Remove(pbox);
           else if (disposeOnComplete) this.Dispose();
        }
        if (bmpBack != null) { bmpBack.Dispose(); bmpBack = null; }
        if (bmpFore != null) { bmpFore.Dispose(); bmpFore = null; }
    }
    private void startFade(int dir) {
        this.Controls.Add(pbox);
        this.Controls.SetChildIndex(pbox, 0);
        blendDir = dir;
        fadeTimer.Enabled = true;
        fadeTimer_Tick(this, EventArgs.Empty);
    }

    protected override void OnCreateControl() {
        base.OnCreateControl();
        if (!DesignMode) FadeIn();
    }
    protected override void OnResize(EventArgs eventargs) {
        pbox.Size = this.ClientSize;
        base.OnResize(eventargs);
    }
    protected override void Dispose(bool disposing) {
        if (disposing) {
            stopFade(false);
            pbox.Dispose();
            fadeTimer.Dispose();
        }
        base.Dispose(disposing);
    }

    private PictureBox pbox;
    private Timer fadeTimer;
    private Bitmap bmpBack, bmpFore;
    private float blend;
    private int blendDir = 1;
    private bool disposeOnComplete;
}