刚才看到一个极其精彩的代码,我实在忍不住就发博客上了,原文地址:http://www.christec.co.nz/blog/archives/279
Today I thought I would demonstrate a proof of concept that may enable you to create today screen items in managed languages such as C# or VB.NET. In part this early preview was brought about by a recent request for advice on how to create managed Input Methods for the SIP keyboard, something that I think could be achieved using a similar approach. This is still a work in progress to see what is possible…. at the moment I have not fully evaluated the technique to be valid and/or tidied the code to my usual standard for release. I would love your feedback on this project.
The Windows Mobile OS has a Today Screen API that enables custom items to be displayed on the main screen of the device. This API is highly geared towards native (C or C++) developers, and it is not possible for managed (VB.NET or C#) developers to implement the API directly.
Jim Wilson previously demonstrated in an MSDN article titled “Creating a Pocket PC Today Screen Plug-in with the .NET Compact Framework” a technique were a C++ based today screen item was developed to display HTML based content that was generated by a C# application. Although this is suitable for some applications it doesn’t lend itself to highly interactive or graphic intensive animated displays.
What we ideally want to do is to implement a minimal amount of native code that satisifies the requirements of the Today Screen API and have this native stub delegate all the GUI functionality off to a managed application.
It would also be extremely handy if the native part of this solution could be written once and reutilised among multiple managed today screen items. In part because this would open up today screen item development to those developers who currently don’t have experience in developing native code.
My solution utilises a native today screen item written in C++. This today screen item is implemented in a DLL called ManagedTodayScreenItem.dll. The OS is configured to load this item into the today screen process. However unlike other today screen items this one looks up additional configuration data stored in the registry to determine the name of a managed (i.e. VB.NET or C#) executable that should be launched when it is first displayed.
The managed executable starts up as normal and displays it’s main form. However once displayed the managed process then proceeds to establish an inter-process communication (IPC) channel back to the native today screen item. Once this channel is established the managed application informs the native today screen item of it’s window handle. The native today screen item then reparents the managed form to be a child of the today screen item and resizes it to fit the space allocated to the today screen item.
From this point on the illusion of a managed today screen item has been made. Whenever the managed form needs to act like a today screen item (such as painting the today screen watermark on it’s background) it can communicate with the native today screen item stub, and conversely whenever the native stub detects a change in it’s size or location it can communicate this change back to the managed part of the item.
Creating a new today screen item with this framework is relatively easy. Perhaps the easiest way is to modify the SampleTodayScreenItem example within the sample application mentioned below.
If you are creating a today screen item from scratch you need to follow these steps:
The last step is very important. The TodayScreenPluginForm class itself derives from Form but overrides a couple of methods (such as OnPaint) to ensure the form has the look and feel of a today screen item. This base class also behind the scenes sets up the inter-process communication channel which allows the managed part of the solution to communicate with the native part.
Your form source code should look something like the following after these changes:
using Christec.WindowsMobile.TodayScreen; public Form1 : TodayScreenPluginForm { public Form1() : base(4567) { InitializeComponent(); } }
A key thing to point out here is the call to the TodayScreenPluginForm constructor that accepts an integer parameter. This integer is an id that is a unique value that identifies this particular today screen plugin. This is the part of the framework that enables the one native today screen item to be reutilised multiple times by different managed plugins (since each managed plugin should be given a different id value to differentiate itself).
Once the managed executable has been created as described above and compiled all that is required is a couple of registry settings to be added to make the operating system aware of the new today screen item. These registry settings are as follows:
Underneath HKLM\Software\Microsoft\Today\Items\<Name>
<Name> within the registry key above should be replaced with the name you want to be visible to the user within the Today Screen control panel applet. All these registry values should be identical for each managed today screen plugin you develop. The only difference should be the value you use for the Flags setting. This should match up with the value you passed into the TodayScreenPluginForm constructor within the source code of the managed part of your today screen item.
The native ManagedTodayScreenItem.dll today screen item utilises this “flags” value to lookup another set of item specific registry keys to determine which managed executable needs to be executed as outlined below:
Underneath HKLM\Software\ChrisTec\ManagedTodayScreenPlugins\<id>
<id> within the registry key above should be replaced with the unique id value (4567 in the example) for your managed today screen item. At present it is not possible to dynamically change the height of the today screen item at runtime. This would be something that is reasonably easy to implement but is one of the features I have not implemented yet as it wasn’t required in order to prove the validity of the concept.
The sample project that is available for download contains two CAB files within a subdirectory called “bin”. These are as follows:
If both of these CAB files are installed on a Pocket PC device and the device is then soft reset you should see the new today screen item appear.
If you would like to have a go at creating your own managed today screen item you should also find a pre-compiled copy of the Christec.WindowsMobile.TodayScreen assembly that you will need to reference within this directory.
Within the other subdirectory (called “src”) you should be able to find solution files that will enable you to rebuild the two CAB files mentioned above.
As I stated in the introduction, this project is an early proof of concept that I have decided to share early on in the hope that it helps a few people and perhaps gets a couple interested in contributing. Since the code is not fully released there are a number of known issues and outstanding tasks.
Some of these are as follows:
Hopefully this blog entry will cause some interest, as I know developing custom today screen items in managed code is a frequent question on online developer help forums. Although this solution isn’t fully complete and isn’t the most straight forward to configure (at present at-least) the results I have managed to get so far are encouraging.
If this proof of concept can validate the technique I am using to host .NET Compact Framework based forms within native processes I can see no reason why it would not work in other situations such as custom SIP based keyboards. The only difference would be the native component that would need to wrap up the native API provided by the operating system.
I would be really keen to hear your feedback and thoughts on this prototype. Especially if you are able to give me a hand to further validate and develop the concept.