C # affiche le formulaire de notification sans qu’il y ait mise au point

Donc, nous avons estimé que ce serait une bonne idée d’append une sorte de capacité Toast à notre application de chat, qui fonctionne bien, cependant, lorsque le formulaire s’affiche, il vole le focus pendant une seconde, ce qui peut rendre le chat La zone de saisie (lorsque vous la saisissez) clignote ou efface tout le texte (le focus ayant été volé).

J’ai passé en revue plusieurs discussions sur ce site, sur la façon de l’empêcher de passer outre les createparms et même d’ showwithoutactivating une émission sans showwithoutactivating ou autre, mais cela ne fonctionne pas tout à fait correctement.

C’est ce que j’ai (je m’excuse pour tous les commentaires, nos patrons veulent tout documenté):

  public partial class ToastForm : DevComponents.DotNetBar.Metro.MetroForm { #region Variables private readonly int _location; ///  /// The list of currently open ToastForms. ///  private static readonly List OpenForms = new List(); ///  /// Set the window to top most ///  private const int WsExTopmost = 0x00000008; #endregion // Variables #region Constructors ///  /// Creates a new ToastForm object that is displayed for the specified length of time. ///  ///  /// The length of time, in milliseconds, that the form will be displayed. ///  /// title of tooltip /// message for tooltip /// Location: 0 = top left, 1 = top right, 2 = bottom left, 3 = bottom right public ToastForm(int lifeTime, ssortingng title, ssortingng message, int location) { InitializeComponent(); // Set the time for which the form should be displayed and the message to display. lifeTimer.Interval = lifeTime; tooltipTitle.Text = ssortingng.Format("New{0}", title); tooltipText.Text = message; _location = location; } ///  /// Do not activate the window just show it ///  protected override bool ShowWithoutActivation { get { return true; } } ///  /// Force the ExStyle to be TopMost ///  protected override CreateParams CreateParams { get { var param = base.CreateParams; param.ExStyle |= WsExTopmost; // make the form topmost return param; } } #endregion // Constructors #region Event Handlers ///  /// Do this when the form loads ///  ///  ///  private void ToastFormLoad(object sender, EventArgs e) { switch (_location) { case 0: // top left corner of screen Location = new Point(0, 0); break; case 1: // top right corner of screen Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width - 5, 0); break; case 2: // bottom left corner of screen Location = new Point(0, Screen.PrimaryScreen.WorkingArea.Height - Height - 5); break; case 3: // bottom right corner of screen Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width - 5, Screen.PrimaryScreen.WorkingArea.Height - Height - 5); break; } // Move each open form upwards to make room for this one. foreach (var openForm in OpenForms) { switch (_location) { case 0: case 1: openForm.Top += Height + 5; break; case 2: case 3: openForm.Top -= Height + 5; break; } } OpenForms.Add(this); lifeTimer.Start(); } ///  /// Happens when the form closes ///  ///  ///  private void ToastFormFormClosed(object sender, FormClosedEventArgs e) { // Move down any open forms above this one. foreach (var openForm in OpenForms.TakeWhile(openForm => openForm != this)) { switch (_location) { case 0: openForm.Top -= Height + 5; break; case 1: openForm.Top -= Height + 5; break; case 2: openForm.Top += Height + 5; break; case 3: openForm.Top += Height + 5; break; } } // Remove this form from the open form list. OpenForms.Remove(this); } ///  /// If the tooltip has expired ///  ///  ///  private void LifeTimerTick(object sender, EventArgs e) { // The form's lifetime has expired. Close(); } #endregion // Event Handlers #region Methods ///  /// Quickly close the tooltip ///  ///  ///  private void TooltipCancelClick(object sender, EventArgs e) { lifeTimer.Interval = 1; } #endregion } 

Nous déclenchons ces popups en fonction des événements de notre formulaire principal (comme lorsqu’un nouveau message public arrive, en référençant une commande dans une autre classe (économise de la place dans la classe de notre formulaire principal)):

 class ToastControl { public static int SliceCount { get; private set; } internal static void ShowAlert(ssortingng msg, ssortingng title, Font fnt) { switch (Settings.Default.PopUpSide) { case 0: AlertTopLeft(msg, title, fnt); break; case 1: AlertTopRight(msg, title, fnt); break; case 2: AlertBottomLeft(msg, title, fnt); break; case 3: AlertBottomRight(msg, title, fnt); break; default: AlertBottomRight(msg, title, fnt); break; } } internal static void AlertBottomRight(ssortingng msg, ssortingng title, Font fnt) { SliceCount += 1; var slice = new ToastForm(5000, title, msg, 3) { Height = (25 + 82) + ((int)(msg.Length / fnt.Size)) * 2 }; slice.Show(); } internal static void AlertBottomLeft(ssortingng msg, ssortingng title, Font fnt) { SliceCount += 1; var slice = new ToastForm(5000, title, msg, 2) { Height = (25 + 82) + ((int)(msg.Length / fnt.Size)) * 2 }; slice.Show(); } internal static void AlertTopLeft(ssortingng msg, ssortingng title, Font fnt) { SliceCount += 1; var slice = new ToastForm(5000, title, msg, 0) { Height = (25 + 82) + ((int)(msg.Length / fnt.Size)) * 2 }; slice.Show(); } internal static void AlertTopRight(ssortingng msg, ssortingng title, Font fnt) { SliceCount += 1; var slice = new ToastForm(5000, title, msg, 1) { Height = (25 + 82) + ((int)(msg.Length / fnt.Size)) * 2 }; slice.Show(); } } 

Et un exemple de l’appel à cette classe:

 if (Settings.Default.PopUpEnabledChat) { if (!(Settings.Default.NoAlerts)) ToastControl.ShowAlert(ssortingng.Format("{0}: {1}", user.Nick, description.Replace("\r", "").Replace("\n", "").Replace("\0", "")), channel, Font); } 

Comment puis-je obtenir ce formulaire de notification pour montrer sans jamais voler l’attention de l’application principale?

On dirait que la solution consiste à faire à peu près ce que j’ai fait, sauf que je devais append ce qui suit au formulaire de notification:

 ///  /// Do not activate the window just show it ///  protected override bool ShowWithoutActivation { get { return true; } } protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x00000008; //WS_EX_TOPMOST return cp; } } 

Et changez la classe Toast Control pour utiliser ‘Visible’ au lieu de ‘.Show’:

  internal static void AlertBottomRight(ssortingng msg, ssortingng title, Font fnt) { SliceCount += 1; new ToastForm(5000, title, msg, 3) { Height = (25 + 82) + ((int) (msg.Length / fnt.Size)) * 2, Visible = true }; } internal static void AlertBottomLeft(ssortingng msg, ssortingng title, Font fnt) { SliceCount += 1; new ToastForm(5000, title, msg, 2) { Height = (25 + 82) + ((int) (msg.Length / fnt.Size)) * 2, Visible = true }; } internal static void AlertTopLeft(ssortingng msg, ssortingng title, Font fnt) { SliceCount += 1; new ToastForm(5000, title, msg, 0) { Height = (25 + 82) + ((int) (msg.Length / fnt.Size)) * 2, Visible = true }; } internal static void AlertTopRight(ssortingng msg, ssortingng title, Font fnt) { SliceCount += 1; new ToastForm(5000, title, msg, 1) { Height = (25 + 82) + ((int) (msg.Length / fnt.Size)) * 2, Visible = true }; } 

Maintenant, lorsque les notifications sont affichées, elles ne volent pas le focus, et elles apparaissent bien au-dessus des autres fenêtres 🙂