jjzjj

C# 显示通知表单而不关注

coder 2024-06-08 原文

因此,我们决定为我们的聊天应用程序添加某种 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
}

我们根据主窗体中的事件触发这些弹出窗口(比如当一条新的公共(public)消息进来时,通过引用另一个类中的命令(在我们主窗体的类中节省空间):

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);
            }

如何在不从主应用程序窃取焦点的情况下显示此通知表单?

最佳答案

看起来解决方案与我所做的差不多,只是我需要将以下内容添加到通知表单中:

/// <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
                         };
    }

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

关于C# 显示通知表单而不关注,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8424217/

有关C# 显示通知表单而不关注的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  5. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  6. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  7. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  8. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  9. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  10. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

随机推荐