Я придумал следующее расширение:
public static class ObjectExtensions
{
public static void SetValue<TValue>(this object @object, string propertyName, TValue value)
{
var property = @object.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
if (property?.CanWrite == true)
property.SetValue(@object, value, null);
}
}
, которое можно назвать глобально; это работает только в публичных свойствах.
myObject?.SetValue("MyProperty", new SomeObject());
Следующая улучшенная версия работает на что угодно,
public static void SetValue<TObject>(this TObject @object, Action<TObject> assignment)
{
assignment(@object);
}
И также может быть вызвана глобально,
myObject?.SetValue(i => i.MyProperty = new SomeObject());
Но имя расширения несколько вводит в заблуждение, поскольку Action
не требует исключительно назначения.
Вы на самом деле не указали значок, отображаемый на панели задач. Запустив код в LINQPad, просто добавив notifyIcon.Icon = SystemIcons.Application
перед вызовом ShowBalloonTip
, я смог получить подсказку для отображения. Также обратите внимание, что вы должны называть Dispose
, когда вы закончили свой экземпляр NotifyIcon
.
См. приведенный ниже исходный код.
using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace ShowToolTip
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btBallonToolTip_Click(object sender, EventArgs e)
{
ShowBalloonTip();
this.Hide();
}
private void ShowBalloonTip()
{
Container bpcomponents = new Container();
ContextMenu contextMenu1 = new ContextMenu();
MenuItem runMenu = new MenuItem();
runMenu.Index = 1;
runMenu.Text = "Run...";
runMenu.Click += new EventHandler(runMenu_Click);
MenuItem breakMenu = new MenuItem();
breakMenu.Index = 2;
breakMenu.Text = "-------------";
MenuItem exitMenu = new MenuItem();
exitMenu.Index = 3;
exitMenu.Text = "E&xit";
exitMenu.Click += new EventHandler(exitMenu_Click);
// Initialize contextMenu1
contextMenu1.MenuItems.AddRange(
new System.Windows.Forms.MenuItem[] { runMenu, breakMenu, exitMenu });
// Initialize menuItem1
this.ClientSize = new System.Drawing.Size(0, 0);
this.Text = "Ballon Tootip Example";
// Create the NotifyIcon.
NotifyIcon notifyIcon = new NotifyIcon(bpcomponents);
// The Icon property sets the icon that will appear
// in the systray for this application.
string iconPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\setup-icon.ico";
notifyIcon.Icon = new Icon(iconPath);
// The ContextMenu property sets the menu that will
// appear when the systray icon is right clicked.
notifyIcon.ContextMenu = contextMenu1;
notifyIcon.Visible = true;
// The Text property sets the text that will be displayed,
// in a tooltip, when the mouse hovers over the systray icon.
notifyIcon.Text = "Morgan Tech Space BallonTip Running...";
notifyIcon.BalloonTipText = "Morgan Tech Space BallonTip Running...";
notifyIcon.BalloonTipTitle = "Morgan Tech Space";
notifyIcon.ShowBalloonTip(1000);
}
void exitMenu_Click(object sender, EventArgs e)
{
this.Close();
}
void runMenu_Click(object sender, EventArgs e)
{
MessageBox.Show("BallonTip is Running....");
}
}
}
ShowBalloonnTip занимает миллисекунды. 3 миллисекунды могут быть слишком быстрыми, чтобы вы даже могли видеть. Попробуйте что-то большее, чем 3000
Возможно, вам придется передать модель компонента в конструктор. Это то, что я вижу во всех примерах. Извините, я долгое время использовал его. См. Первый ответ здесь:
Взгляните на пример здесь http://msdn.microsoft.com/en-us/library/system.windows.forms.notifyicon.aspx
I см. некоторые отличительные отличия между ним и вашим кодом, есть много частей, которые вы оставляете, например, создание ComponentModelContainer
и передача этого в конструктор NotifyIcon
.
Мэтью определил проблему, но я все еще изо всех сил пытался собрать все части. Поэтому я подумал, что краткий пример, который работает в LINQPad as-is, будет полезен (и, предположительно, в другом месте). Просто ссылку на сборку System.Windows.Forms
и вставьте этот код.
var notification = new System.Windows.Forms.NotifyIcon()
{
Visible = true,
Icon = System.Drawing.SystemIcons.Information,
// optional - BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info,
// optional - BalloonTipTitle = "My Title",
BalloonTipText = "My long description...",
};
// Display for 5 seconds.
notification.ShowBalloonTip(5000);
// This will let the balloon close after it's 5 second timeout
// for demonstration purposes. Comment this out to see what happens
// when dispose is called while a balloon is still visible.
Thread.Sleep(10000);
// The notification should be disposed when you don't need it anymore,
// but doing so will immediately close the balloon if it's visible.
notification.Dispose();
ToolTip
, а не NotifyIcon
. Возможно, это связано с тем, что This [the timeout] parameter is deprecated as of Windows Vista. Notification display times are now based on system accessibility settings.
– user276648
20 July 2017 в 10:11
ShowBalloonTip()
, кажется, работает достаточно хорошо для меня, не нуждаясь в потоке sleep: notification.BalloonTipClosed += (sender, args) => notification.Dispose();
и notification.BalloonTipClicked += (sender, args) => notification.Dispose();
(я обнаружил, что оба требуются , в зависимости от того, нажимает ли пользователь закрыть или оставляет его в тайм-аут).
– jlmt
24 June 2018 в 15:53
Dispose
при закрытии / закрытии окна, иначе он задерживается, пока вы не нажмете на него мышь. – Andrew Grinder 16 July 2014 в 02:24