C# WinForm调用Shell_NotifyIcon的示例代码
程序员文章站
2022-06-24 09:57:46
public class innerclass: form { private shell_notifyiconex servicesclass = null; // 接受主class 的实例句柄...
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.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); //定义回调 }
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的资料请关注其它相关文章!
上一篇: Android 调用系统相册选择照片
下一篇: 亲自操作Monkey命令基本参数