Yu Junjun, Zhang Yi, Xi'an Second Artillery Engineering College
Summary
This article introduces how to add the application icon to the Windows system tray in detail,
Then a C ++ class is provided to conveniently implement this function, and an application is provided in VC ++ 6.0.
Instance to reflect its specific implementation process. At the same time, the application instance also explains how to implement the dynamic
Draw icons and disable computer technology in programs.
Keywords: System Tray animation icon
The system tray of Windows 98 desktop is located at the right of the taskbar, that is, the bottom right of Windows 98 desktop. It often
Displays the status of some systems. For example, system time, volume control, and other icons
Software installed on human machines, for example, Windows 98 system tray. (Figure omitted)
It is often seen that some excellent software will add its application icon to the system tray after running, such
Kingsoft. If you can add your own application icons to the system tray
The program looks very professional.
In fact, this is not difficult. There is only one function for communicating with the system tray:
Shell_policyicon (uint message, policyicondata & m_nid );
First, let's take a look at the two parameters of the function.
The first parameter message can take the following values:
Nim_add adds an icon to the tray;
Nim_modify modify the icon in the tray
Nim_delete delete an icon from the tray
The second parameter m_nid is a reference to the policyicondata structure. The structure is prototype as follows:
Typedef struct _ policyicondata
{
DWORD cbsize; // the size of the structure, which must be given in the program
Hwnd;
// Is the window handle for receiving messages from pallets in your program
Uint uid;
// The ID of the tray icon defined in the application. This parameter is used as an identifier.
Uint uflags;
// Set the attribute. the lower three digits make sense, 0--7, as shown below:
// First // # define nif_message 0x1
// The ucallbackmessage parameter is valid.
// Second digit // # define nif_icon 0x2 // The hicon parameter is valid.
// The Third digit // # define nif_tip 0x4 // The sztip parameter is valid.
Uint ucallbackmessage;
// Custom message id value, which must not be duplicated with some message IDs.
Hicon;
// The icon handle displayed on the system tray, which can be the idi_winlogo of the system.
Char sztip [64]; // The prompt string used for icon display
} Policyicondata;
To receive notification messages from pallets, you can set ucallbackmessage as the message you define.
ID value, and set the nif_message flag. In this way, when the user moves or presses the mouse on your tray icon
Windows sends a message: the messageid of the message is defined in ucallbackmessage.
Value; wparam is your defined uid value; lparam is a mouse event (such as wm_lbuttondown), So you
The application will be able to respond to the event.
Therefore, in order to add your application to the system tray, you must first create a processing tray notification message
And then associate the window object with your own tray notification message and create the corresponding Tray
Notification Message ing mechanism, so that your window objects can process corresponding events.
We can see that in policyicondata, the member variables hwnd, uid, and uflags are used in the window
Like establishing a connection with your own tray notification message, while the member variable ucallbackmessage must be
The ID of the notification message corresponding to the tray of your window object.
The work to be completed is:
(1) create a window object for processing notification messages on pallets;
(2) create a struct policyicondata variable, and assign values to the corresponding fields of the variable to notify the cancellation in the tray.
And the window object;
(3) establish the corresponding tray notification message ing mechanism;
(4) Call the shell_policyicon function to add, modify, or delete icons in the system tray;
(5) Of course, do not forget to write the corresponding Event Response Function in your window object.
Therefore, you can write a C ++ class to implement the above functions to simplify programming and improve code reusability. To
Code for this class:
Class ctrayicon: Public c0000target {
Protected:
Declare_dynamic (ctrayicon)
Notifyicondata m_nid;
// Structure parameters in the shell_policyicon Function
Public:
Ctrayicon (uint UID );
~ Ctrayicon ();
// Call the member function to receive notification messages from the tray.
Void setnotificationwnd (cwnd * pnotifywnd,
Uint ucbmsg );
// Seticon is used to add, change, and delete icons in the system tray.
// Call the delete icon as follows: seticon (0)
Bool seticon (uint UID );
Bool seticon (hicon, lpcstr lptip );
Bool seticon (maid, lptip)
{
Return seticon (lpresname?
Afxgetapp ()-> loadicon (lpresname): NULL, lptip );
}
Bool setstandardicon (maid, lptip)
{
Return seticon (: loadicon (null, lpsziconname), lptip );
}
Virtual lresult ontraynotification (wparam uid, lparam Levent );
};
Ctrayicon: ctrayicon (uint UID)
{
// Initialize the policyicondata Structure Variable
Memset (& m_nid, 0, sizeof (m_nid ));
M_nid.cbsize = sizeof (m_nid );
M_nid.uid = uid;
Afxloadstring (UID, m_nid.sztip, sizeof
(M_nid.sztip ));
}
Ctrayicon ::~ Ctrayicon ()
{
Seticon (0); // Delete the icon from the system tray
}
// Set the notification window, which must have been created
Void ctrayicon: setnotificationwnd (cwnd * pnotifywnd, uint ucbmsg)
{
Assert (ppolicywnd = NULL |: iswindow (ppolicywnd-> getsafehwnd ()));
M_nid.hwnd = ppolicywnd-> getsafehwnd ();
Assert (ucbmsg = 0 | ucbmsg> = wm_user );
M_nid.ucallbackmessage = ucbmsg;
}
Bool ctrayicon: seticon (uint UID)
{
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, lpcstr lptip)
{
Uint MSG;
M_nid.uflags = 0;
// Set the icon
If (hicon ){
// Determine whether to add or delete the icon in the system tray
MSG = m_nid.hicon? Nim_modify: nim_add;
M_nid.hicon = hicon;
M_nid.uflags | = nif_icon;
} Else {// Delete the icon
If (m_nid.hicon = NULL)
Return true; // deleted
MSG = nim_delete;
}
If (lptip)
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)
M_nid.uflags | = nif_message;
Bool Bret = shell_policyicon (MSG, & m_nid );
If (MSG = nim_delete |! Bret)
M_nid.hicon = NULL;
Return Bret;
}
// Default event handler, which handles the right-click and double-click events.
Lresult ctrayicon: ontraynotification (wparam WID,
Lparam Levent)
{
If (WID! = M_nid.uid |
(Levent! = Wm_rbuttonup & Levent! = Wm_lbuttondblclk ))
Return 0;
// Use a menu with the same ID as the tray icon as a shortcut menu
// Use the first item in the menu as the default command,
// The default command is sent when the wm_lbuttondblclk event occurs.
//
Cmenu 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 item of the menu to the default item (shown in bold)
: Setmenudefaultitem (psubmenu-> m_hmenu, 0, true );
// The menu is displayed at the current position of the mouse.
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 the event: the first item in the execution menu
: Sendmessage (m_nid.hwnd, wm_command, psubmenu->
Getmenuitemid (0), 0 );
Return 1; // indicates that the event has been processed
}
The following uses the specific program implemented in VC ++ 6.0 as an example. The program will have the following features: The program is executed
Then, a dialog box is displayed, indicating that the program starts to run and the dialog box disappears. Next, the program icon
Added to the system tray, you can see that this icon will be an animation icon. When you place the cursor in this system
When you right-click the disk, a menu is displayed. (Omitted ). The first item is the default command. Click
The application is displayed. To simplify programming, the application only displays an application main window. Click
The second item in the menu closes the machine, and the third item in the menu ends the program. When a user double-clicks,
Ctrayicon will execute the first item on the menu: display the service program, which will hit the live (Display) traydemo
(Normally, it is hidden ). To terminate the traydemo, you must end the program. When you
When you execute file exit or disable the main traydemo window, traydemo does not actually close,
It is hidden. Traydemo reloads the cmainframe: onclose function to execute this function.
First, generate a single document project traydemo in VC ++ 6.0 using the Application Wizard, and then in the project
Add the ctrayicon class above.
To use the ctrayicon class, you must first instantiate a ctrayicon class object. The traydemo is in the view.
Complete this task. The following code is used:
Class ctraydemoview: Public cview {
Protected: ctrayicon m_trayicon;
// My tray icon
.
.
.
};
After you instantiate a ctrayicon class object, you must assign it an ID number. The ID number is shown in this figure.
The only ID used in the lifecycle, even if you change the actual display icon in the future. This
ID is the ID you obtain when a mouse event occurs. It does not need to be the resource ID of the icon; In traydemo
The value is idr_trayicon, Which is initialized by the ctraydemoview constructor.
Ctraydemoview: ctraydemoview ():
M_trayicon (idr_trayicon ){
.
.
.
}
To add an icon, you can call seticon to reload one of the functions.
M_trayicon.seticon (idi_myicon); // The parameter is the resource ID.
M_trayicon.seticon ("myicon"); // The parameter is the resource name.
M_trayicon.seticon (hicon); // The parameter is the hicon handle.
M_trayicon.setstandardicon (idi_winlogo );
// Add the System icon
Except for the seticon (uint UID) function, a string resource with the same uid ID is required as the prompt string.
All these functions have an optional parameter pointing to the prompt string. For example
Traytest contains the following lines:
// (In traydemoview. cpp)
M_trayicon.seticon (idi_red );
This statement also sets the prompt string when adding an icon, because traydemo has a word with the same ID
String: If you want to change the icon, you only need to call one of the seticon functions again.
The same ID or hicon. The ctrayicon class knows to respond to the nim_modify message instead of the nim_add message. Similarly
You can even remove the icon from the function:
M_trayicon.seticon (0); // removeicon
The ctrayicon class interprets it as a nim_delete event. So many codes and logos use only one simple
This is the greatness of C ++.
To display the animation icon, you only need to set a timer and call it in the timer RESPONSE event.
You can use the seticon member function. For example:
Int ctraydemoview: oncreate (maid)
{
M_timerid = This-> settimer (99,200, null );
...
}
Void ctraydemoview: ontimer (uint nidevent)
{
Uchangeicon ++;
If (uChangeIcon-IDI_RED> 2)
Uchangeicon = idi_red;
M_trayicon.seticon (uchangeicon );
Cview: ontimer (nidevent );
}
In the example program, there are three icons with the ID idi_red, idi_yello, idi_green, and their ID value is
Therefore, the uint variable uchangeicon is used to rotate three icons in sequence. After this program is executed, you
The red, yellow, and green traffic lights are flashing in turn.
So how to handle the tray notification?
To process the tray notification, call the ctrayicon: setnotificationwnd function before setting the icon.
Of course, you must have created a window. In the oncreate function
This is also the case. Use classwizard to add the wm_create message response letter to the ctraydemoview class
And add the following code:
// Private message used for tray configurications
# Define wm_my_tray_notification wm_user + 0
Int ctraydemoview: oncreate (maid)
.
.
.
M_trayicon.setnotificationwnd (this, wm_my_tray_notification );
M_trayicon.seticon (idi_red );
Return 0;
}
Then register the message (register). After registration, you can use the normal message ing method.
Handle tray notifications.
Begin_message_map (cmainframe, cframewnd)
On_message (wm_my_tray_notification, ontraynotification)
// (Or on_registered_message)
End_message_map ()
Of course, do not forget to add the following statement to traydemoview. h:
Afx_msg lresult ontraynotification (wparam WP, lparam LP );
After your handler gets control of the mouse event on the tray icon, The wparam parameter is
The ID defined when the ctrayicon class is used; lparam is a mouse event (for example, wm_lbuttondown ). When
After the notification, you can do anything you want. Remember to call
Ctrayicon: ontraynotification function to complete some default processing. This virtual function is completed before
Some cylinder UI behaviors mentioned. Specifically, it handles wm_lbuttondblclk and WM-RBUTTONUP
. The ctrayicon class looks for menus with the same ID as the icon (for example, idr_trayicon ). If you have
This ID menu exists. The ctrayicon class displays this menu when you right-click the icon.
When you click, ctrayicon will execute the first command on the menu.
Lresult ctraydemoview: ontraynotification (wparam WP, lparam LP)
{
Return m_trayicon.ontraynotification (WP, LP );
}
There are only two things that need further explanation. Before the menu is displayed, the ctrayicon class makes the first item a tank saving item,
Therefore, it looks capitalized. But how to make a menu item capitalized? Use Functions
Gsetmenudefaultitem.
// Make first menu item the default (bold font)
: Setmenudefaultitem (psubmenu-> m_hmenu, 0, true );
0 specifies the first menu item. True indicates that the menu item is determined by position rather than ID.
For ctrayicon: ontraynotification, the second item we care about is to display the relevant menu.
What?
: Setforegroundwindow (m_nid.hwnd );
: Trackpopupmenu (psubmenu-> m_hmenu ,...);
To make the trackpopupmenu function work normally in the tray environment, you must first have this pop-up menu
To call the setforegroundwindow function. Otherwise, when you press ESC or
When you click the mouse, the menu will not disappear. As you can see, the ctrayicon class makes the arrangement of the tray icon
The process is very simple. To make the tray menu take effect, all you do in traydemo is to implement a notification program.
Ctrayicon: ontraynotification is called in this program. Do not forget to provide
The ctrayicon class has a menu with the same ID. In the traydemo program, add an ID
The following menu of idr_trayicon:
Then, use classwizard to add the following response functions for the three menu commands in the View class:
Void ctraydemoview: ondisplayprogram ()
{
Cwnd * pwnd;
Pwnd = afxgetapp ()-> m_pmainwnd;
Pwnd-> showwindow (sw_normal );
Pwnd-> setforegroundwindow ();
}
Void ctraydemoview: oncloseprogram ()
{
M_bshutdown = true; // really exit
Cwnd * pwnd;
Pwnd = afxgetapp ()-> m_pmainwnd;
Pwnd-> sendmessage (wm_close );
}
Void ctraydemoview: onshutoff ()
{
Exitwindowsex (ewx_shutdown, 0 );
}
In the onshutoff function, exitwindowsex (ewx_shutdown, 0) is used to shut down the computer. Limited
For more information, see msdn.
Finally, the cmainframe: onclose function must be reloaded as follows:
Void cmainframe: onclose ()
{
Ctraydemoview * pview =
(Ctraydemoview *) getactiveview ();
If (pview-> m_bshutdown)
Cframewnd: onclose ();
Else
Showwindow (sw_hide );
}
To enable the Framework Program to recognize the view class, add the following two sentences to mainfrm. cpp:
# Include "traydemodoc. H"
# Include "traydemoview. H"
If you are interested, you can expand the program to monitor the system status: When the mouse and key
If the disk remains idle after a specified time, the program will automatically execute the shutdown command.
The above programs are successfully debugged in Windows98, VC ++ 6.0.
Bytes ---------------------------------------------------------------------------------------
Use of VC tray icon |
Author: From: reads:
6 [big, medium, and small] |
|
Add the following member variables to cmainframe: Notifyicondata m_trayicon; Cmenu m_menutray;Add the following at the end of the oncreate function of cmainframe: M_trayicon.cbsize = sizeof (policyicondata ); M_trayicon.hicon = (hicon) LoadImage (afxgetapp ()-> m_hinstance, Makeintresource (idi_trayicon), image_icon, 16, 16, 0 ); M_trayicon.hwnd = m_hwnd; M_trayicon.uid = maintrayicon; M_trayicon.uflags = nif_message | nif_icon | nif_tip; M_trayicon.ucallbackmessage = wm_trayicon; Strcpy (m_trayicon.sztip, loadresstring (ids_tooltip )); Shell_policyicon (nim_add, & m_trayicon ); Added the message wm_trayicon response function: On_message (wm_trayicon, ontraynotify) Int cmainframe: ontraynotify (wparam, lparam) { If (wparam! = Maintrayicon) Return 0l; If (m_menutray.m_hmenu = NULL &&! M_menutray.loadmenu (idr_mainframe )) Return 0; Cmenu * psubmenu = m_menutray.getsubmenu (0 ); If (! Psubmenu) Return 0; If (lparam = wm_rbuttonup) { : Setmenudefaultitem (psubmenu-> m_hmenu, 0, true ); Cpoint Pos; Getcursorpos (& Pos );
Setforegroundwindow (); Psubmenu-> trackpopupmenu (tpm_rightalign | tpm_leftbutton | Tpm_rightbutton, POS. X, POS. Y, this, null ); } Else if (lparam = wm_lbuttondown) { Showwindow (sw_show ); Setforegroundwindow (); } Else if (lparam = wm_lbuttondblclk) { Sendmessage (wm_command, psubmenu-> getmenuitemid (0), 0 ); } Return 1l; } If you need to disable the window at the same time, you need to add a message processing function: On_wm_syscommand () Void cmainframe: onsyscommand (uint NID, lparam) { If (nid = SC _close) { Showwindow (sw_hide ); Return; } Cframewnd: onsyscommand (NID, lparam ); } Call the destroy function in the window: Shell_policyicon (nim_delete, & m_trayicon ); |