VC Programming Making System Tray Program Windows operating system does not display the run window, only displaying an icon on the taskbar, indicating that the program is running, the user can interact with the application, such as Jinshan drug tyrants and other applications We sometimes need to prepare similar programs running only in the background, in order not to interfere with the running interface of the front program and the unnecessary window, you should make the main window when the program is running is invisible. At the same time, an icon is displayed in the right end of the taskbar and responds to the user's mouse action. Here is the design method of Visual C development such a program. First, the main window of the hidden program first, to make the program's main window is invisible, and do not appear on the taskbar, do these two points, you need to set the style and extended style of the main Border window, you: BOOL CMAINFRAME :: PrecreateWindow (CREATESTRUCT & CS) {cs.style = WS_POPUP; // Make the main window cs.dwexStyle | = WS_EX_TOOLWINDOW; / / Do not display the task button return cframeWnd :: PrecreateWindow (CS);} II, will represent the icon running Add the above function in the CMAINFRAME :: onCreate () function of the main frame window, you can display the icon on the task bar to use the system API function shell_notifyicon () to display an icon in the notification area of the taskbar. The prototype of this function is: Before calling the function, you need to determine the value of its parameters. Where the first parameter of the shell_notifyicon () function is a predefined message, you can take one of the values: NIM_ADD, NIM_DELETE, or NIM_MODIFY, indicate the add icon, delete icon, or modify icon. Another parameter is a pointer to the Notifyicondata type. Its prototype is: typedef struct _notifyicondata {dWord Cbsize; hwnd hwnd; uint UID; uint uflags; uint ucallbackMessage; Hicon Hicon; Charsztip [64];} Notifyicondata In the member of this structure, CBSIZE is the number of bytes of this structure HWnd is a handle of the window that accepts the message issued by the icon (the mouse will make a message when the mouse is on the taskbar icon on the taskbar icon. This message user must define itself), the UID is the ID of the display icon, uflags indicates the rest of it. Several members (HICON, UCALLBACKMESSAGE and SZTIP) are valid, uCallbackMessage is a user-defined message, when the user acts on this icon, the icon will be the main frame window of the application (specified in the HWND member The window is issued,. Hicon is a string that will be displayed on the task bar, and the SZTIP mouse is displayed on the icon.
int CMainFrame :: OnCreate (LPCREATESTRUCT lpCreateStruct) {NOTIFYICONDATA tnd; tnd.cbSize = sizeof (NOTIFYICONDATA); tnd.hWnd = this-> m_hWnd; tnd.uID = IDR_MAINFRAME; tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; tnd.uCallbackMessage = WM_MYMESSAGE; File: // User-defined message, ie the message TND.HICON = Loadicon (AFXGETITINSTANCEHANDLE), MakeintResource (iDR_mainframe); strcpy (TND.SZTIP, "Test Procedure"); // Icon prompt to "Test Program" shell_notifyicon (NIM_ADD, & TND); // Add icon to the taskbar} III to interact with the user's interaction, that is, when the user is on this icon Click or Double-click the left mouse button or right-click to perform the appropriate operation, at least in response to the will of the program terminate the program. It has been mentioned that when the user performs a mouse action on the icon, a custom message will be issued to the window specified in the HWND member, which is the WM_Myessage specified by the UCALLBACKMESSAGE, which is WM_USER 101 (how to customize the message) ,I will not say much). We have to achieve the task is to respond to custom messages in the HWND window: void cmainframe :: OnmyMessage (WPARAM WPARAM, LPARAM LPARAM) {uint uid; // The icon of the icon of the message is issued by the Icon ID UMOUSEMSG; // Mouse action Point Pt; UID = (uint) wParam; umousemsg = (uint) LParam; if (umousemsg == wm_rbuttondown) // If you are right-click {switch (uid) {copy {copyR_mainframe: // If it is our icon getCursorpos (& PT); / / Get the mouse location AFXGETAPP () -> m_pmainwnd-> showwindow (sw_shownormal); // Display Program Window Break; Default:}} Return;} 4. When the program is deleted, the program icon is deleted in the notice area. Icon, then call the shell_notifyicon function, only the first parameter is Nim_Delete indicating the delete icon: void cmainframe :: ~ cmainframe () {notifyicondata tnid; tnid.cbsize = sizeof (notifyicondata); tnid.hwnd = This-> m_hwnd; tnid.uid = idr_mainframe; // guarantees that our icon shell_notifyicon (nim_delete, & tnid);}
System tray programming 2002-11-3 15:48:18 vckbase.com Authors Not detailed: 1999 Windows 95 and later Windows version Allows you to put the program icon into the system tray. The so-called system tray, is usually referred to as the area of displaying time, volume, etc. display time, volume and other icons below the screen. This area is mainly used to display status information or when you are not visible, allowing you to easily access the main features of the program. This area can also be used to display the icon of the applet so that the user can easily access the main program or load the master program at a predetermined time. Some system tray icons can vary to indicate the status, for example, the browser's system tray icon shows different icons when MODEM receives and transmits data. Staying the mouse to the tray icon and stays. Stay often display a prompt, depending on the status of the program, it may also change. Right-click on the tray icon often display a program menu, and double-click the left mouse button often you can start the main window or application. The way to access the system tray is achieved by the shell_notifyicon function and the Notifyicondata structure. typedef struct _NOTIFYICONDATA {DWORD cbSize; HWND hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; HICON hIcon; TCHAR szTip [64]; DWORD dwState; // Version 5.0 DWORD dwStateMask; // Version 5.0 TCHAR szInfo [256]; // Version 5.0 Uint Utimeout; // Version 5.0 Tchar Szinfotitle [64]; // Version 5.0 DWORD DWINFOFLAGS; // Version 5.0} Notifyicondata, * PNOTICONDATA; In order to display icons in the system tray, use the NIM_ADD flag to call the shell_notifyicon function. #define ID_TASKBARICON 100 # define WM_ICONNOTIFY (WM_USER 101) // custom message NOTIFYICONDATA nid; // initialize the system tray icon nid.cbSize = sizeof (NOTIFYICONDATA); nid.hWnd = hWnd; nid.uID = ID_TASKBARICON; nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nid.uCallbackMessage = WM_ICONNOTIFY; nid.hIcon = LoadImage (hInst, MAKEINTRESOURCE (IDI_TRAY1), IMAGE_ICON, 16, 16, 0); strcpy (nid.szTip, "My Tooltip Text"); Shell_NotifyIcon ( NIM_ADD, & NID); CBSIZE membership is the size of the structure (using it mainly to support this structure size). HWND is the window handle. When an event occurs (such as click, double-click, etc.), Windows sends the message specified by the UcallbackMessage member to the window. UID member specifies the ID associated with the icon. It is not very important unless you need to display and track a few icons. Uflag members tell Windows Which member should be read. When adding an icon, most members of this structure should be included. When updating the icon, if you just want to change the icon, you can set the corresponding flag. HICON members are icons you want to show. Finally, the SZTIP member is a prompt text.
After setting these structural members, call the shell_notifyicon function. When the event associated with the icon occurs, Windows will send the message specified by the UcallbackMessage member. IParam contains messages sent. When a WM_LBUTTONDBLCLK message is obtained, the main window is displayed or the main program is started. The menu is displayed when a WM_RBUTTONUP message is obtained. Note: If you click the mouse button in the system tray, there is sometimes a pop-up (context menu) menu display / disappearance, detailed information, please refer to Microsoft Knowledge Base article Q135788, you can also refer to the following code to solve . switch (nMsg) {case WM_ICONNOTIFY: switch (lParam) {case WM_LBUTTONDBLCLK: // Load main window here break; case WM_RBUTTONUP: {POINT point; HMENU hMenu, hSubMenu; // Get mouse position GetCursorPos (& point); // Popup context menu hMenu = LoadMenu (hInst, MAKEINTRESOURCE (IDR_MYMENU)); hSubMenu = GetSubMenu (hMenu, 0); SetMenuDefaultItem (hSubMenu, IDM_DEFAULTCMD, FALSE); SetForegroundWindow (hMainDlg); // Per KB Article Q135788 TrackPopupMenu (hSubMenu, TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN, POINT.X, POINT.Y, 0, HWND, NULL); PostMessage (Hmaindlg, WM_NULL, 0, 0); // Per Kb Article Q135788 DestroyMenu (HMENU);} Break; Default: Return False;}} no matter When you can call Shell_Not with NIM_MODIFY Ifyicon. Before the program terminates, call shell_notifylic from the tray from the tray with NIM_DELETE. Shell_Notifyicon (Nim_Delete, & Nid);
Many software, for example: KV3000, etc., there is a small pallet icon after the tray area, which means that the program does not really stop and run in the background. When we click the mouse to make a maximization window on the desktop; if we click on the upper right corner of the program, or click the program to run on the file menu; the program is still running on the tray; only we right click The tray icon selects the exit in the menu that appears to really exit the program. Now we implement the above functions through a class CSystemtray and modify the system menu. Let's change the system menu first. 1. When we click on the mouse button on the title bar of the program, only a few items are shown. And through the MFC will also appear from ABOUT, we have given it it. We call the system menu to get the function getSystemMenu (), then call DeleteMenu () to remove the unnecessary system menu items, here we have dropped the separation line and "About" code below "Close" below: cmenu * psystemmenu = getSystemMenu (False); psystemmenu-> deleteMenu (8, mf_byposition); psystemmenu-> deleteMenu (7, mf_byposition); number of numbers 7 and 8 indicate seventh and 8 items of the system menu, pay attention to the separation line in VC One. (Here is the same as the method of modifying the system menu as before.). When we remove "about", we should also remove the corresponding corresponding code in the system command. We find the function onsysCommand (uint nid, lparam lparam) removed the code that intercepts the About dialog: IF ((NID & 0xFFF0) == idm_aboutbox) {Caboutdlg Dlgabout; dlgabout.domodal ();} It doesn't have any use of us, put it I can only give us a hassle here. Of course, if you don't remove it, there is no error in it. So why we have to get these two items because we are ready to achieve the same functionality in the tray. 1. We will change the function of the closure flag "X" of the program, change it to hide instead of completely closed. Let's take a closing command to change it to hide. IF ((NID & 0xFFF0) == SC_Close) {// onclose (); this is the close here to hide. AnimateWindow (getSafehWnd (), 1000, aw_hide | aw_blend; killtimer (0); showwindow (sw_hide); // The shutdown of the system menu is also changed to hidden. } Two sentences in front of ShowWindow (sw_hide) are to achieve a special effect, that is, slowly and gentle hidden, but only these two sentences should still be in front of Stdafx.h, the following two lines of code: # undef Winver #define Winver 0x500 2, let's create a tray menu, ID number is IDR_TUOPAN When we click right click on the pallet, there will be a menu, in the menu we have: About, display (hidden), change song, exit Four items. Let's define a message in the header file VioLetPlayDlg.h: #define wm_user_tray_notification (wm_user 0x101) Pay attention to its format. Define a tray variable in the file Csystemtray M_Trayicon, we can do a tray first after you have these. A tray is generated in the main file VioletPlayDlg.cpp.
We use the Creat () function as follows: m_trayicon.create (this, wm_user_tray_notification, "viiletplay", m_hicon, idr_tuopan); where the second parameter is our custom function, that is, the tray icon, the third parameter is when we The description text appears when the mouse is placed on the icon, and the fifth parameter is the menu that appears when we click the right button. ) When our mouse leaves the icon, the text ViOLETPLAY will automatically disappear, and we are implemented by a conditional statement. First we define a BOOL variable BOOL Start_minimized us to determine its value: if (start_minimized) Postmessage (WM_Close); send a close command when our mouse is moved, close the window. When we add a code when the code is running in the file violetplay.cpp, we can display it in the tray and display on the tray: dlg.start_minimized = getprofileint (_t (""), _ t ("startminimized"), false) We add this code before the dialog where the main program is displayed, and play a "interception" role. In this way, we have achieved the initial function, that is, an icon appears in the tray, but this is still not enough, we are here to implement other features. 3, although we have a tray menu, but we can't have the right mock now to make it, because our programs still can't respond to this message, below we pass overloaded functions: AFX_MSG Long OntrayNotification (WPARAM WPARAM, LPARAM LPARAM and add response code to implement this function. We use the Switch ... case ... structure to respond to the right click of the message, of course, if you are willing to use the IF statement to achieve the same functionality. The code is as follows: long cvioletplaydlg :: ontraynotification (wparam wparam, lparam lparam) {switch (lparam) {copy wm_rbuttondown: {// User Right-click on the tray icon and pops up the context menu Hide / Display dialog.
CMenu Omenu; IF (omenu.loadmenu) {cmenu * ppopup = omenu.getsubmenu (0); assert (ppopup! = Null); cpoint opoint; if (iswindowVisible ()) // According to the display / file of the dialog window / Hidden Status Modify Menu Name Omenu.ModifyMenu (IDC_SHOW, MF_STRING, IDC_SHOW, "Hide (& H)"); else Omenu.ModifyMenu (IDC_SHOW, MF_STRING, IDC_SHOW, "Display (& S)"); // Determine the position of the mouse to Near the location of the menu getCursorpos (& opoint); setForegroundWindow (); ppopup-> TRACKPOPMENU (TPM_LEFTALIGN | TPM_RightButton, Opoint.x, Opoint.y, this);}} Break; // Click / Double click the left mouse left mouse button Box Case WM_LBUTTONDBLCLK: Case WM_LButtondown: OnShow (); Break;} Return 0;} We simultaneously implement dynamic changing menu "Show / Hide" function, when the program main interface appears, the menu is hidden "Indicates that if we click on it, the program main interface is hidden. If the menu is changed to "Display" indicates that the program main interface can be displayed when we click on it. In addition, the last three sentences of the above code indicates that there is a main program interface, which is the same as the command that we send or double-click the left mouse button. We are analyzed by a command in the tray menu. Here we make the program true exit, so it accepts commands: postquitmessage (0), make the program truly exit, pay attention to us, other two "exit" are hidden. Because the user can do not know this, we need to design a dialog here to remind, if we ask for this, we will change the command sent by clicking the "Exit" menu to call an AfxMessageBox, when using Click "Yes" to realize the real exit. Click "NO" without exiting. The code is as follows: void cvioletplaydlg :: onClose () {if (AFXMESSAGEBOX ("Really Exit", MB_YESNO) == iDYES) {AnimateWindow (getsafehwnd (), 1000, aw_hide | aw_blend); killtimer (0); :: PostquitMessage (0);}} When you click on the exit in the file menu, the same thing is just when you click "Yes", you can only hide the main interface, and when you click "No", you cannot hide the main interface. We only need to change the exit command in the above code :: PostquitMessage (0) to hide the command showWindow (sw_hide). We now realize all the features of the tray icon. Note: Class CSystemtray inherits to CWND is public form, the class definition and implementation can be referred to the file: ViOLETPLAY, the file name is SYSTEMTRAY.H and SystemTray.cpp source files See: ViOLETPLAY (Note, there are some code for vckbase website I only analyze and summarize it. I will express my gratitude and apologize.
Some netizens have developed their own tray and achieved slightly cumbersome. Here I recommend a simple and very effective tray class (I am in a book). 1. Copy Trayicon.cpp and Trayicon.cpp to your project directory and add it to the project. 2, add #include "trayicon.h" 3 in Demodlg.h, add member variables CTRAYICON M_CTRAYICON; 4, create menu resources, to create a menu resource, make it IDR_DEMO, Design menu:
Add event handlers to Demo1 and Exit:
Void cdemodlg :: onfiledemo1 () {showwindow (sw_show); m_trayicon.removeicon ();} void cdemodlg :: onfileexit () {m_trayicon.removeicon (); oncancel ();} 5, custom message in DEMODLG.CPP Define WM_ICON_NOTIFY WM_USER 10, and declares message processing function at declarative message: begin_Message_Map (CDEMODLG, CDIALOG) ... ON_MESSAGE (WM_ICON_NOTIFY, ONTRAYNOTIFICATION) ... End_Message_Map ()
CDemoDlg increase the class member functions: LRESULT OnTrayNotification (WPARAM wParam, LPARAM lParam); Part achieved: LRESULT CDemoDlg :: OnTrayNotification (WPARAM wParam, LPARAM lParam) {return m_TrayIcon.OnTrayNotification (wParam, lParam);}
6. Add "Start" button to the dialog and double-click the "Start" button editing handler:
Void cdemodlg :: OnbnclickedButton1 () {m_trayicon.create (this, wm_ICON_NOTIFY, "Mouse pointing", m_hicon, idr_demo); // Construct ShowWindow (SW_HIDE); // Hide Window}
7, you can flexibly use other class member functions. Such as: Seticon changes the icon, you can implement the tray icon animation effect through the Timer message. 8, delete the tray icon: m_trayicon.removeicon ();