10 Jul
Posted by kdutta in C#, Development, Home Screen, Interop, Windows Mobile
One of my recent projects at Enterprise Mobile was creating a custom home screen (see above) for the new MotoQ9h and Blackjack II devices. The top row is the standard Windows Mobile “Icon Bar”. The second row has the clock, messaging center (SMS, Mail, Voicemail), and current profile. Below that is the status text and the application bar. (Everything below the icon bar is a single full screen plug-in.)
![]()
At first glance, I assumed this would be a breeze. I have a powerful layout, key handling, and paint framework that I use in every project I work on, and thought that creating a home screen leveraging that would make it trivial. Sadly I was sorely mistaken.
Those of you familiar with WM Home Screen development know that there are actually two APIs: the Home Screen API (Smartphone) and the Today Screen API (Pocket PC). I was only interested in the prior. Smartphone Home Screen development is considerably more difficult: you don’t have nearly as much control. The developer must implement IHomePlugin which only receives paint events (the plug-in is supplied only an HDC) and some key events (left and right only). On Pocket PC, you get an HWND and all the good things that go along with it.
That didn’t phase me too much. My plan of action was to implement this IHomePlugin interface in managed code and then let the magic happen. Easy enough. I implement a dummy plug-in in C#, and try to register the COM object… and it doesn’t work. It refused to register, the error claiming it was an invalid DLL. I poked at it for a while before finally giving up and checking to see if Google would know why I could not register a C# COM object on Windows Mobile.
I searched for a while, and found plenty of examples of how to invoke unmanaged code from managed code. Then I noticed, not a single site showed how to invoke managed from unmanaged. I began searching explicitly for that, and found my answer:
The .Net Compact Framework does not support hosting the runtime from native code. This means that you will not be able to call CoCreateInstace to instantiate a managed object, or register managed objects as COM objects on the system. You will also not be able to call CorBindToRuntime or ClrCreateManagedInstance. In order to call managed functions from native code, you must first use the runtime to marshal a managed interface or a delegate down to native code. This means you must always start out in managed code (with a .net executable) in order to expose .net components to native code.
This was news to me. And pretty devastating; the thought of creating a fairly complex home screen from scratch in unmanaged code was daunting. If it is not obvious, I’m primarily a .NET developer. Don’t get me wrong, I have grass roots in C, but, the facts of life are that the lower level your programming language, the higher the development time and bug count.
So I quickly thought of a workaround though: create a managed service executable that hosts the UI framework. And using a combination of MessageWindows and sharing memory between processes, I could construct a bridge from unmanaged to managed code:
Implement IHomePlugin in unmanaged code and add that plug-in to the home screen. The unmanaged plug-in will do the following:
Once started, the managed executable does the following:
That solves the painting issue, but the plug-in still needed to get key events from the Home Screen API and deliver them to managed code. Easy enough: the managed executable can create a MessageWindow and the unmanaged can deliver the key events provided by the Home Screen API. The managed code can then process the key event, repaint the back buffer, and invalidate the plug-in to refresh the screen.
This works great, but the catch with the API is that it delivers only left and right key presses. It won’t send up and down key events (because then the user can’t navigate to another plug-in on the home screen). However, since my plug-in was full screen, I did not matter. I needed a way to navigate vertically between elements laid out in my single full screen plug-in.
The solution to capturing all key events is a neat trick that native Win32 API developers are familiar with. Have the unmanaged plug-in subclass the home screen window (DesktopExplorerWindow as found in the VS Remote Spy++ tool) proc to steal the key presses and send them off to the managed code.
And there you go, a fully functional “managed” Home Screen Plug-In. My initial worry was that performance would suffer terribly from the cross process communication, but the home screen was actually very responsive. Users reported that the UI was quite “snappy”.
Unfortunately I don’t have any sample code to provide (yet), since this is all company IP. But maybe it will be released in the future!
Note: I should mention that Home Screen development actually gets easier with this interprocess communication. Developing a purely unmanaged plug-in means that the entire home.exe process needs to be stopped and started with every little change made to the plug-in. This can grow to be quite tedious. With the two-process model, starting and stopping the second managed process leaves the home.exe undisturbed.
Koushik Dutta
Software Engineer
www.koushikdutta.com
6 Responses
Malcolm Hall
10|Jul|2008 1Very cool post, this is one of my favourite topics at the moment. Shared memory sounds interesting but when I built my C# homescreen plugin a few months ago I decided instead to create about 3 custom window message IDs to use to pass the dimensions and the HDC, then I wrapped up all of the real plugin messages in a custom ones and forwarded it to C#. I haven’t published my code yet either because I am trying to make it cross platform between pocket pc and smartphone using some abstraction. That is getting messy though.
By the way I have recently spotted a third person who has solved this problem too, the project is called Throttle Launcher and uses a Pocket PC plugin. No source code either but you can have a peak with Reflector.
kdutta
10|Jul|2008 2Getting into managed code on the Pocket PC Today Sceen is relatively easier from what I understand. You can create a regular System.Windows.Form/Control, and then parent it to your plugin window. Haven’t messed around with it at all though.
Joseph Mujhe
15|Jul|2008 3Hi All.
Hard work to do this! I’m trying to do something similar, but the entire code is in unmanaged code. But trying to subclass the home.exe WndProc is causing a lot of crashes! Has It happen with you?
Other big problem I’m facing is to change the RSK of the Desktop toolbar. I can change it via WM_Messages but when the device receives some O.S. commands (like new message) causes some inconsistency.
Any ideas?
Thanks!
Joseph Mujhe
kdutta
15|Jul|2008 4I didn’t have any issues with the WndProc causing crashes. I only took certain key events, and passed the rest of the events on using CallWindowProc. Make sure you reset the old window proc when the home screen changes (your plugin is released).
You can filter those OS messages too via the WndProc probably… similar to how you are setting the RSK.
Pila
28|Jul|2008 5I think it will help me as i have a Blackjack device.
Manvendra
24|Feb|2009 6Plz help me, i also want to put custom clickable msg on home screen , that open new windows form on click.I can also pay money……
Leave a reply
Search
Archives
Categories
Device Info
Windows Mobile Blogs
Copyright © 2008 - Enterprise Mobile
Proudly powered by WordPress - InSense 1.0 Theme by Design Disease.