C#显示通知表,没有它成为焦点

时间:2011-12-07 23:35:13

标签: c# windows winforms api

所以,我们认为在我们的聊天应用程序中添加某种Toast功能是一个好主意,实际上它工作得很好,但是,当表单显示时,它会将焦点转移到breif秒,这可以使聊天输入框(当你输入它时)闪烁或清除所有文本(因为焦点被偷走了)。

我已经回顾了这个网站上的几个主题,关于如何通过覆盖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 个答案:

答案 0 :(得分:6)

看起来解决方案是做我做的几乎所有,除了我需要在通知表单中添加以下内容:

/// <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'而不是'.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
                         };
    }

现在,当显示通知时,它们不会窃取焦点,并且它们在其他窗口的顶部看起来很好:)