Using Visual C ++ to implement system tray programs

xiaoxiao2021-04-08  321

Since Microsoft launched

Since the Windows 95 operating system, the system tray application is a very attractive user interface.

Designed is deeply loved by users. Use the system tray as the number of Windows applications in the user interface, such as "Jinshan Word", "Winamp", "RealPlayer", etc.

These programs do not display the run window when running, only displaying an icon on the taskbar, indicating that the program is running, the user can interact with the application,

Program developers sometimes need similar programs that are running only in the background, in order not to interfere with the running interface of the foreground program and the unnecessary window, it 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. This example is introduced

Visual C develops such a programming method, after the program is compiled, if you double-click the tray icon, the program pops up a message list window, as long as the mouse moves or click on the tray icon (whether ordered left or double click on the left), The generated message will be displayed in this window; when the mouse light is shifted onto the tray icon, the prompt information is displayed near the icon; when the right button is pop-up, the context menu is pop-up, this menu should include the command to open the properties page or open and icon Commands of related other windows, in addition, the program can also dynamically change the icon of the tray. Referring to this example, I believe that the reader can easily apply a system tray in their own procedure.

First, implementation method

In order to implement the traile disc, first make the program's main window is not visible, this is very easy, as long as ShowWindow (sw_hide) is, this instance is this method, and there is a way to set it by setting The style and extension style of the main border window hide the main frame:

BOOL CMainFrame :: PreCreateWindow (CREATESTRUCT & cs) {cs.style = WS_POPUP; // main window is not visible; cs.dwExStyle | = WS_EX_TOOLWINDOW; // do not display task buttons; return CFrameWnd :: PreCreateWindow (cs);}

The display icon on the task bar is 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:

Bool Shell_Notifyicon (DWORD DWMESSAGE, PNOTICONDATA PNID);

The first parameter dWMessage type of the function is DWORD, indicating the action to be performed, it can be one of the following values:

NIM_ADD: Add an icon to the taskbar.

NIM_MODIFY: Modify the icon of the status bar area.

NIM_DELETE: Delete icons for the status bar area.

NIM_SETFOCUS: Return the focus to the taskbar notification area. When the user interface operation is completed, the taskbar icon must use this message. For example, if the taskbar icon is displayed on the context menu, but the user presses the "ESCAPE" button to cancel the operation. At this time, you must use this message to return the focus to the taskbar notification area.

NIM_SETVERSION: Indicates the taskbar to work according to the corresponding dynamic library version.

The second parameter PNID is the address of the Notifyicondata structure, which is determined by the value of DWMessage. This structure is defined in the shellapi.h file as follows:

TypedEf struct _notifyicondata {dword cbsize; // Structural Size (SIZEOF STRUCT), you must set the HWND HWND; // Send the window handle of the notification message; // icon ID (specified by the callback function) uint uflags; uint ucallbackMessage; // The message is sent to this window process Hicon Hicon; // taskbar icon handle char sztip [64]; // Tips text} notifyicondata; the value of uflags in this structure is:

#define nif_message 0x1 // Indicates UcallbackMessage valid #define nif_icon 0x2 // indicates that HICON valid #define nif_tip 0x4 // indicates that SZTIP is valid

In a member of this structure, CBSIZE is the number of bytes of this structure, and hWnd is a handle of the window that accepts the message issued by the icon (the mouse will make a message when the icon is on the taskbar icon, this message user To define itself), the UID is the ID of the displayed icon, UFlags indicates whether the value of the remaining members (Hicon, UcallbackMessage, and Sztip) is valid, uCallbackMessage is a user-defined message, when the user acts on the icon Some mouse When the action, the icon will issue this message to the application's main frame window (window specified in the HWND member), in order to make the main frame of the program get the notification message, you need to set the value of the FLAG member of the Notifyicondata structure to Nif_Message. Hicon is a prompt string that will be displayed when the SZTIP mouse is displayed on the icon on the icon handle on the taskbar. Although the shell_notifyicon function is simple and practical, it is a Win32 API. In this instance, it is packaged in a C class. This class is called CTRAYICON, with it, the tray programming will be more relaxing, because it hides Notifyicondata, Messages Codes, logos, and some cumbersome details. Second, programming step 1. Start Visual C 6.0, generate a single document application TRAYTEST, cancel the document view support; 2, add custom message to the CMAINFRAME class #define WM_MY_TRAY_NOTIFICTION WM_USER 0, and in this class This custom message manually adds a message map ON_MESSAGE (WM_MY_TRAY_NOTIFICATION, ONTRAYNOTIFICATION), and message response function AFX_MSG LRESULT ONTRAYNOTIFICATION (WPARAM WP, LPARAM LP); 3, the design two icons are added to the project, and its ID flag is "idi_myicon", " IDi_myicon2 ", as the icon when the tray is displayed; 4, add the following variables in the CMAINFRAME class: CTRAYICON M_TRAYICON (used to operate the icon class object), CEDIT M_WNDIT (edit box is used to display the tracking mouse message), int M_iWhichicon (which icon to determine the current tray), BOOL M_BSHUTDOWN (Whether the current tray program flag), BOOL M_BSHOWTRAYNOTIFICATIONS (Whether the tray message flag is displayed); 5, add the context menu IDI_TRAYICON for the program for the program IDR_MAINFRAME The title and ID flag of the menu item see the code section), then add a process function to each menu item using Class Wizard; 6, add code, compile the running program.

CTrayIcon class header file; #ifndef _TRAYICON_H # define _TRAYICON_Hclass CTrayIcon: public CCmdTarget {protected: DECLARE_DYNAMIC (CTrayIcon) NOTIFYICONDATA m_nid; // struct for Shell_NotifyIcon args public: CTrayIcon (UINT uID); ~ CTrayIcon (); // Call this to receive tray notifications void SetNotificationWnd (CWnd * pNotifyWnd, UINT uCbMsg); BOOL SetIcon (UINT uID); // main variant you want to use BOOL SetIcon (HICON hicon, LPCSTR lpTip); BOOL SetIcon (LPCTSTR lpResName, LPCSTR lpTip) {return SetIcon (lpResName AfxGetApp () -> LoadIcon (lpResName):? NULL, lpTip);} BOOL SetStandardIcon (LPCTSTR lpszIconName, LPCSTR lpTip) {return SetIcon (:: LoadIcon (NULL, lpszIconName), lpTip);} virtual LRESULT OnTrayNotification ( WPARAM UID, LPARAM LEVENT);}; # Endif /// CTRAYICON class .CPP file #include "stdafx.h" #include "trivon.h" #include // for AFXLOADSTRINGIMPLEMENT_DYNAMIC (CTRAYICON, CCMDTARGET) CTRAYICON :: CTRAYICON (UINT UID) {MEMSET (& M_NID, 0, SIZEOF (M_NID)); // Initialize Notifyicondata M_NID.cb Size = sizeof (m_nid); m_nid.uID = uID; // never changes after construction AfxLoadString (uID, m_nid.szTip, sizeof (m_nid.szTip)); // Use resource string as tip if there is one} CTrayIcon :: .. ~ CTrayIcon () {SetIcon (0); // remove icon from system tray} void CTrayIcon :: SetNotificationWnd (CWnd * pNotifyWnd, UINT uCbMsg) {// Set notification window It must created already ASSERT (pNotifyWnd == NULL | | :: IsWindow (pNotifyWnd-> GetSafeHwnd ())); m_nid.hWnd = pNotifyWnd-> GetSafeHwnd (); ASSERT (uCbMsg == 0 || uCbMsg> = WM_USER); m_nid.uCallbackMessage = uCbMsg;} BOOL CTrayIcon :: Seticon (UINT UID) {// sets Both the icon and tooltip resource id,

To remove the icon, call seticon (0) hicon hicon = null; if (uid) {AFXLOADSTRING (UID, m_nid.sztip, sizeof (m_nid.sztip)); hicon = AFXGetApp () -> loadicon (UID);} return Seticon (Hicon, Null);} Bool CTRAYICON :: Seticon (Hicon Hicon, LPCSTR LPTIP) {// Common Seticon for All Overloads. Uint msg; m_nid.uflags = 0; if (hicon) {// set the icon msg = m_nid.hicon? NIM_MODIFY: NIM_ADD; m_nid.hicon = hic; // add or replace icon in system tray m_nid.uflags | = nif_icon;} else {if (m_nid.hicon == null) // remove icon from travel return true ; // already deleted msg = nim_delete;} if (lptip) // use the TIP, IF ANY STRNCPY (M_NID.SZTIP, LPTIP, SIZEOF (M_NID.SZTIP)); if (m_nid.sztip [0]) m_nid.uflags | = NIF_TIP; if (m_nid.uCallbackMessage && m_nid.hWnd) // Use callback if any m_nid.uFlags | = NIF_MESSAGE; BOOL bRet = Shell_NotifyIcon (msg, & m_nid); // Do it if (msg == NIM_DELETE ||! Bret) m_nid.hicon = null; // failed return bret;} LRESULT CTRAYICON :: OntrayNotification (WPARAM WID, LPARAM LEVENT) {i f (Wid! = m_nid.uid || (Levent! = WM_RBUTTONUP && Levent! = WM_LButtondBLCLK) Return 0; cmenu Menu; // Load the context menu; if (! menu.loadmenu (m_nid.uid)) Return 0; cmenu * psubmenu = menu.getsubmenu (0); if (! psubmenu) return 0; if (levent == wm_rbuttonup) {// Set the first menu item as the default menu item :: setmenudefaultItem (psubmenu-> m_hmenu, 0, true ); // use the current menu as a context menu; cpoint mouse; getCursorpos (& mouse); :: setForegroundWindow (m_nid.hwnd); :: TrackPopupmenu (psubmenu-> m_hmenu, 0, mouse.x, mouse.y, 0, m_nid .hwnd, null);} else // Double Click: Execute First Menu Item :: SendMessage (m_nid.hwnd, wm_command, psubmenu-> getmenuitemid (0), 0); Return 1;

} / MainFrm.h: interface of the CMainFrame class # if defined (AFX_MAINFRM_H__9ED70A69_C975_4F20_9D4E_B2877E3575D0__INCLUDED _) # define AFX_MAINFRM_H__9ED70A69_C975_4F20_9D4E_B2877E3575D0__INCLUDED_ # if _MSC_VER> 1000 # pragma once # endif // _MSC_VER> 1000 # include "trayicon.h" class CMainFrame:! Public CFrameWnd {public : CMainFrame (); protected: DECLARE_DYNAMIC (CMainFrame) // Attributes public: // Overrides // ClassWizard generated virtual function overrides // {{AFX_VIRTUAL (CMainFrame) //}} AFX_VIRTUAL // Implementation public: virtual ~ CMainFrame (); #ifdef _DEBUG virtual void AssertValid () const; virtual void Dump (CDumpContext & dc) const; #endif protected: // control bar embedded members CStatusBar m_wndStatusBar; CTrayIcon m_trayIcon; // my tray icon CEdit m_wndEdit; // to display tray notifications int M_iwhichicon; // Which Hicon to use book m_bshutdown; // ok to terminate traytest bool m_bshowtraynotifications; // display info in main window // generated message map functions protected: // {{AFX_MSG (CMainFrame) afx_msg LRESULT OnTrayNotification (WPARAM wp, LPARAM lp); afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); afx_msg void OnToggleIcon (); afx_msg void OnViewClear (); afx_msg void OnViewNotifications (); afx_msg void OnUpdateViewClear (CCmdUI * pCmdUI); afx_msg void OnUpdateViewNotifications (CCmdUI * pCmdUI); afx_msg void OnClose (); afx_msg void OnAppOpen (); afx_msg void OnAppSuspend (); // NOTE - the ClassWizard will add and remove member functions here //. Do Not Edit What You See In There Blocks of Generated Code! //}} AFX_MSG DECLARE_MESSAGE_MAP ()}; /// CMAINFRM.CPP # include "stdafx.h" #include "traytest.h" #include "mainfrm.h"

#ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILEstatic char THIS_FILE [] = __FILE __; # endif /// CMainFrame // Message ID used for tray notifications # define WM_MY_TRAY_NOTIFICATION WM_USER 0IMPLEMENT_DYNAMIC (CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd) // {{AFX_MSG_MAP (CMainFrame) // NOTE -. the ClassWizard will add and remove mapping macros here // DO NOT EDIT what you see in these blocks of generated code ON_MESSAGE (WM_MY_TRAY_NOTIFICATION, OnTrayNotification) ON_WM_CREATE () ON_COMMAND (ID_VIEW_CLEAR, OnViewClear)! ON_COMMAND (ID_TOGGLE_ICON, OnToggleIcon) ON_COMMAND (ID_VIEW_NOTIFICATIONS, OnViewNotifications) ON_UPDATE_COMMAND_UI (ID_VIEW_CLEAR, OnUpdateViewClear) ON_UPDATE_COMMAND_UI (ID_VIEW_NOTIFICATIONS, OnUpdateViewNotifications) ON_WM_CLOSE () ON_COMMAND (ID_APP_OPEN, OnAppOpen) ON_COMMAND (ID_APP_SUSPEND, OnAppSuspend) //}} AFX_MSG_MAPEND_MESSAGE_MAP () static UINT indicators [ ] = {Id_separator, // status line indeicator id_indicator_caps, id_indicator_num, id_indicator_scrl ,}; /// CMainFrame construction / destructionCMainFrame :: CMainFrame (): m_trayIcon (IDR_TRAYICON) {// TODO: add member initialization code here m_bShowTrayNotifications = TRUE; // zxn m_bShutdown = FALSE; // zxn} CMainFrame :: ~ CMainFrame () {} int CMainFrame :: OnCreate (lPCREATESTRUCT lpCreateStruct) {if (CFrameWnd :: OnCreate (lpCreateStruct) == -1) return -1;! if (m_wndStatusBar.Create (this) || m_wndStatusBar.SetIndicators (indicators,! SIZEOF (INDICATORS) / SIZEOF (UINT))) {trace0 ("Failed to Create Status Bar / N); Return -1; // Fail to Create} // Create Child Edit Control for Displaying Messages CRECT RC;

if return -1 (m_wndEdit.Create (WS_VISIBLE | WS_CHILD | WS_VSCROLL | | ES_MULTILINE ES_READONLY, rc, this, AFX_IDW_PANE_FIRST)!); // Set up tray icon m_trayIcon.SetNotificationWnd (this, WM_MY_TRAY_NOTIFICATION); m_iWhichIcon = 1; m_trayIcon.SetIcon (IDI_MYICON); return 0;} //// Close window Unless we are shutting down, just hide it.void CMainFrame :: OnClose () {if (m_bShutdown) CFrameWnd :: OnClose ();. else ShowWindow (SW_HIDE); } Handle notification from tray icon: display a message.LRESULT CMainFrame :: OnTrayNotification (WPARAM uID, LPARAM lEvent) {if (m_bShowTrayNotifications) {static LPCSTR MouseMessages [] = { "WM_MOUSEMOVE", "WM_LBUTTONDOWN", "WM_LBUTTONUP", "WM_LBUTTONDBLCLK "" WM_RBUTTONDOWN "," WM_RBUTTONUP "," WM_MBUTTONDOWN "," WM_MBUTTONUP "," WM_MBUTTONUP "," WM_MBUTTONDBLCLK "}; cstring s; S.Format (" Tray Notification Message: ID =% D, Levent = 0x% 04x% S / R / N ", UID, LEVENT, WM_MOUSEFIRST <= Levent && Levent <= WM_MOUSELAST? MouseMesses [Levent-WM_Mousefirst]:" Unknown Message) "); M_Wndedit.Setsel (-1 , -1); // end of edit text m_wndit.replasel (s); // append string .. m_wndedit.sendMessage (em_scrollcaret); // ..and make visible} // let Tray Icon Do Default Stuff Return M_Trayicon. OnTrayNotification (uID, lEvent);} // Command handlers below.//void CMainFrame :: OnViewClear () {m_wndEdit.SetWindowText ( "");} void CMainFrame :: OnUpdateViewClear (CCmdUI * pCmdUI) {pCmdUI-> Enable (m_wndEdit .GetLineCount ()> 1 || m_wndedit.LineLength ()> 0);} void cmainframe :: Ontoggleicon () {m_iwhichicon =! M_iwhichicon; m_trayicon.seticon (m_iwhichicon? Idi_myicon: idi_myicon2);

!} Void CMainFrame :: OnViewNotifications () {m_bShowTrayNotifications = m_bShowTrayNotifications;} void CMainFrame :: OnUpdateViewNotifications (CCmdUI * pCmdUI) {pCmdUI-> SetCheck (m_bShowTrayNotifications);} void CMainFrame :: OnAppOpen () {ShowWindow (SW_NORMAL); SetForegroundWindow ( );} void CMainFrame :: OnAppSuspend () {m_bShutdown = TRUE; // really exit SendMessage (WM_CLOSE);} /// CMainFrame diagnostics # ifdef _DEBUGvoid CMainFrame :: AssertValid () const {CFrameWnd :: AssertValid ();} void CMAINFRAME :: DUMP (CDumpContext & DC) const {cframeWnd :: dump (dc);} # endif // _ debug /// Bool CMYAPP :: InitInstance () {// Hide the program's main frame in the application initial function ; #ifdef _AFXDLL Enable3dControls (); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic (); // Call this when linking to MFC statically #endif SetRegistryKey (_T ( "Local AppWizard-Generated Applications")); CMAINFRAME * PFRAME = New CMAINFRAME; M_PMAINWND = Pframe; Pframe-> LoadFrame (idR_mainframe, ws_overlappedwindow | fws_addtotitle, null, null); pframe-> showwind OW (sw_hide); pframe-> UpdateWindow (); return true;} four, small knot

The information prompt for the tray program is usually the mouse light to the pallet icon,

Windows will send a message to the tray program to display the prompt information --Tooltip. In

In Windows XP, we also see that some system tray programs are automatically displayed Tooltips information, that is, do not need to move the mouse light to the tray icon, you can display Tooltips, this new information prompt is generally called a balloon prompt, it is Your program controls the display. The balloon prompts for the tray program to provide a non-blown method to inform the user that something has occurred. But how to make the balloon prompt display? In fact, all pallet icons are operated by a simple API function shell_notifyicon. You can use this function of the parameters NOTIFYICONDATA structure, this structure tells Windows what you want to do. Here is the latest version of this structure (for IE5.0 ), which has been added to the new member:

typedef struct _NOTIFYICONDATA {DWORD cbSize; HWND hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; HICON hIcon; #if (_WIN32_IE <0x0500) WCHAR szTip [64]; #else WCHAR szTip [128]; #endif #if (_WIN32_IE> = 0x0500) DWORD dwState; DWORD dwStateMask; WCHAR szInfo [256]; union {UINT uTimeout; UINT uVersion;} DUMMYUNIONNAME; WCHAR szInfoTitle [64]; DWORD dwInfoFlags; #endif} NOTIFYICONDATA, * PNOTIFYICONDATA; flag in the NOTIFYICONDATA.uFlags One is Nif_tip, with it to set the traditional information prompt, the mouse is to be moved to the icon. New flag Nif_info (due to _Win32_ie> = 0x0500 Category Definition, please note that the latest version of the header file shellapi.h is included, and guarantee the latest version of the library file shell32.lib, with the latest version when distributing the program The running dynamic link library shell32.dll) is used for displaying the balloon prompt. That is, to display the balloon prompt, then the NIF_INFO flag must be used when calling the shell_notifyicon function. The prompt text fills in the Szinfo domain, and the title text fills in Szinfotitle. You can even set a timeout in the Notifyicondata.utimeout, after the specified milliseconds, the balloon prompts automatically hide.

转载请注明原文地址:https://www.9cbs.com/read-132791.html

New Post(0)