Programmatically display system tray icon on Windows Mobile
As a Windows Mobile user you would have seen some icons near to the bottom right corner of the Today screen. These icons give users ability to easily launch the application or show an menu with more choices.
Tray icons on Today screen (Dell Axim)
This post discusses the steps and code to put your own icon in the system tray. I will also provide a solution to a common issue with Windows Mobile whereby its not easy to know the coordinates of the icon or the coordinates where the user might have tapped within the tray area.
okay…I will take an example of a Win32 native application. The concepts will hold good even if you are programming with some other framework.
1. Declare some variables and function prototypes
// some required defines
#define WM_SYSTRAY_MSG WM_USER+1
#define ID_TRAY 1
// some variables
static NOTIFYICONDATA g_structNotifyIconData = {0};
static HWND g_hWndMain = NULL;
static HWND g_hWnd = NULL;
static WNDPROC g_fnProc = NULL;
static DWORD g_dwTapPos = 0;
LRESULT DesktopExplorerWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
2. Implement a wrapper function to show and hide tray icon.
BOOL ShowTrayIcon(HWND hWnd, BOOL bShowIcon)
{
BOOL bRet = FALSE;
g_structNotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
g_structNotifyIconData.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_SHOWTRAYICON));
g_structNotifyIconData.hWnd = hWnd;
g_structNotifyIconData.uCallbackMessage = WM_SYSTRAY_MSG;
g_structNotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON;
g_structNotifyIconData.szTip[0] = ”;
g_structNotifyIconData.uID = ID_TRAY;
if (bShowIcon)
bRet = Shell_NotifyIcon(NIM_ADD, &g_structNotifyIconData);
else
bRet = Shell_NotifyIcon(NIM_DELETE, &g_structNotifyIconData);
return bRet;
}
Above function fills up fields in NOTIFYICONDATA structure, setting the icon resource handle, parent window handle, callback message identifier, flags specifying that uCallbackMessage and icon information is being set and an user defined ID value.
3. Call ShowTrayIcon function in WM_CREATE handler
In the WM_CREATE handler portion of the main WndProc function, call ShowTrayIcon(hWnd, TRUE).
case WM_CREATE:
ShowTrayIcon(hWnd, TRUE);
…
…
4. Add handler for WM_SYSTRAY_MSG
WM_SYSTRAY_MSG will be sent to the main window procedure (WndProc) when the user taps or clicks on the icon. We must add the following code to make some good use of the icon.
switch (message)
{
case WM_SYSTRAY_MSG:
{
switch (lParam)
{
case WM_LBUTTONDOWN:
if (ID_TRAY == wParam)
{
BOOL bRet = FALSE;
POINT pt = {0};
HMENU hTrayMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_TRAY_MENU));
if (hTrayMenu)
{
HMENU hSubMenu = GetSubMenu(hTrayMenu, 0);
pt.x = LOWORD(g_dwTapPos);
pt.y = HIWORD(g_dwTapPos);
bRet = TrackPopupMenu(hSubMenu, TPM_CENTERALIGN | TPM_BOTTOMALIGN, pt.x, pt.y, 0, hWnd, NULL);
dwError = GetLastError();
DestroyMenu(hSubMenu);
DestroyMenu(hTrayMenu);
}
}
}
}
break;
Here we know that user has tapped on the icon area. As a result we can do anything that we might want. Here I an showing up a popup menu using TrackPopupMenu API. g_dwTapPos variable contains the x & y position where the user tapped on the system tray area. We will see later how we get the information in g_dwTapPos. Note that GetCursorPos() does not get us this position value on Windows Mobile whereas it works on Windows desktop.
5. Getting the tap coordinates on system tray icon
One way I found to know the coordinates where the user tapped or clicked on the taskbar is to subclass the DesktopExplorerWindow and trap WM_CANCELMODE message. In the handler for WM_CANCELMODE, calling GetMessagePos() will return the position into a g_dwTapPos variable.
//
// DesktopExplorerWindow
//
LRESULT DesktopExplorerWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
// Trap WM_CANCELMODE message
// This will get us the point at which tap occurred
case WM_CANCELMODE:
g_dwTapPos = GetMessagePos();
break;
}
return ::CallWindowProc(g_fnProc, hWnd, msg, wParam, lParam);
}
BOOL HookDesktopExplorerWindow()
{
if(g_fnProc)
return FALSE;
g_hWnd = ::FindWindow(_T(”DesktopExplorerWindow”), NULL);
if(g_hWnd)
{
g_fnProc = (WNDPROC)::SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG)DesktopExplorerWindowProc);
}
return g_hWnd != NULL;
}
BOOL FreeDesktopExplorerWindow()
{
if(!g_fnProc)
return FALSE;
::SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG)g_fnProc);
g_fnProc = NULL;
return TRUE;
}
HookDesktopExplorerWindow can be called from WM_CREATE handler in main Window procedure before calling ShowTrayIcon. FreeDesktopExplorerWindow can be called from WM_DESTROY handler in main Window procedure.
Tray Icon
See below how the icon and popup menu shows up in my sample application.
Debugging CeRAPIInvoke Calls
RAPI (Remote API) dlls are loaded by rapiclnt.exe on the Windows Mobile device when CeRapiInvoke API is called by the desktop application. CeRapiInvoke is a general-purpose API to remotely execute a function on a Windows Mobile device that is connected to the desktop over ActiveSync.
To debug your RAPI dll, do the following.
1. Launch Visual Studio and Open the RAPI dll project (.sln, .vcproj) in debug mode.
2. Go to Debug Menu and click on Attach to process menu item.
3. On the transport screen (see below), change the transport selection to Smart Device.
rapiclnt.exe running on the device
4. On the above screen, select rapiclnt.exe and click on Attach button. This step makes rapiclnt.exe and all modules loaded by it debuggable as long as debugging information is available to the debugger.
5. Now locate the function that you want to debug in source files and insert the breakpoint (or use DebugBreak function) at an appropriate location. You will see the inactive breakpoint icon. It means this module is not currently loaded. Thats okay as we know we have not yet called the function from the desktop application. When the function is eventually called, it will result in loading of the RAPI dll by rapiclnt.exe.
6. Now start the desktop side application. As CeRapiInvoke API is called, breakpoints will become active and you will see the control breaking at the first breakpoint.
From here onwards you can just debug the dll as you would debug normal applications.
Note: If you want debug both desktop application and RAPI dll, you should open the two projects in separate instances of Visual Studio IDE.
Create full screen application in .Net CF
Applications can use the screen real estate to their benefit by running in full screen mode. If you are developing your application in .NET CF, there are 2 ways to make it full screen.
In Code
Put the following code into your form's Load() method like below.
private void Form1_Load(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
}
In Designer View
Set FormBorderStyle to None and WindowState property to Maximized.
FullScreen in SureLock Studio
SureLock Studio has an option to set an "approved" application to run in full screen mode. This does not mean that SureLock will launch it in fullscreen mode, instead this option instructs SureLock to not interfere with application making itself fullscreen. A well-behaved fullscreen application should provide a way for the user to minimize or exit.
If your application is full screen and you don't specify this in SureLock Studio then you will see the windows taskbar popping at the top. This is an undesired behavior and can be easily avoided by setting "This is a full screen application" option.
Better customer support with Live Chat
We recently started using Meebo Live Chat on our website. It is working out really well. Earlier with emails going back and forth used to take a few hours if not days to resolve any problem. It's now down to a few minutes. Saves everybody's time. All the visitors and existing customers are happy about that.
http://www.42gears.com/livesupport.html
Why Meebo?
We choose Meebo as we didn't want to get indulged in setting up chat software on our servers. With Meebo we just had to put up a small widget code and it all started working. And yes, Meebo Notifier is very much required as you won't want to stare at chat window all the time.
Windows Mobile Shortcuts
Shortcuts makes it easy for users to launch applications. Shortcut files have “.lnk” extension and they take up very little storage space. Shortcuts contain information about the application to launch along with any parameter information. They are really handy if predetermined values need to be passed to the application as command line parameters.
How to create a Shortcut on the device
- Run Microsoft ActiveSync on your desktop and establish connection with the PDA.
- Right-click on the ActiveSync icon on the desktop Windows taskbar and Click Explore. This will bringup a window showing contents of Mobile Device folder
- Now goto the folder where the executable resides
- Rightclick on the file (say ABC.exe) and a menu pops up. Select Create Shortcut menu item
- This will generate a shortcut (.lnk) file with the name like “Shortcut to ABC.exe”
- You can rename the shortcut to anything that you like
- Move or copy the shortcut if you want it anywhere else on the device
How shortcuts work (Tech stuff for developers)
This section describes the format of a shortcut file. Simply copy the .lnk file to the desktop and open it in your favorite text editor. I use Notepad. The content in the .lnk file will have the following format.
xx#”\{APPLICATION_PATH}{OPTIONAL PARAMETERS}”
where xx is number of characters in the above text excluding xx#.
For e.g.
18#”\Windows\abc.exe”
where 18 is the count of characters after pound character (#) and \Windows\abc.exe is the target application.
To create a shortcut from your application use SHCreateShortcut API.
Sample Code: (Courtesy MSDN)
BOOL SHCreateShortcutExample()
{
// Create a shortcut called myAppShortcut.lnk,
// that links to the target file in \\, named myApp.exe.
// Place the shortcut in the folder \Windows.
return SHCreateShortcut(TEXT("\\Windows\\myAppShortcut.lnk"), TEXT("\\myApp.exe"));
}
SureLock Studio: New Release (2009.09.15.0)
We have released SureLock Studio v2009.09.15.0. This release has some new feature additions:
- Phone Signal Status Indicator on the Kiosk Main Screen
- Speaker Volume control
- Align Screen (Stylus Calibration) support
How to find Phone Signal Strength in Windows Mobile?
There is no API to determine the current signal strength of the phone radio on a Windows Mobile Phone Device. But as it changes the status is updated in the registry at the following location.
[HKEY_LOCAL_MACHINE\System\State\Phone]
“Signal Strength” value represents the signal value (0-100). The operating system uses this value to show the bars on the taskbar representing the current signal strength.
You might want to know in your application when the signal strength changes. Your application can poll the registry but polling is a resource intensive operation and should be avoided. Instead you can use RegistryNotifyCallback function provided by State and Notifications Broker mechanism. This powerful feature is available since WM 5.0 and gives applications an easy way to get notified when status of registry value changes.
Visit the following link for more information and sample code.
http://msdn.microsoft.com/en-us/library/ms894764.aspx
Native programmers should check out snapi.h file in the WM SDK. It gives more information about the bitmasks of various registry values.
Starter’s Guide to Windows Mobile Development
Information in this post is for developers who are new to windows mobile application development and have no clue on where to start.
Languages:
You can choose from the following available languages.
- Visual C# and Visual Basic for Managed programming. Managed applications require .net compact framework runtime to be installed on the device. It's a virtual machine on which common language runtime (CLR) instructions execute in a platform independent way. (Remember Java!!!). C# is most commonly used of these two. Sample code availability on the web is also more for C#.
- Native programming with Visual C++ using Win32 APIs or MFC (Microsoft Foundation Classes). Although managed programming is easier, it does not have support for everything. Besides managed programs have slower execution times than their native counterparts. Note that execution speed has contextual importance. BTW our product SureLock Studio is completely developed in Visual C++ but we use test applications written in C# and VB.NET.
Required Development Tools and SDKs:
- Microsoft Visual Studio (Professional or Team Edition): De facto tool for developing applications for Windows Mobile 5 and later. It supports programming in Visual C++, Visual C# and Visual Basic.
- Latest Windows Mobile SDK.
- Embedded Visual C++: EVC++ was tool for development applications for Windows Mobile devices before WM 5.0. It is still available for download and is completely free. You can only write managed applications with it. Note that you must install latest service pack and SDK.
Additional Tools:
- Device Emulator Manager: Great way to test applications on various Emulators installed on the desktop PC. You can perform different operations like launching emulators instances, simulating cradle insert/remove, shutdown, saving/clearing state etc. Device Emulator Manager ships as part of Visual Studio
- Emulator Images: Device Emulator uses the actual emulator OS images for execution. These emulator images come along with SDK.
- Device Security Manager: Useful when your first Windows Mobile application is not allowed to execute on the device configured with security policies. You can change the security settings and add/remove certificates on the device. Device Security Manager also comes as part of with Visual Studio 2008.
SureLock Studio: New Release (2009.08.31.0)
We have released SureLock Studio 2009.08.31.0. This update has fixes for phone keys control and user interface on the device.
For any feedback on this release, write to support_nospam@42gears.com (remove _nospam).
Windows CE and Windows Mobile for starters
Many a times I find myself in discussions on the history of Windows CE and Windows Mobile operating systems. Besides, if you have just started to work with Windows Mobile or Windows CE, its good to be aware of origins and basics of these operating systems.
Following is an attempt to sort those questions out. So here we go!
- Microsoft launched Windows CE (code named Pegasus) in 1996
- Previous attempts from Microsoft – WinPad (Win16) and Pulsar (Win32) projects (both canceled), Teams joined and became Pegasus.
- Windows CE (now known as Windows Embedded) is a functionally scaled-down Windows operating system. It means it does lots of things like the desktop Windows but not all.
- Designed from scratch for requirements of embedded and handheld devices (memory, CPU and power constraints). Although Windows CE has some functionality similar to desktop Windows but they are implemented completely differently.
- CE kernel can run in under 1MB RAM
- Windows CE is a highly customizable operating system. OEMs can pick and choose features or add new ones to their devices as per the requirements. For e.g. one Windows CE device can be a handheld with a display and a keyboard and another one can be a headless device without any display or keyboard.
- Multithreading Support: Multithreading gives an illusion to running applications that all the system resources are available to it at all times. The illusion is a result of some intelligent time-sharing (also known as Scheduling) implemented in the operating system.
- Pre-emptive scheduling between different priority levels and round-robin policy within a level.
- Processor Support: Windows CE is supported on x86, ARM, SH3 ad MIPS based processors.
- Difference between Windows Mobile and Windows CE: Windows Mobile is built on top of Windows CE kernel and subsystems. It is targeted at handheld devices with specific hardware and software features. OEMs are required to following strict guidelines (software and hardware) for developing their devices.
- Windows CE supports Unicode only.
More later...
