Customizing the Windows CE .NET User Interface, Part 2
Customizing the Windows CE .NET User Interface, Part 2
May 1, 2002
Last month we took a look at customizing certain user interface features of the Microsoft® Windows® CE .NET operating system. This month we extend this to cover building a custom shell using the Microsoft® Windows CE Internet Explorer. Of course, the same process could be used to create a custom shell using a stand-alone application.
The Explorer shell provided with Platform Builder is a good general-purpose shell that allows users a great deal of flexibility, while maintaining a generally familiar look and feel. Many embedded devices require a more tightly controlled user experience; for example, HMI industrial controllers, self-service Kiosks, or possibly even the control system of the train I'm riding in as I write this. These types of systems require a custom shell that limits the device to a particular function or set of functions it was designed for. Fortunately, Windows CE was designed with this in mind, and allows you to use any application you want as the shell.
Let's look at some of the functionality a custom shell might need:
3. Change modes/Tasks.
在系统启动时运行shell是非常简单的，只需要一个 注册表项.The following extract from the registry shows how the standard shell (explorer.exe is loaded):
内核初始化之后，将扫描Init key 寻找"LaunchXX"形式的key，然后以数字顺序装载列在里面的应用程序.DependXX values specify the XX value of an application loaded by the kernel as binary values in the registry. (The "hex:" syntax is used in REG files for values of type REG_BINARY.) The data for this registry value is a set of DWORD values corresponding to the Launch values of other applications the program depends on.
Note The data is defined as a sequence of bytes, so you must take into account that the operating system expects the data in little-endian 顺序.
So the example translates to:
运行explorer.exe after whatever application is listed as "Launch20" and the application listed as "Launch30." (These happen to be Device.exe and Gwes.exe.)
这里有一个catch机制.The dependency is designed for operating system dependent services. The device manager and GWES must actually have initialized to a point where they can be used before the shell can start using them. Therefore, the operating system can't just launch the applications randomly. (Well, actually it could, but that would leave each application to create its own mechanism for indicating it was ready for use—creating general havoc for developers the world over.) 幸运的是, the Windows CE architects considered this and created a standard mechanism for indicating that an application is ready for use. Windows CE uses this mechanism to determine when it should launch the dependent applications.任何在Init key下装载的应用程序都必须调用函数SignalStarted(),并把命令行参数转换为一个长整数传进去：
Once you have gotten your application to load at boot time in place of the shell, it's time to get busy with the UI coding. Typically, a UI in embedded devices doesn't resemble the traditional Windows application, with its main window and menu, toolbars, status bar, and so on. Instead, an embedded device UI is usually quite visual, and often best created by professional graphics designers. (Most engineers don't even come close to that!) So it's often desirable for the programmer and graphics designer to work together. Such a meeting of minds is proving very successful in Web development and design. Fairly rich, visually pleasing interfaces are generated almost daily on the great WWW. Why not use that model in your embedded system UI design? Windows CE .NET includes a browser component that let's you do just that.
Windows CE .NET下的浏览器组件是Microsoft® Internet Explorer 5.5 浏览器控件桌面版的一个子集. 这个组件是一个Microsoft ActiveX® 控件，可以支持所有 browsing and rendering functionality in one reusable package. 有一个叫做IESAMPLE的样例程序 (一会我们将使用它。)
The IESAMPLE application, which hosts the Internet Explorer browser control, provides a familiar Internet Explorer browser interface complete with menus, toolbars, and status bar. However, as previously mentioned, this isn't desirable in most embedded systems. What we need to have is an application that can use the browser in a "Full Screen" mode. Well it just so happens that the good folks at Microsoft thought of that, too. (Although, they failed to mention it in the documentation!) The IESAMPLE application includes a number of #if tests to enable or disable the menus, status bar, and favorites. So you only need to make a few minor modifications to the build of IESAMPLE to get what you need for a browser-based shell.
Setting Up the Project
The IESAMPLE application is located in _WINCEROOT\public\Internet Explorer\oak\IESAMPLE. As we've discussed in previous articles, it's generally not a good idea to modify the Microsoft provided code off the COMMON directory or any of the standard configurations. So you can copy the IESAMPLE files to a folder under your platform's workspace folder (that is, _WINCEROOT\MyDevice\IESHELL). IESAMPLE is set up to build using a SOURCES file. You can create a new blank Platform Builder project and add the files in the IESHELL folder you copied everything into. The easiest way to do this is to right-click on the project in the file view and click Add files to project. (Add everything except the 'SOURCES' and 'MAKEFILE' and options.cpp. Be sure to use the *.* filtering when adding files to the project to get the various resource files as well.)
Because the project was originally created using a SOURCES file, there are some extra settings you will need to make to the project before it will build correctly.
First, you will need to add the path to the ATL headers on the C/C++ tab under the Preprocessor category. (Be sure to click All Configurations so that the settings apply to each of the project configurations.)
Figure 1. 加上ATL库
From the same tab in the ProjectSsettings dialog, click the Precompiled Headers category and click the IESHELL project in the left side tree view. This will change the settings for all files in the project. The precompiled header is PRECOMP.H, so all files should be set to use it.
Figure 2. 设置预编译头
Next, click the stdafx.cpp file in the tree view to alter its settings to generate the pre-compiled header information through precomp.h.
Figure 3. Setting the precompiled header for stdafx.cpp
Next, click the IESHELL project in the tree and then click the Link tab. You will need to add the following libraries to the input libraries (note that they are separated by a space):
ole32.lib oleaut32.lib commctrl.lib uuid.lib wininet.lib winsock.lib
Figure 4. 加上所需的附加库
Then, on the Link tab, click the Output category, and set the entry point to WinMain, the Stack size to 0x20000, and the commit size to 0x1000.
Figure 5. 设置保留和提交大小
The SOURCES file uses the RCADDNULL option, which adds a '\0' to the end of all resource strings, so they can be used directly with LoadString(). Unfortunately, there aren't any settings options for that directly in the IDE, so you will need to adjust the resource compiler settings to use the /n parameter manually in the Project Options. Click the Resources tab, and click the IESHELL project in the tree, so that the settings are made project wide for all RC files. The Project Options field is only editable when you have a single configuration selected, so you will need to make this adjustment for each configuration.
Figure 6. 调整资源编译器设置
在 PRECOMP.H 文件中加入下列语句:
defines.h is needed to make sure some definitions are available even if the other headers and features are disabled by the NOxxxx defines. The NOxxxx defines could be set in the project settings dialog as another option. You must also comment out or remove the #include<pkfuncs.h> (Line 44), as it is not actually needed.
You'll need to make some changes in MainWnd.cpp as well:
1. Replace all occurrences of IESAMPLE with IESHELL.
2. Replace the lines 190-193 with the following code to handle the SignalStarted() call:
3. // allow launching with command line arg
4. // for development purposes. When loaded
5. // from the init key initSignal will be non zero
6. int initSignal = _wtol(lpCmdLine);
10. if(HandleNewWindow2(_T(""), NULL))
12. goto Cleanup;
16. if(HandleNewWindow2(lpCmdLine, NULL))
18. goto Cleanup;
20. At the top of CMainWnd::~CMainWnd(), place an #ifdef block around the command bar support.
21. #ifndef NOCOMMANDBAR
25. In CMainWnd::MainWndProc(), move the #endif // NOCOMMANDBAR down to enclose both the WM_COMMAND and the WM_NOTIFY message.
26. 在 CMainWnd::Close()函数的底部, enclose the command bar code in an #ifdef NOCOMMANDBAR block as follows:
27. #ifndef NOCOMMANDBAR
31. _himlCmdBand = NULL;
33. #endif //NOCOMMANDBAR
Next, you will need to add some build actions to get things going. You can use any HTML and image files you need for your own UI. We've provided a simple sample of what a WebPhone device might look like. At this point it would be appropriate to remind you that it's rare to find a software engineer who is also a good graphics designer. (This sample is no exception!) The major advantage of using the browser as the shell of a dedicated device is the separation of presentation from functionality. The DHTML can contain ActiveX objects that implement the core functionality of the device and are manipulated by Microsoft JScript® code to connect the UI to the primary device functionality.
To set the actions for the sample, from the Feature View, you will need to right-click the IESHELL.PBP and select settings from the popup menu. Click All Configurations and Pre-Make Image for the Build Step. 点击 New to create a new action to copy C:\WINCE400\PUBLIC\MyPad\IESHELL\Files\IESHELL.reg to the $(_FLATRELEASEDIR).
In the Make Image step, add an environment variable IMGIESHELL and set it to 1.
The registry file will be copied to the release directory and processed by the makeimg tool. IESHELL.REG is set up to test for the Environment variable IMGIESHELL, conditionally include the settings to launch IESHELL.EXE as the shell, and to specify the default home page.
Figure 7. 复制IESHELL 注册表文件到_FLATRELEASEDIR目录
Click the BIB Info tab. Add any file; you can then edit the entry in the dialog to $(_FLATRELEASEDIR)\IESHELL.EXE, but be sure it's in the Modules section and is not compressed. Then add each of the files listed below as uncompressed in the Files section. These are the images and home page (shell.htm) for the HTML-based shell:
Figure 8. 加文件到BIB Info
Making the start page and the elements it loads uncompressed helps the page to load faster.
Once you have all of the changes and settings taken care of, you can build the project and see the result. It should look like the following:
Figure 9. 最后的结果: 一个IE shell for Windows CE
It doesn't really do anything particularly useful, but it does show how to set up a UI based on the browser. You can further enhance the functionality to support a set of navigation buttons for the mini-browser window, and even include an address bar. If you are really ambitious, you can enhance it to utilize the support available in Windows CE .NET for Voice over IP and Real-Time Communications.
Mike Hall is a Product Manager in the Microsoft Embedded and Appliance Platform Group (EAPG). Mike has been working with Windows CE since 1996—in developer support, Embedded System Engineering, and the Embedded product group. When not at the office, Mike can be found with his family, working on Skunk projects, or riding a Honda ST1100.
Steve Maillet is the Founder and Senior Consultant for Entelechy Consulting. Steve has provided training and has developed Windows CE solutions for clients since 1997, when CE was first introduced. Steve is a frequent contributor to the Microsoft Windows CE development newsgroups. When he's not at his computer burning up the keys, Steve can be found jumping out of airplanes at the nearest drop zone.