Feedback

C# - Fading MessageBox ohne Buttons

Veröffentlicht von am 11/22/2007
(7 Bewertungen)
Update 11.12.2007
- Diese neue Version läuft nun als eigener Thread. Somit muß der Anwender nicht mehr warten bis sich die MessageBox geschlossen hat.

- Die FadingMessageBox erscheint nun immer als oberste Ebene auf dem Screen. Somit kann sie nicht mehr versehentlich von anderen Fenstern verdeckt werden.

Zur Beachtung: Weil es hier ein automatisches Disposing gibt, muß die FadingMessageBox bei jeder Nutzung neu instanziiert werden (siehe Gebrauchsbeispiel). Eine Instanziierung in einem Klassenkonstruktor und damit Persistenz zur Lebenszeit einer Klasse führt zu einer ObjectDisposedException ab dem zweiten Aufruf. Diese Exception wird abgefangen.
------------------------------------------------------------
Bei der Verwendung meines ID-Generators brauchte ich einmal viele IDs.
Jedesmal wenn ich eine ID in's Clipboard kopiert hatte, mußte ich auf den OK-Button der Messagebox klicken.
Das ging mir auf die Nerven. So entstand die Idee der Messagebox ohne Buttons.
Statt es durch Mausklick zu schließen, sollte sie sich automatisch nach einer Sekunde, zusammen mit einem Fade-Effekt, schließen.
Das hier ist die Realisierung.
Noch ein Tip: Macht aus dem Snippet eine DLL.

Warum das Interface IFadingMessageBox?
Die FadingMessageBox-Klasse erbt alle öffentlichen Member der Forms-Klasse. Wenn im Designer die Instanzmember von FadingMessageBox aufgerufen werden, würden sämtliche Forms-Member in der Intellisense-Liste ebenfalls erscheinen. ShowAndFade würde darin vollkommen untergehen! Darum habe ich eine explizite Interface-Implementierung eingesetzt.
Es ist möglich, Member der Forms-Klasse zu überschreiben und für Intellisense unsichtbar zu machen (vielen Dank an das MyCsharp-Forum an dieser Stelle). Beispiele:

#region Member der Forms-Klasse ausblenden.
[EditorBrowsable(EditorBrowsableState.Advanced)]
new public IButtonControl AcceptButton
{
get
{
return base.AcceptButton;
}
set
{
base.AcceptButton = value;
}
}

[EditorBrowsable(EditorBrowsableState.Never)]
public void Activate()
{
base.Activate();
}
#endregion

Es sind aber dutzende Member, die auf diese Weise überschrieben werden müßten, und dazu habe ich, ehrlich gesagt, keine Lust. Warum so einen Aufwand betreiben, wenn es mit einem einfachen I auch geht? ;-)
// Interface IFadingMessageBox.cs ================================================
using System;
namespace Cyrons
{
   public interface IFadingMessageBox
   {
      void ShowAndFade(string message, string title, double TimeToFade);
      void ShowAndFade(string message, string title, double TimeToFade,
         FadingMessageBox.FadingMessageBoxIcon icon);
   }
}

// FadingMessageBox.cs ========================================================
#region Gebrauchsbeispiel
/*
private void button_OpenMyMessagebox_Click(object sender, EventArgs e)
{
   IFadingMessageBox fmb = new FadingMessageBox();
   fmb.ShowAndFade("Made by Cyron", "Hinweis", 1.0,
      FadingMessageBox.FadingMessageBoxIcon.Information);
}
*/
#endregion
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace Cyrons
{
   /// <summary>
   /// Stellt eine Messagebox dar,
   /// die sich automatisch nach einer
   /// vorgegebenen Zeit auflöst.
   /// </summary>
   public partial class FadingMessageBox : Form, IFadingMessageBox
   {
      public FadingMessageBox()
      {
         InitializeComponent();
      }

      /// <summary>
      /// Verhindert die mehrfache Ausführung eines Threads,
      /// während die MessageBox noch aktiv ist.
      /// </summary>
      private static volatile bool isAlive;

      #region Properties
      private static string _message;
      protected static string Message
      {
         get
         {
            return _message;
         }
         set
         {
            _message = value;
         }
      }
      private static string _title;
      protected static string Title
      {
         get
         {
            return _title;
         }
         set
         {
            _title = value;
         }
      }
      private static double _fadingTime;
      protected static double FadingTime
      {
         get
         {
            return _fadingTime;
         }
         set
         {
            _fadingTime = value;
         }
      }
      private static FadingMessageBoxIcon _fmbIcon;
      protected static FadingMessageBoxIcon FmbIcon
      {
         get
         {
            return _fmbIcon;
         }
         set
         {
            _fmbIcon = value;
         }
      }
      #endregion

      /// <summary>
      /// Stellt eine Messagebox dar, die sich automatisch nach einer
      /// vorgegebenen Zeit auflöst.
      /// </summary>
      /// <param name="message">Nachrichtentext</param>
      /// <param name="TimeToFade">Zeit in Sekunden, die die Messagebox sichtbar sein soll,
      /// bevor sie ausblendet.</param>
      void IFadingMessageBox.ShowAndFade(string message, string title, double timeToFade)
      {
         if(!isAlive)
         {
            Message = message;
            Title = title;
            FadingTime = timeToFade;
            Thread bgThread = new Thread(new ThreadStart(FadeNoIcon));
            bgThread.Name = "ShowAndFadeWithoutIcon";
            bgThread.Priority = ThreadPriority.BelowNormal;
            bgThread.Start();
         }
      }

      /// <summary>
      /// Stellt eine Messagebox dar, die sich automatisch nach einer
      /// vorgegebenen Zeit auflöst.
      /// </summary>
      /// <param name="message">Nachrichtentext</param>
      /// <param name="TimeToFade">Zeit in Sekunden, die die Messagebox sichtbar sein soll,
      /// bevor sie ausblendet.</param>
      /// <param name="icon">MessageboxIcon-Enumerator</param>
      void IFadingMessageBox.ShowAndFade(string message, string title,
         double timeToFade, FadingMessageBoxIcon icon)
      {
         if(!isAlive)
         {
            Message = message;
            Title = title;
            FadingTime = timeToFade;
            FmbIcon = icon;
            Thread bgThread = new Thread(new ThreadStart(Fade));
            bgThread.Name = "ShowAndFadeWithIcon";
            bgThread.Priority = ThreadPriority.BelowNormal;
            bgThread.Start();
         }
      }

      private void FadeNoIcon()
      {
         isAlive = true;
         try
         {
            int time = Convert.ToInt32(FadingTime * 1000);
            this.Text = Title;
            label_Message.Text = Message;
            //Autosize-Feature
            this.Size = new Size(label_Message.Size.Width + 75, this.Size.Height);
            this.Show();
            this.BringToFront();
            this.Refresh(); // Muß gemacht werden, weil die Form sonst ohne Inhalt erscheint.
            System.Threading.Thread.Sleep((time));
            for(double i = 100; i > -1; i--)
            {
               this.Opacity = i / 100; // Die Opazität ist von 1.0 bis 0.0 definiert.
               this.Refresh(); // Muß gemacht werden, weil die Form sonst ohne Inhalt erscheint.
            }
            this.Close();
         }
         catch(ObjectDisposedException)
         {
            MessageBox.Show("Konstruktor-Instanzen der FadingMessageBox-Klasse sind unzulässig!",
               "FEHLER!", MessageBoxButtons.OK, MessageBoxIcon.Error);
         }
         isAlive = false;
      }

      private void Fade()
      {
         isAlive = true;
         try
         {
            int time = Convert.ToInt32(FadingTime * 1000);
            this.Text = Title;
            label_Message.Text = Message;
            //Autosize-Feature
            this.Size = new Size(label_Message.Size.Width + 75, this.Size.Height);
            InsertIcon(FmbIcon);
            this.Show();
            this.BringToFront();
            this.Refresh(); // Muß gemacht werden, weil die Form sonst ohne Inhalt erscheint.
            PlaySystemSound(FmbIcon);
            System.Threading.Thread.Sleep(time);
            for(double i = 100; i > -1; i--)
            {
               this.Opacity = i / 100; // Die Transparenz ist von 1.0 bis 0.0 definiert.
               this.Refresh(); // Muß gemacht werden, weil die Form sonst ohne Inhalt erscheint.
            }
            this.Close();
         }
         catch(ObjectDisposedException)
         {
            MessageBox.Show("Konstruktor-Instanzen der FadingMessageBox-Klasse sind unzulässig!",
               "FEHLER!", MessageBoxButtons.OK, MessageBoxIcon.Error);
         }         
            isAlive = false;         
      }

      #region Comment
      /* Es gibt noch mehr Messagebox-Icons,
       * aber es sind doppelte:
       * Asterisk = Information
       * Hand = Error
       * Exclamation = Warning
       */
      #endregion

      /// <summary>
      /// Setzt ein System-Icon in die Messagebox.
      /// </summary>
      /// <param name="icon">Icon-Enumerator</param>
      private void InsertIcon(FadingMessageBoxIcon icon)
      {
         switch(icon)
         {
            case FadingMessageBoxIcon.Error:
               pictureBox1.Size = new Size(SystemIcons.Error.Width,
               SystemIcons.Error.Height);
               pictureBox1.Image = SystemIcons.Error.ToBitmap();
               break;
            case FadingMessageBoxIcon.Information:
               pictureBox1.Size = new Size(SystemIcons.Information.Width,
               SystemIcons.Information.Height);
               pictureBox1.Image = SystemIcons.Information.ToBitmap();
               break;
            case FadingMessageBoxIcon.Question:
               pictureBox1.Size = new Size(SystemIcons.Question.Width,
               SystemIcons.Question.Height);
               pictureBox1.Image = SystemIcons.Question.ToBitmap();
               break;
            case FadingMessageBoxIcon.Warning:
               pictureBox1.Size = new Size(SystemIcons.Warning.Width,
               SystemIcons.Warning.Height);
               pictureBox1.Image = SystemIcons.Warning.ToBitmap();
               break;
         }
      }

      /// <summary>
      /// Spielt einen Systemsound ab, abhängig vom gewählten System-Icon.
      /// </summary>
      /// <param name="icon">Icon-Enumerator</param>
      private void PlaySystemSound(FadingMessageBoxIcon icon)
      {
         switch(icon)
         {
            case FadingMessageBoxIcon.Error:
               System.Media.SystemSounds.Hand.Play();
               break;
            case FadingMessageBoxIcon.Information:
               System.Media.SystemSounds.Asterisk.Play();
               break;
            case FadingMessageBoxIcon.Question:
               System.Media.SystemSounds.Question.Play();
               break;
            case FadingMessageBoxIcon.Warning:
               System.Media.SystemSounds.Beep.Play();
               break;
         }
      }

      /// <summary>
      /// Stellt verschiedene System-Icons zur Verfügung.
      /// </summary>
      public enum FadingMessageBoxIcon
      {
         Error = 1,
         Information,
         Question,
         Warning
      }
   }
}

// FadingMessageBox.Designer.cs ===============================================
namespace Cyrons
{
   partial class FadingMessageBox
   {
      /// <summary>
      /// Erforderliche Designervariable.
      /// </summary>
      private System.ComponentModel.IContainer components = null;

      /// <summary>
      /// Verwendete Ressourcen bereinigen.
      /// </summary>
      /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
      protected override void Dispose(bool disposing)
      {
         if(disposing && (components != null))
         {
            components.Dispose();
         }
         base.Dispose(disposing);
      }

      #region Vom Windows Form-Designer generierter Code

      /// <summary>
      /// Erforderliche Methode für die Designerunterstützung.
      /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
      /// </summary>
      private void InitializeComponent()
      {
         this.label_Message = new System.Windows.Forms.Label();
         this.pictureBox1 = new System.Windows.Forms.PictureBox();
         ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
         this.SuspendLayout();
         // 
         // label_Message
         // 
         this.label_Message.AutoSize = true;
         this.label_Message.Location = new System.Drawing.Point(62, 37);
         this.label_Message.Name = "label_Message";
         this.label_Message.Size = new System.Drawing.Size(78, 13);
         this.label_Message.TabIndex = 0;
         this.label_Message.Text = "label_Message";
         // 
         // pictureBox1
         // 
         this.pictureBox1.Location = new System.Drawing.Point(12, 28);
         this.pictureBox1.Name = "pictureBox1";
         this.pictureBox1.Size = new System.Drawing.Size(32, 32);
         this.pictureBox1.TabIndex = 1;
         this.pictureBox1.TabStop = false;
         // 
         // FadingMessageBox
         // 
         this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
         this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
         this.ClientSize = new System.Drawing.Size(147, 92);
         this.ControlBox = false;
         this.Controls.Add(this.pictureBox1);
         this.Controls.Add(this.label_Message);
         this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
         this.MaximizeBox = false;
         this.MinimizeBox = false;
         this.Name = "FadingMessageBox";
         this.ShowIcon = false;
         this.ShowInTaskbar = false;
         this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
         this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
         this.Text = "FadingMessageBox";
         this.TopMost = true;
         ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
         this.ResumeLayout(false);
         this.PerformLayout();

      }

      #endregion

      private System.Windows.Forms.Label label_Message;
      private System.Windows.Forms.PictureBox pictureBox1;
   }
}
Abgelegt unter fading, Messagebox, ausblenden, button, buttons.

4 Kommentare zum Snippet

Volker Steitz schrieb am 11/22/2007:
Find ich prima
Rainer Hilmer schrieb am 5/31/2009:
Ich stelle fest daß die Bewertung meines Snippets mit der Zeit schlechter wird. Es wäre nett wenn die Leute, die mir eine schlechte Bewertung geben, hier einen Kommentar hinterlassen. Durch euer Feedback wäre ich in der Lage, Verbesserungen vorzunehmen.
Keks1911 schrieb am 6/21/2010:
Ich wüsste jetzt nicht genau, wo ich eine solche Messagebox einsetzen würde. Vielleicht bei "Sie haben dieses Feld nicht ausgefüllt"-Hinweisen?
Der Fade-Effekt ist mit meinem build gegen .NET 4.0 nicht sehr stark. Ich habe mal in die Fade-Schleife noch einen Sleep(10) eingebaut, damit man den bemerkt.
Du hast eine Menge Code dupliziert, das könnte man wohl auch kürzer formulieren.
Mein Visual Studio packt das mit dem Designer-Code auch nicht ganz.

Soweit die Dinge, die mir aufgefallen sind. Bewertet habe ich das Snippet nicht.
Silbär schrieb am 9/15/2010:
Eklatante Fehler:
1. Viel doppelter Code
2. Fading über for-schleife ohne Verzögerung => Kann nicht (zuverlässig) funktionieren
3. Fadingtime nicht einstellbar
4. Zugriff auf UI-Element aus anderen Thread. Dafür gibt es Invoke.


=> Gut gedacht aber schlecht gemacht
 

Logge dich ein, um hier zu kommentieren!