C# WinForm調(diào)用Shell_NotifyIcon的示例代碼
更新時間:2020年11月21日 17:13:42 作者:正在緩沖
這篇文章主要介紹了C# WinForm調(diào)用Shell_NotifyIcon的示例代碼,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
public class InnerClass: Form
{
private Shell_NotifyIconEx servicesClass = null; // 接受主CLASS 的實例句柄
internal InnerClass(Shell_NotifyIconEx _servicesClass)
{
servicesClass = _servicesClass;
}
private const int WM_LBUTTONDOWN = 0x0201; // 左鍵
private const int WM_RBUTTONDOWN = 0x204; // 右鍵
private const int WM_MBUTTONDOWN = 0x207; // 中鍵
[DllImport("user32.dll", EntryPoint = "TrackPopupMenu")]
private static extern int TrackPopupMenu( // c# 和vb.net 好象沒有了隨地popup 了,只要請它老人家出馬了
IntPtr hMenu,
int wFlags,
int x,
int y,
int nReserved,
IntPtr hwnd,
ref RECT lprc
);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{ // 上面那位用的結(jié)構(gòu),表示前彈出菜單可用的一個范圍大?。ㄒ话闶侨聊欢甲屗茫糁阌螒蚧蛞曨l對話之類的朋友指定菜單可用的范圍)
internal int Left;
internal int Top;
internal int Right;
internal int Bottom;
}
protected override void WndProc(ref Message msg)
{
if (msg.Msg == servicesClass.WM_NOTIFY_TRAY)
{ // 如果消息相符
if ((int)msg.WParam == servicesClass.uID)
{ // 并且消息的WParam 相符
MouseButtons mb =MouseButtons.None;
if ((int)msg.LParam == WM_LBUTTONDOWN)
{ //如果點擊的是左鍵
mb =MouseButtons.Left;
}
else if ((int)msg.LParam == WM_MBUTTONDOWN)
{ //中鍵
mb =MouseButtons.Middle;
}
else if ((int)msg.LParam == WM_RBUTTONDOWN)
{ //右鍵
if (servicesClass.contextMenuHwnd != IntPtr.Zero)
{ //如果有定義過菜單關(guān)聯(lián)
RECT r = new RECT();
r.Left = Screen.PrimaryScreen.WorkingArea.Left;
r.Right =Screen.PrimaryScreen.WorkingArea.Right;
r.Top =Screen.PrimaryScreen.WorkingArea.Top;
r.Bottom =Screen.PrimaryScreen.WorkingArea.Right;
TrackPopupMenu(
servicesClass.contextMenuHwnd,
2,
Cursor.Position.X,
Cursor.Position.Y,
0,
servicesClass.formHwnd,
ref r
);
}
else
{ //如果沒有定義過菜單關(guān)聯(lián)
mb =MouseButtons.Right;
}
}
if (mb !=MouseButtons.None && servicesClass._delegateOfCallBack != null)
{
servicesClass._delegateOfCallBack(mb); // 執(zhí)行回調(diào)
return;
}
}
}
base.WndProc(ref msg);
}
}
public class Shell_NotifyIconEx
{
/// <summary>
/// ArLi, last fix: 2003.9.12, reference: ArLi.CommonPrj Lib @ http://zpcity.com/arli/
/// </summary>
public static readonly System.Version myVersion = new System.Version(1, 2); //版本聲明
private readonly InnerClass formTmp = null; // 這個很重要,不能放在構(gòu)造里,因為它必須和此實例同等生存期才不會被中止消息循環(huán)
private readonly IntPtr formTmpHwnd = IntPtr.Zero; // 這是上一行的句柄
private readonly bool VersionOk = false; // 這是一個由VersionPass 返回的屬性,它允許開發(fā)者檢測當(dāng)前機子的Shell32.dll(可能在win95 或未知平臺上版本) 合適此組,不符則用.net 自己的notifyicon
private bool forgetDelNotifyBox = false; // 這是一個私有標(biāo)志,它允許開發(fā)者在程序退出時忘記調(diào)用DelNotifyBox 來清除圖標(biāo)時會自動在析構(gòu)里清掉它。
internal IntPtr formHwnd = IntPtr.Zero; // 這是調(diào)用此組件的主窗口句柄(當(dāng)前實例有效,可多個icon 不沖突)
internal IntPtr contextMenuHwnd = IntPtr.Zero; // 這是菜單的句柄(當(dāng)前實例有效,可多個icon 不沖突)
internal delegate void delegateOfCallBack(System.Windows.Forms.MouseButtons mb);
internal delegateOfCallBack _delegateOfCallBack = null;
public Shell_NotifyIconEx() // 構(gòu)造
{
WM_NOTIFY_TRAY += 1; // 消息ID +1,避免多個ICON 消息處理沖突
uID += 1; // 同上
formTmp = new InnerClass(this); // 新實例一個消息循環(huán)
formTmpHwnd = formTmp.Handle; // 新實例句柄
VersionOk = this.GetShell32VersionInfo() >= 5; // 版本是否合適,此組件由于重點在氣泡提示,它要求Shell32.dll 5.0(ie 5.0) 以上
}
~Shell_NotifyIconEx()
{ // 析構(gòu)
if (forgetDelNotifyBox) this.DelNotifyBox(); //如果開發(fā)者忘記則清理icon
}
#region API_Consts
internal readonly int WM_NOTIFY_TRAY = 0x0400 + 2001; //readonly 表示只在構(gòu)造可付值
internal readonly int uID = 5000;
// 常數(shù)定義,有VC 的可以參見 shellapi.h
private const int NIIF_NONE = 0x00;
private const int NIIF_INFO = 0x01;
private const int NIIF_WARNING = 0x02;
private const int NIIF_ERROR = 0x03;
private const int NIF_MESSAGE = 0x01;
private const int NIF_ICON = 0x02;
private const int NIF_TIP = 0x04;
private const int NIF_STATE = 0x08;
private const int NIF_INFO = 0x10;
private const int NIM_ADD = 0x00;
private const int NIM_MODIFY = 0x01;
private const int NIM_DELETE = 0x02;
private const int NIM_SETFOCUS = 0x03;
private const int NIM_SETVERSION = 0x04;
private const int NIS_HIDDEN = 0x01;
private const int NIS_SHAREDICON = 0x02;
private const int NOTIFYICON_OLDVERSION = 0x00;
private const int NOTIFYICON_VERSION = 0x03;
[DllImport("shell32.dll", EntryPoint = "Shell_NotifyIcon")]
private static extern bool Shell_NotifyIcon( // 這位是主角
int dwMessage,
ref NOTIFYICONDATA lpData
);
/// <summary>
/// 此API 的作用是當(dāng) this.focus() 無效時可以考慮使用,效果很好
/// </summary>
/// <param name="hwnd">this.Handle, 當(dāng)前窗體句柄</param>
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
public static extern int SetForegroundWindow(
IntPtr hwnd
);
[StructLayout(LayoutKind.Sequential)]
private struct NOTIFYICONDATA
{ // 主角用的結(jié)構(gòu)
internal int cbSize;
internal IntPtr hwnd;
internal int uID;
internal int uFlags;
internal int uCallbackMessage;
internal IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x80)]
internal string szTip;
internal int dwState; // 這里往下幾個是 5.0 的精華
internal int dwStateMask;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0xFF)]
internal string szInfo;
internal int uTimeoutAndVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x40)]
internal string szInfoTitle;
internal int dwInfoFlags;
}
#endregion
/// <summary>
/// 建一個結(jié)構(gòu)
/// </summary>
private NOTIFYICONDATA GetNOTIFYICONDATA(IntPtr iconHwnd, string sTip, string boxTitle, string boxText)
{
NOTIFYICONDATA nData = new NOTIFYICONDATA();
nData.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(nData); // 結(jié)構(gòu)的大小
nData.hwnd = formTmpHwnd; // 處理消息循環(huán)的窗體句柄,可以移成主窗體
nData.uID = uID; // 消息的 WParam,回調(diào)時用
nData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO; // 標(biāo)志,表示由消息、圖標(biāo)、提示、信息組成
nData.uCallbackMessage = WM_NOTIFY_TRAY; // 消息ID,回調(diào)用
nData.hIcon = iconHwnd; // 圖標(biāo)的句柄,有興趣的話可以定時改變它變成動畫ICON
nData.uTimeoutAndVersion = 10 * 1000 | NOTIFYICON_VERSION; // 提示的超時值(幾秒后自動消失)和版本
nData.dwInfoFlags = NIIF_INFO; // 類型標(biāo)志,有INFO、WARNING、ERROR,更改此值將影響氣泡提示框的圖標(biāo)類型
nData.szTip = sTip; // 圖標(biāo)的提示信息
nData.szInfoTitle = boxTitle; // 氣泡提示框的標(biāo)題
nData.szInfo = boxText; // 氣泡提示框的提示內(nèi)容
return nData; // 這個嘛。。。
}
private int GetShell32VersionInfo()
{ // 返回shell32 的版本
FileInfo fi = new FileInfo(Path.Combine(System.Environment.SystemDirectory, "shell32.dll")); //將來的平臺shell32 放哪目前不得而知,碰到再改
if (fi.Exists)
{
FileVersionInfo theVersion = FileVersionInfo.GetVersionInfo(fi.FullName);
int i = theVersion.FileVersion.IndexOf('.');
if (i > 0)
{
try
{
return int.Parse(theVersion.FileVersion.Substring(0, i));
}
catch { }
}
}
return 0;
}
/// <summary>
/// 加一個新圖標(biāo)
/// </summary>
/// <param name="iconHwnd">圖標(biāo)句柄</param>
/// <param name="sTip">提示, 5.0 最大: 128 char</param>
/// <param name="boxTitle">氣泡標(biāo)題, 最大: 64 char</param>
/// <param name="boxText">氣泡內(nèi)容, 最大: 256 char</param>
/// <returns>成功、失敗或錯誤(-1)</returns>
public int AddNotifyBox(IntPtr iconHwnd, string sTip, string boxTitle, string boxText)
{
if (!this.VersionOk) return -1;
NOTIFYICONDATA nData = GetNOTIFYICONDATA(iconHwnd, sTip, boxTitle, boxText);
if (Shell_NotifyIcon(NIM_ADD, ref nData))
{
this.forgetDelNotifyBox = true;
return 1;
}
else
{
return 0;
}
}
/// <summary>
/// 和add 差不多,不重復(fù)了
/// </summary>
public int DelNotifyBox()
{
if (!this.VersionOk) return -1;
NOTIFYICONDATA nData = GetNOTIFYICONDATA(IntPtr.Zero, null, null, null);
if (Shell_NotifyIcon(NIM_DELETE, ref nData))
{
this.forgetDelNotifyBox = false;
return 1;
}
else
{
return 0;
}
}
public int ModiNotifyBox(IntPtr iconHwnd, string sTip, string boxTitle, string boxText)
{
if (!this.VersionOk) return -1;
NOTIFYICONDATA nData = GetNOTIFYICONDATA(iconHwnd, sTip, boxTitle, boxText);
return Shell_NotifyIcon(NIM_MODIFY, ref nData) ? 1 : 0;
}
#region Optional Module //這里是可選方法
/// <summary>
/// 連接一個已存在的 contextMenu
/// </summary>
/// <param name="_formHwnd">窗體句柄,用來處理菜單的消息</param>
/// <param name="_contextMenuHwnd">菜單的句柄</param>
public void ConnectMyMenu(IntPtr _formHwnd, IntPtr _contextMenuHwnd)
{
formHwnd = _formHwnd;
contextMenuHwnd = _contextMenuHwnd;
}
/// <summary>
/// 立即清理掉圖標(biāo)、委托和formtmp 資源(好象沒什么資源,考慮到可能二次開發(fā)掛接就開了這個東東)
/// </summary>
public void Dispose()
{
_delegateOfCallBack = null;
this.formTmp.Dispose();
}
/// <summary>
/// 版本適合
/// </summary>
public bool VersionPass
{
get
{
return this.VersionOk;
}
}
#endregion
}
用法示例:
private void button2_Click (object sender, System.EventArgs e) {
Shell_NotifyIconEx ().AddNotifyBox (this.Icon.Handle, this.Text, "這是標(biāo)題", "單擊這里開始,我將帶你暢游API 世界");
}
private void GetPoc1 (MouseButtons mb) { // 回調(diào)處理
if (mb == MouseButtons.Left) {
MessageBox.Show ("來自菜單1");
}
}
privateShell_NotifyIconEx o1 = newShell_NotifyIconEx (); //這個放外面是用在 o.DelNotifyBox
private void button1_Click (object sender, System.EventArgs e) {
o1.AddNotifyBox (this.Icon.Handle, this.Text, "菜單1", "單擊這里開始,我將帶你暢游API 世界");
o1.ConnectMyMenu (this.Handle, this.contextMenu1.Handle); // 掛上菜單,可選
o1._delegateOfCallBack = newShell_NotifyIconEx.delegateOfCallBack (GetPoc1); //定義回調(diào)
}
private void GetPoc1(MouseButtons mb) { // 回調(diào)處理
if (mb == MouseButtons.Left) {
MessageBox.Show("來自菜單1");
}
}
private Shell_NotifyIconEx o1 = new Shell_NotifyIconEx(); //這個放外面是用在 o.DelNotifyBox
private void button1_Click(object sender, System.EventArgs e) {
o1.AddNotifyBox(this.Icon.Handle,this.Text,"菜單1","單擊這里開始,我將帶你暢游API 世界");
o1.ConnectMyMenu(this.Handle,this.contextMenu1.Handle); // 掛上菜單,可選
o1._delegateOfCallBack = new Shell_NotifyIconEx.delegateOfCallBack(GetPoc1); //定義回調(diào)
}
private void GetPoc2(MouseButtons mb) {
if (mb == MouseButtons.Left) {
MessageBox.Show("來自菜單2");
}
}
private Shell_NotifyIconEx o2 = new Shell_NotifyIconEx(); //第二個nofityicon 和上面一樣
private void button2_Click(object sender, System.EventArgs e) {
o2.AddNotifyBox(this.Icon.Handle,this.Text,"菜單2","單擊這里開始,我將帶你暢游API 世界");
o2.ConnectMyMenu(this.Handle,this.contextMenu2.Handle);
o2._delegateOfCallBack = new Shell_NotifyIconEx.delegateOfCallBack(GetPoc2);
}
以上就是C# WinForm調(diào)用Shell_NotifyIcon的示例代碼的詳細內(nèi)容,更多關(guān)于C# WinForm調(diào)用Shell_NotifyIcon的資料請關(guān)注腳本之家其它相關(guān)文章!
您可能感興趣的文章:
相關(guān)文章
C#中const,readonly和static關(guān)鍵字的用法介紹
這篇文章介紹了C#中const,readonly和static關(guān)鍵字的用法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08
C#創(chuàng)建一個可快速重復(fù)使用的項目模板(詳細過程)
這篇文章主要介紹了C#如何創(chuàng)建一個可快速重復(fù)使用的項目模板今天給大家介紹的是基于官方的cli donet new 命令創(chuàng)建自己的項目模板,需要的朋友可以參考下2024-06-06
C#利用Refit實現(xiàn)JWT自動續(xù)期詳解
Refit?是一個受到Square的Retrofit庫(Java)啟發(fā)的自動類型安全REST庫,這篇文章主要為大家介紹了C#如何利用Refit實現(xiàn)JWT自動續(xù)期,感興趣的可以了解下2023-08-08

