C # показать форму уведомления, не принимая фокус - PullRequest
2 голосов
/ 08 декабря 2011

Итак, мы пообещали, что было бы неплохо добавить какую-либо способность Toast в наше приложение чата, которое на самом деле работает нормально, однако, когда форма показывается, она крадет фокус на короткую секунду, что может заставить окно ввода чата (при вводе в него) мигать или очистить весь текст (так как фокус был украден от него).

Я просмотрел несколько веток на этом сайте, о том, как не допустить этого, переопределив createparms и даже выполнив showwithoutactivating или что-то подобное, но он работает не совсем правильно.

Это то, что у меня есть (прошу прощения за все комментарии, наши начальники хотят, чтобы все было задокументировано):

 public partial class ToastForm : DevComponents.DotNetBar.Metro.MetroForm
{
    #region Variables

    private readonly int _location;

    /// <summary>
    /// The list of currently open ToastForms.
    /// </summary>
    private static readonly List<ToastForm> OpenForms = new List<ToastForm>();

    /// <summary>
    /// Set the window to top most
    /// </summary>
    private const int WsExTopmost = 0x00000008;
    #endregion // Variables


    #region Constructors

    /// <summary>
    /// Creates a new ToastForm object that is displayed for the specified length of time.
    /// </summary>
    /// <param name="lifeTime">
    /// The length of time, in milliseconds, that the form will be displayed.
    /// </param>
    /// <param name="title">title of tooltip</param>
    /// <param name="message">message for tooltip</param>
    /// <param name="location">Location:  0 = top left, 1 = top right, 2 = bottom left, 3 = bottom right</param>
    public ToastForm(int lifeTime,
                     string title,
                     string message,
                     int location)
    {
        InitializeComponent();


        // Set the time for which the form should be displayed and the message to display.
        lifeTimer.Interval = lifeTime;
        tooltipTitle.Text =
            string.Format("<b><font size=\"+6\"><i>New</i><font color=\"#B02B2C\">{0}</font></font></b>",
                          title);
        tooltipText.Text = message;
        _location = location;

    }

    /// <summary>
    /// Do not activate the window just show it
    /// </summary>
    protected override bool ShowWithoutActivation
    {
        get { return true; }
    }

    /// <summary>
    /// Force the ExStyle to be TopMost
    /// </summary>
    protected override CreateParams CreateParams
    {
        get
        {
            var param = base.CreateParams;
            param.ExStyle |= WsExTopmost; // make the form topmost
            return param;
        }
    }

    #endregion // Constructors


    #region Event Handlers

    /// <summary>
    /// Do this when the form loads
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    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();
    }

    /// <summary>
    /// Happens when the form closes
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    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);
    }

    /// <summary>
    /// If the tooltip has expired
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void LifeTimerTick(object sender,
                               EventArgs e)
    {
        // The form's lifetime has expired.
        Close();
    }

    #endregion // Event Handlers

    #region Methods

    /// <summary>
    /// Quickly close the tooltip
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void TooltipCancelClick(object sender,
                                    EventArgs e)
    {
        lifeTimer.Interval = 1;
    }
    #endregion
}

Мы запускаем эти всплывающие окна на основе событий в нашей основной форме (например, когда приходит новое общедоступное сообщение, путем ссылки на команду в другом классе (экономит место в классе нашей основной формы):

class ToastControl
{
    public static int SliceCount { get; private set; }

    internal static void ShowAlert(string msg, string 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(string msg, string 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(string msg, string 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(string msg, string 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(string msg, string title, Font fnt)
    {
        SliceCount += 1;
        var slice = new ToastForm(5000,
                                  title,
                                  msg, 1)
        {
            Height = (25 + 82) + ((int)(msg.Length / fnt.Size)) * 2
        };
        slice.Show();
    }
}

И пример вызова этого класса:

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

Как я могу получить эту форму уведомления, чтобы она не отвлекала внимание от основного приложения?

1 Ответ

6 голосов
/ 09 декабря 2011

Похоже, что решение состоит в том, чтобы сделать в значительной степени то, что я сделал, за исключением того, что мне нужно было добавить следующее в форму уведомления:

/// <summary>
    /// Do not activate the window just show it
    /// </summary>
    protected override bool ShowWithoutActivation
    {
        get { return true; }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x00000008; //WS_EX_TOPMOST 
            return cp;
        }
    } 

и изменить класс Toast Control, чтобы использовать вместо него «Visible»of .Show:

 internal static void AlertBottomRight(string msg, string 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(string msg, string 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(string msg, string 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(string msg, string title, Font fnt)
    {
        SliceCount += 1;
        new ToastForm(5000,
                      title,
                      msg,
                      1) {
                             Height = (25 + 82) + ((int) (msg.Length / fnt.Size)) * 2,
                             Visible = true
                         };
    }

Теперь, когда отображаются уведомления, они не крадут фокус, и они выглядят просто отлично в верхней части других окон :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...