Although .NET expands and civilians, the system's own Notifyicon is inevitious, so that the new version of Shell32.dll (this bubble function is Win98 IE5) is completely available. Not reflected, I have seen a lot of people in 9CBS to make efforts to extend a more perfect Notifyicon, I wrote this extended control bar to the forefront of some of the night before night. There are two days. Many friends throw eggs, so special this draft to supplement the functionality of this control and its specific content to facilitate the second development of friends, this article also defines most of the constants and structures.
preview:
The components are as follows:
Standard shell32.dll's bubble prompt, with the system upgrade support left, right, medium three-click callback support Right-click menu (Handle reference, so you can use .NET yourself can also use .NET own contextMenu) to support dynamic icons (Handle reference, so You can draw your own or resource / external reference, then change, modify the original icon with the modinotifybox of this component, which is the same as addnotifybox, as long as it changes its ICON handle to the handle of the new icon, it is not used Allow multiple icons to be unable to conflict, available for multi-wow software
The content is as follows:
Using system; using system.windows.forms; using system.runtime.interopservices;
Namespace arli.commonprj // To change this name, you should pay attention to change innerclass {using system.io; using system.diagnostics;
///
Private readonly innerclass.formTMP formTMP = null; // This is very important, you can't be placed in the constructor, because it must be in the same life of this instance, it will not be aborted message loop private readonly INTPTR FORMTMPHWND = INTPTR.ZERO; // This is The handle of the last line private readonly bool versionok = false; // This is a property returned by VersionPass, which allows developers to detect the shell32.dll of the current machine (possibly on the Win95 or Unknown Platform), this group, does not match .NET's own NotifyiCon Private Bool ForgetDelnotifyBox = false; // This is a private flag that allows developers to forget to call DelnotifyBox when the program is exited to clear the icon. INTERNAL INTPTR FORMHWND = INTPTR.ZERO; // This is the main window handle of this component (current instance is valid, can be multiple icon does not conflict) INTERNAL INTPTR CONTEXTMENUHWND = INTPTR.ZERO; // This is the handle of the menu (current instance is valid , More icon does not conflict) INTERNAL DELEGATE VOID DELEGATEOFCALLBACK (System.Windows.Forms.MouseButtons MB); Internal DelegateOfCallback_dlegateOfCallback = NULL;
Public shell_notifyiconex () // Construct {WM_NOTIFY_TRAY = 1; // Message ID 1, avoid multiple ICON message processing conflict UID = 1; // 同 同 同 =TMP = New InnerClass.FormTMP (this); // New instance one Message loop FORMTMPHWND = FormTmp.Handle; // New instance handle Versionok = this.getshell32versioninfo ()> = 5; // is appropriate, this component is due to the focus on the bubble tips, it requires shell32.dll 5.0 (IE 5.0) or more}
~ Shell_notifyiconex () {// Destructure IF (ForgetDelnotifyBox) this.delnotifybox (); // If the developer is forgotten to clean ICON}
#REGION API_CONSTS INTERNAL READONLY INT WM_NOTIFY_TRAY = 0x0400 2001; // readonly means only payment value INTERNAL IINLY INTUD = 5000;
// Constant definition, there is a VC can see 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 (// This is the protagonist int dwmessage, ref notifyicondata lpdata);
///
[StructLayout (LayoutKind.Sequential)] private struct NOTIFYICONDATA {// internal lead structures used 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; // this is the essence down a few of the internal int dwStateMask 5.0; [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 0xFF)] internal string szInfo; internal int uTimeoutAndVersion; [MarshalAs ( UnmanagedType.Byvaltstr, SIZECONST = 0x40)] INTERNAL STRING SZINFOTITLE; INTERNAL INT DWINFOFLAGS;} #ENDREGION
///
NData.sztip = stip; // icon prompt information ndata.szinfotitle = BoxTitle; // Bubble prompt box title nData.szinfo = BoxText; // Bubble prompt box prompt content
Return nData; // this. . . }
Private int getShell32versionInfo () {// Returns the version of Shell32 fileInfo fi = new fileInfo (path.combine (system.environment.systemdirectory, "shell32.dll")); // In the future platform shell32, where to know, touch To change 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;
///
///
Notifyicondata ndata = getNotifyicondata (intptr.zero, null, null, null); if (shell_notifylicon (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;}
#REGON OPTIONAL MODULE / / This is an optional method ///
///
#Region Formtmpnamespace arli.commonprj.innerclass {interface class formtmp: system.windows.Forms.form {
Private arli.commonprj.shell_notifyiconex servicesclass = null; // Accept the instance of the primary Class in INTERNAL FORMTMP (arli.commonprj.shell_notifyiconex _serviceclass) {servicesClass = _ServicesClass;}
PRIVATE CONST INT WM_LBUTTONDOWN = 0x0201; // Left button private const INT WM_RBUTTONDOWN = 0x204; // Right-click Private const INT WM_MBUTTONDOWN = 0x207; //
[DLLIMPORT ("User32.dll", entrypoint = "trackpopupmenu")] Private static extern int trackpopunu (// c # and vb.net seems to have no place to popup, as long as it is invited to horses INTPTR HMENU, int WFLAGS, INT X, int y, int NRESERVED, INTPTR HWND, REF Rect LPRC);
[Structlayout (layoutkind.sequential] Private struct rect {// The above-mentioned structure, indicating a range of ranges available before the pop-up menu (generally full screen makes it, keeping games or video conversations) Friends Specify the range available for menu) INTERNAL INT LEFT; INTERNAL INT RIGHT; Internal Int Bottom;
Protected Override Void WndProc (MSG.MSG == ServicesClass.WM_NOTIFY_TRAY) {// If message match IF ((int) msg.wparam == servicesclass.UID) {// WPARAM matching SYSTEM .Windows.forms.mousebuttons mb = system.windows.forms.mousebuttons.none; if ((int) msg.lparam == wm_lbuttondown) {// If you click the left button MB = System.Windows.Forms.MouseButtons.Windows.Forms.MouseButtons.Left } Else if ((int) msg.lparam == wm_mbuttondown) {// mid key MB = system.windows.Forms.MouseButtons.Middle;} else if (int) msg.lparam == wm_rbuttondown) {// Right button IF (ServicesClass.ContextMenuhWnd! = INTPTR.ZERO) {// If there is a defined menu association Rect r = new reference (); r.Left = system.windows.forms.screen.primaryScreen.workingArea.primaryScreen.workingArea.L.Right = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Right; r.Top = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Top; r.Bottom = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Right; TRACKPOPUPMENU (ServicesClass.ContextMenuhwnd, 2 System.windows.forms.cursor.position.x, system.windows.forms.cursor.position.y, 0, serviceclass.formhwnd, ref r);} else {// If there is no defined menu association MB = system. Windows.Forms.MouseButtons.right;}}
IF (MB! = system.windows.forms.mousebuttons.none && service._delegateofcallback! = null) {ServicesClass._dlegateOfCallback (MB); // Perform callback return;}}}}
Base.WndProc (Ref msg);}}} # endregion
Usage example:
Simple example: private void button2_click (object sender, system.eventargs e) {new arli.commonprj.Shell_notifyiconex (). AddnotifyBox (this.icon.handle, this.text, "zpcity.com/arli", "click here to start , I will take you to the API World ");} Sample support menu and callback: private void getpoc1 (MouseButtons MB) {// Tonance Processing if (MB == MouseButtons.Left) {MessageBox.show (" from Menu 1 " );}} private ArLi.CommonPrj.Shell_NotifyIconEx o1 = new ArLi.CommonPrj.Shell_NotifyIconEx (); // this is placed outside the o.DelNotifyBox private void button1_Click (object sender, System.EventArgs e) {o1.AddNotifyBox (this . Parth1, this.text, "Menu 1", "Click here to start, I will take you to the API World"); O1.Handle, this.contextMenu1.handle; // Mount menu optionally o1._delegateOfCallBack = new ArLi.CommonPrj.Shell_NotifyIconEx.delegateOfCallBack (GetPoc1); //} advanced application defines a callback plurality of notifyicon: private void GetPoc1 (MouseButtons mb) {// callback processing if (mb == MouseButtons. Left) {MessageBox.show ("From Menu 1");}} private arli.commonprj.shell_notifyiconex o1 = new arli.commonprj.Shell_notifyiconex (); // This exterior is used in O.DELNOTI Fybox private void button1_click (object sender, system.eventargs e) {o1.addnotifybox (this.icon.handle, this.text, "menu 1", "Click here to start, I will take you to the API World"); O1 .ConnectMyMenu (this.Handle, this.contextMenu1.Handle); // put menu, optionally o1._delegateOfCallBack = new ArLi.CommonPrj.Shell_NotifyIconEx.delegateOfCallBack (GetPoc1); // define the callback} private void GetPoc2 (MouseButtons mb) {IF (MB == MouseButtons.Left) {MessageBox.show ("From Menu 2");}} private arli.commonprj.shell_notifyiconex o2 = new arli.commonprj.Shell_notifyiconex ();
// Second Nofityicon and the same private void button2_click (Object sender, system.eventargs e) {o2.addnotifybox (this.icon.handle, this.text, "menu 2", "Click here to start, I will bring you swim API world "); o2.ConnectMyMenu (this.Handle, this.contextMenu2.Handle); o2._delegateOfCallBack = new ArLi.CommonPrj.Shell_NotifyIconEx.delegateOfCallBack (GetPoc2);} compiled into a DLL component to other languages: csc / t : library /docyiconex.xml cls_notifyiiconex.xml cls_shell_notifyiconex.cs About the detection version does not match: if (! o2.versionpass) {// may be Win98 first edition or 95 // Todo: with .NET own notifyicon} ModinotifyBox: Its usage is basically the same, it is mainly used to modify the original icon, such as the real-time prompt, animation icon, etc. in the Mailcheck module, animation icon, etc. Reference:
Using the Microsoft .NET Compact Framework MessageWindow ClassHttp: //msdn.microsoft.com/library/default.asp? URL = / library / en-us / dnnetcomp / html / messagewindow.asp