In this example, we’ll learn a couple of useful techniques for managing the appearance of the shell. First, you’ll see how to add an application’s icon to the toolbar, along with a tour of the related APIs and data structures. Next, you’ll see how to manage the MRU list. Making the most of shell features is key to creating user friendly (and comprehensible) apps.
Adding Application Icons to the Taskbar
By adding an application icon to the HPC or HPC Pro taskbar, you provide the user a means of quickly starting an application any time she wants because the taskbar is always visible on these platforms.
Adding the icon is somewhat more involved than the shell operations you’ve seen so far, as you must initialize a NOTIFYICONDATA structure to do so. Here are the members of the structure and their meanings:
Table 1—NOTIFYICONDATA Structure Members and Their Meanings
Member Name | Meaning |
DWORD cbSize; | Size of the structure in bytes |
HWND hWnd; | Handle to a window that receives notification messages |
UINT uID; | Application’s ID for the taskbar icon |
UINT uFlags; | Any combination of: NIF_ICON—The hIcon member is valid NIF_MESSAGE—The uCallbackMessage member is valid NIF_TIP—The szTip member is valid |
UINT uCallbackMessage; | Application defined message ID. System sends this message to the window specified by the hWnd member, in response to mouse click events over the icon’s bounding rectangle |
HICON hIcon; | Handle to the icon to add, delete, or modify |
WCHAR szTip[64]; | Tool tip string |
Here’s the structure declaration:
//declaration of structure NOTIFYICONDATA nidNotifyIcon;
It’s a good practice to fully initialize any structure we pass as a function parameter, so always null initialize the structure’s space with memset() before filling in the meaningful structure members.
memset( &nidNotifyIcon, 0x0, sizeof(NOTIFYICONDATA));
Next, we initialize the structure members, setting the NIF_ICON flag to indicate that we are manipulating an icon. Notice that we use LoadImage() rather than LoadIcon() to retrieve the bitmap for the icon. LoadImage() loads a 16 x 16 bit image, which is suitable for display on the toolbar. LoadIcon() retrieves a large icon bitmap, which will cause the next operation to fail.
nidNotifyIcon.cbSize = sizeof(NOTIFYICONDATA); nidNotifyIcon.hWnd = GetParent( hWnd ); nidNotifyIcon.uFlags = NIF_ICON; nidNotifyIcon.hIcon = (HICON) LoadImage(hInst, MAKEINTRESOURCE(IDI_SYSMENUGADGETS), IMAGE_ICON, 16, 16, 0); nidNotifyIcon.uID = 10;
Porting Tip: If you have difficulty getting your application to add icons to the toolbar, double check to make sure bitmaps are exactly 16 x 16.
To add the icon to the toolbar, call Shell_NotifyIcon():
Shell_NotifyIcon( NIM_ADD, &nidNotifyIcon ))
The parameters, in the order shown, are a flag specifying the icon operation and the address of the initialized NOTIFYICONDATA structure. You may pass only one flag value in each call to the function. Here are the possible values and for the Shell_NotifyIcon() flag parameter:
Table 2—Shell_NotifyIcon() Flags and Their Meanings
Flag Name | Meaning |
NIM_ADD | Add the icon |
NIM_DELETE | Delete the icon |
NIM_DELETE | Modify the icon |
To delete an icon from the taskbar, use the same NOTIFYICONDATA structure initialization, but pass the NIM_DELETE flag:
Shell_NotifyIcon( NIM_DELETE, &nidNotifyIcon );
Adding Documents to the Most Recently Used List
Add documents to the MRU by calling SHAddToRecentDocs().
SHAddToRecentDocs( SHARD_PATH, TEXT("MyDocumentsHello.txt"));
The parameters, in the order shown, are the flag SHARD_PATH, which indicates that we are adding the document using its fully qualified, null terminated pathname; and the pathname as a literal string. CE has an upper limit of ten MRU documents, and if you try to add more the function will fail. You can’t delete individual documents from the MRU list. To empty the entire list, pass a zero for the pathname parameter:
//delete all files from the MRU list SHAddToRecentDocs( SHARD_PATH, 0 ); }
The SysMenuGadgets techniques you’ve seen in the last three installments work well on the larger CE platforms, but they aren’t entirely in the spirit of the palmtop devices. If you choose to target the smallest devices, you’ll want to pare your application’s shell down to a much more concise set of behaviors.
Looking Ahead
In the next installment, we’ll explore shell behavior in the palmtop platforms, creating the FullScreenDialog example program.
About the Author
Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, entry time data validation.
In addition to writing for Developer.com, she has written several books including Making Win 32 Applications Mobile.
# # #