C# WinForm调用ShellC#教程_

时间:2022-10-16 10:42:06       来源:互联网


(资料图片仅供参考)

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  { // 上面那位用的结构,表示前弹出菜单可用的一个范围大小(一般是全屏幕都让它用,留着搞游戏或视频对话之类的朋友指定菜单可用的范围)   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)      { //如果有定义过菜单关联       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      { //如果没有定义过菜单关联       mb =MouseButtons.Right;      }     }     if (mb !=MouseButtons.None && servicesClass._delegateOfCallBack != null)     {      servicesClass._delegateOfCallBack(mb); // 执行回调      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; // 这个很重要,不能放在构造里,因为它必须和此实例同等生存期才不会被中止消息循环  private readonly IntPtr formTmpHwnd = IntPtr.Zero; // 这是上一行的句柄  private readonly bool VersionOk = false; // 这是一个由VersionPass 返回的属性,它允许开发者检测当前机子的Shell32.dll(可能在win95 或未知平台上版本) 合适此组,不符则用.net 自己的notifyicon  private bool forgetDelNotifyBox = false; // 这是一个私有标志,它允许开发者在程序退出时忘记调用DelNotifyBox 来清除图标时会自动在析构里清掉它。  internal IntPtr formHwnd = IntPtr.Zero; // 这是调用此组件的主窗口句柄(当前实例有效,可多个icon 不冲突)  internal IntPtr contextMenuHwnd = IntPtr.Zero; // 这是菜单的句柄(当前实例有效,可多个icon 不冲突)  internal delegate void delegateOfCallBack(System.Windows.Forms.MouseButtons mb);  internal delegateOfCallBack _delegateOfCallBack = null;  public Shell_NotifyIconEx() // 构造  {   WM_NOTIFY_TRAY += 1; // 消息ID +1,避免多个ICON 消息处理冲突   uID += 1; // 同上   formTmp = new InnerClass(this); // 新实例一个消息循环   formTmpHwnd = formTmp.Handle; // 新实例句柄   VersionOk = this.GetShell32VersionInfo() >= 5; // 版本是否合适,此组件由于重点在气泡提示,它要求Shell32.dll 5.0(ie 5.0) 以上  }  ~Shell_NotifyIconEx()  { // 析构   if (forgetDelNotifyBox) this.DelNotifyBox(); //如果开发者忘记则清理icon  }  #region API_Consts  internal readonly int WM_NOTIFY_TRAY = 0x0400 + 2001; //readonly 表示只在构造可付值  internal readonly int uID = 5000;  // 常数定义,有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 的作用是当 this.focus() 无效时可以考虑使用,效果很好  /// </summary>  /// <param name="hwnd">this.Handle, 当前窗体句柄</param>  [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]  public static extern int SetForegroundWindow(   IntPtr hwnd  );  [StructLayout(LayoutKind.Sequential)]  private struct NOTIFYICONDATA  { // 主角用的结构   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>  /// 建一个结构  /// </summary>  private NOTIFYICONDATA GetNOTIFYICONDATA(IntPtr iconHwnd, string sTip, string boxTitle, string boxText)  {   NOTIFYICONDATA nData = new NOTIFYICONDATA();   nData.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(nData); // 结构的大小   nData.hwnd = formTmpHwnd; // 处理消息循环的窗体句柄,可以移成主窗体   nData.uID = uID; // 消息的 WParam,回调时用   nData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO; // 标志,表示由消息、图标、提示、信息组成   nData.uCallbackMessage = WM_NOTIFY_TRAY; // 消息ID,回调用   nData.hIcon = iconHwnd; // 图标的句柄,有兴趣的话可以定时改变它变成动画ICON   nData.uTimeoutAndVersion = 10 * 1000 | NOTIFYICON_VERSION; // 提示的超时值(几秒后自动消失)和版本   nData.dwInfoFlags = NIIF_INFO; // 类型标志,有INFO、WARNING、ERROR,更改此值将影响气泡提示框的图标类型   nData.szTip = sTip; // 图标的提示信息   nData.szInfoTitle = boxTitle; // 气泡提示框的标题   nData.szInfo = boxText; // 气泡提示框的提示内容   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>  /// 加一个新图标  /// </summary>  /// <param name="iconHwnd">图标句柄</param>  /// <param name="sTip">提示, 5.0 最大: 128 char</param>  /// <param name="boxTitle">气泡标题, 最大: 64 char</param>  /// <param name="boxText">气泡内容, 最大: 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 差不多,不重复了  /// </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>  /// 立即清理掉图标、委托和formtmp 资源(好象没什么资源,考虑到可能二次开发挂接就开了这个东东)  /// </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, "这是标题", "单击这里开始,我将带你畅游API 世界"); }
private void GetPoc1 (MouseButtons mb) { // 回调处理 if (mb == MouseButtons.Left) {  MessageBox.Show ("来自菜单1"); }}privateShell_NotifyIconEx o1 = newShell_NotifyIconEx (); //这个放外面是用在 o.DelNotifyBoxprivate 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); //定义回调}
private void GetPoc1(MouseButtons mb) { // 回调处理 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); //定义回调 } 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调用Shell_NotifyIcon的示例代码的详细内容,更多关于C# WinForm调用Shell_NotifyIcon的资料请关注其它相关文章!

关键词: WinForm 调用Shell_NotifyIcon