WinCE 7: Silverlight Shell with ActiveSync
As usual I started looking enthusiastically on new version of WinCE named Windows Embedded Compact 7 and especially the new features of the OS. I took our reference platform Alioth (A Marvel PXA 300 based reference design) BSP to explore the features of WEC7. I took the important feature of WEC7 (ie) Silverlight Shell. Wow!!! Microsoft introduces a new GUI for WEC7. I have created the new OSDesign for my platform. I have included the “sample Home Screen Silverlight for Windows Embedded (SYSGEN_XRSHELL)” component, other necessary components and successfully build the OS image.
After downloading the image, I was bit disappointed as I couldn’t see XRShell, instead a grey blank screen appeared as shown below.
At the same time, my manager and some other Windows CE team member got success in this. Again my brain got heated up. I started collecting the OSDesign of them, compared it and I found the difference in the list of components in the OSDesign. I tried adding and removing some components in my OSDesign and finally found the culprit component. The component which is not allowing the XRShell to run is“ActiveSync”. I got a pointer to catch this issue.
I looked the source code of XRShell available in the WINCE700\public\ shell\ oak\ XRshell\ src\ CXRShell.cpp. At the same time I was looking the activities of ActiveSync during the booting. Initially I suspect that the SH_Shell API used in ActiveSync may not be implemented. I checked the CXRShell.cpp file and found that they have not implemented the API but they have given a place holder for all the SH_Shell API by filling a single API named “MissingAPI()” and they have initialize the API placeholder in CXRShell::Execute() method. CXRShell::Execute () is the method where the shell creates desktop, scenes etc…including the Initialization of SH_Shell APIs. Using this API placeholder API, XRshell allow other applications which are waiting for SH_Shell APIs to start. But our case is different.Here XRShell is blocked by ActiveSync. So the SH_ShellAPI placeholder is not an issue.
Again the next suspected activity is, ActiveSync will show notification icon on the task bar but unfortunately there is no taskbar currently implemented in XRShell. Finally I found that ActiveSync is looking for taskbar and it blocked the XRShell to launch.
I created a blank taskbar like a place holder and attach with the XRShell. Great!!! Now XRShell is launched along with the ActiveSync.
Now I have explained you – How to create a taskbar placeholder. We can easily create a taskbar from the existing source code given for Standard shell. If you explore the following source code, you can easily create a taskbar place holder.
• \Wince700\public\shell\oak\hpc\explorer \taskbar.cpp
• \Wince700\public\shell\oak\hpc\explorer \main.cpp
Here is the source code I have done for creating a taskbar.
//Below macro definitions are taken from taskbar.hxx file.
#define HHTASKBARDATA 8
#define HHTASKBARCLASSNAME TEXT(“HHTaskBar”)
#define HHTASKBARID 0
#define HHTASKBARSTATE 4
//A dummy WndProc for taskbar
LRESULT CALLBACK XRshellTaskBarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
//Referred the CTaskBar::Register() method in taskbar.cpp to create the below given code.
//Function XShellTaskBar() – Used to create a taskbar placeholder.
void XShellTaskBar(HINSTANCE hInstance)
RETAILMSG(1,(TEXT(“XRshell TaskBar ++\r\n”)));
wc.style = /*CS_HREDRAW | CS_VREDRAW | */CS_DBLCLKS;
wc.lpfnWndProc = (WNDPROC)XRshellTaskBarWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = HHTASKBARDATA;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = HHTASKBARCLASSNAME;
//Create a Window for the taskbar. Referred the CtaskBar::Create() in taskbar.cpp.
hwndTaskBar= CreateWindowEx(0,HHTASKBARCLASSNAME, L””, WS_POPUP, 0, 0,
10, 10, NULL, NULL, hInstance, NULL);
//After the success of window creation, Register the window as a Taskbar using RegisterTaskbar() //API. Referred the Method WINAPI CreateTaskBar()in explorer.cpp. This function calls the //CTaskbar::Register and RegisterTaskBar() API.
RETAILMSG(1,(TEXT(“XRShellTaskBar: RegisterTaskBar success\r\n”)));
RETAILMSG(1,(TEXT(“XRShellTaskBar: RegisterTaskBar failed\r\n”)));
RETAILMSG(1,(TEXT(“XRShellTaskBar: Unable to create Taskbar window\r\n”)));
RETAILMSG(1,(TEXT(“Xshell TaskBar –\r\n”)));
Taskbar placeholder is ready, Now we have to add this with XRShell. It is simple, you can add this code in CXRShell.cpp file beginning and call the XShellTaskBar() function in the CXRShell::Execute() method as shown below.
unsigned long CXRShell::Execute(int nCmdShow)
/*Existing Code */
XShellTaskbar(m_hInstance); //Our Black Taskbar for XRShell
CHR( ShowShell()); //This is a blocking call