Visual Basic .NET Comes to Devices
Microsoft® Visual Basic® .NET
Microsoft Visual Studio® .NET
Summary: Learn how to build Windows applications for smart devices that support the .NET Compact Framework using Smart Device Extensions (SDE) for Visual Studio .NET. This article includes an examination of the entire development, debugging, and deployment process and explores the differences between the .NET Framework and the .NET Compact Framework. (26 printed pages)
Smart Device Extensions (SDE) for Microsoft® Visual Studio® .NET allow you to leverage all of your .NET programming skills to build Microsoft Windows® applications for smart devices that support the Microsoft .NET Compact Framework. Using SDE, you can produce applications for Pocket PC and Microsoft Windows CE .NET platforms using the familiar Microsoft Visual Basic® .NET (or Microsoft Visual C#™) language and the same tools—and class libraries—that are used to build .NET applications for the desktop and server. Since these smart devices don't offer all of the features of their larger cousins, the hardest thing to master is learning which parts of the Microsoft .NET Framework have been modified to align with the reduced functionality of these more limited portable platforms. Fortunately, the Visual Studio environment provides full support for this as well as enabling desktop debugging of applications running on these platforms.
Creating applications using SDE from Visual Basic .NET is so straightforward that you might be tempted to just jump right in by creating a new SDE project, dropping some controls on a form, and writing some code. In fact, we're going to do just that in a moment. But we are also going to step you through the entire development, debugging, and deployment process and point out exactly where the special nature of SDE development is different than developing desktop applications. And for those of you who have a technical interest in how this stuff works, we will explain what's going on under the hood.
Let's start with the traditional "Hello World" application, which, while clearly trivial, still illustrates in a nutshell the entire development process. The following steps illustrate in detail the process of:
- Creating an application on the desktop using Visual Studio .NET
- Deploying the application to the device
- Debugging the application using Visual Studio .NET
We will assume you have installed both Visual Studio .NET and the Smart Device Extensions (SDE) and that you are either using an attached device or, if you don't have an actual device, the supplied Pocket PC emulator.
- Create a new SDE project using Visual Basic .NET
- Open the "New Project" dialog and select—from "Visual Basic Projects"—the "Smart Device Application" template (see Figure 1).
Figure 1. New Project dialog for Smart Device Application
- Update the Location, if desired. You may find it handy to create a separate subdirectory for building test SDE applications that is outside your normal source code tree.
- Give your application a Name (such as "HelloWorld"). This will create a new directory under Location to contain your application's source code.
- Click OK.
- Open the "New Project" dialog and select—from "Visual Basic Projects"—the "Smart Device Application" template (see Figure 1).
- This starts the "Smart Device Application Wizard" (see Figure 2). At this point you need to choose between developing for Windows CE and developing for the Pocket PC, a specific type of Windows CE device. Your choice will determine which project templates are used to construct your initial blank application. For instance, the "Windows Application" template form for the Pocket PC includes a MainMenu control, which is not part of the template for the Windows CE platform.
Figure 2. Smart Device Application Wizard
- Choose the Platform (use Pocket PC if you will be using the emulator).
- Choose the Project Type. For our first simple application—which simply displays a form on the device—choose "Windows Application".
- Click OK and let the wizard create the project (this may take a moment).
You should now be looking at a Visual Basic .NET application that looks somewhat like Figure 3. Your window arrangement will likely be different since Visual Studio remembers the layout you've configured in the past when developing other projects.
Figure 3. Visual Basic .NET with SDE Project
Take a moment to explore Visual Studio and note that the appearance is almost identical to what you are used to when developing desktop applications using Visual Basic .NET. The first thing to notice is that some of the Toolbox items in the Device Controls tab—as for dialogs (Color, Files, Font, Print) and advanced user interface (Calendar, ImageList, DataGrid)—are not included with this first release of SDE. There's also a new Device Extensions toolbar. And if you've selected something on the Form (presized to fit your target smart device), you may also notice that there are fewer things listed in the Properties window.
Now let's do the remaining steps in building this small test program.
- Place a Button on the Form. Note the flat look of the button, which is the style normally used by your target device.
- Double-click the button (or otherwise open the code window) and enter the following line of code in the button's Click event handler:
- Press <F9> to set a breakpoint on this line.
- Press <F11> to start stepping into the application. This builds the application (the steps are listed in the Output window) and then brings up the Deploy dialog box.
- Choose the appropriate target smart device (we will be using the Pocket PC Emulator) and click Deploy to start the deployment process. As for the build process, the deployment steps are listed in the Output window and the Status bar in Visual Studio .NET provides current information.
Note If you are going to have any problems with your SDE development configuration, this is when they will show up. Assuming you have read and followed the installation instructions, the most common problem is the inability to communicate to the device. Note that even if you are using the emulator, this version of the SDE requires that you have a network address. Please refer to the supplied documentation if you are still experiencing difficulties establishing a connection.
Visual Studio .NET will now communicate with the device and install your program. The first step is to install the .NET Compact Framework if it's not already present on the device. Then your application is copied over into the \Windows directory (by default). Finally the application is started.
You are now running the program on the smart device (or emulator), and you are debugging the code on your desktop using Visual Studio .NET. At this point you might want to start exploring on your own, or you can follow these demonstration steps:
- Since you have stepped into the program, you will now be taken to the first line of the application.
- Application.Run(New Form1())
- Note that you have full access to the familiar Visual Studio .NET development environment, including such windows as Locals, Immediate (Command), Call Stack and so on.
- Continue to step through the program execution, which takes you into the constructor (New) and then InitializeComponent subroutines. After completing the Application.Run statement in Main, focus will return to the device (if using the emulator) and the form will be displayed.
- Click the button on the form. You will now be taken back to Visual Studio .NET where the code will break on the statement in the button's Click event handler.
- Continue stepping through the program to bring up the MessageBox on the smart device (see Figure 4).
Figure 4. "HelloWorld" MessageBox on the Device
- Click the OK button in the upper left corner of the MessageBox on the smart device to close the application.
- Back in the debugger again, step again to close the dialog and return you to your original point.
- Click the OK button in the upper right corner of the form on the smart device.
- This jumps you back into the Visual Studio .NET at the bottom of Main. Note that application on the smart device goes away.
- Step one more time to exit the debugger.
So far you have created an application (albeit a trivial one), deployed it to a smart device, and debugged it using Visual Studio .NET on your desktop. The process should seem very familiar, since it's mostly equivalent to the process you use to develop other applications with Visual Studio .NET. Let's now finish the smart device application and create a redistributable package so you can give this powerful program to your friends and amaze them with your smart device programming skills! Oh, so now you're thinking that the program doesn't really have any features? No problem, we'll address that a little later on.
Since we want our smart device program to look like a true professional application, we're going to add an icon and create a redistributable CAB file. The CAB file can then be opened and run by clicking or tapping it from the source location, or it can be copied to the device first. A CAB file can be run from any location since it contains all the setup information needed by the smart device. When the CAB file is run, application files are automatically extracted and placed them into a subdirectory under \Program Files with the same name as your smart device project.
You can control where your application files are installed by providing your own information (.inf) file and optional Setup.dll file before running the CAB wizard. The .inf file specifies directories, files, settings, and configurations. The (optional) Setup.dll file provides functions for performing certain operations during the installation and removal of your application. See the SDE documentation for more information on these topics.
Let's add an icon the same way we do for desktop applications.
- Select Properties from the Project menu, and in the Common Properties node select Build.
- Where the build dialog asks for the location of the Application Icon, navigate to and choose an appropriate icon (.ICO file). Many icons are provided with Visual Studio .NET: By default they are installed in "C:\Program Files\Microsoft Visual Studio .NET\Common7\Graphics\icons" subdirectory. In our example, we will choose the exclem.ico file from the Misc subdirectory.
- The icon is added to the project files and the icon file's Build Action is set to Content.
Now we are ready to build and distribute our device application.
- Choose Build Cab File from the Build menu. This creates a CAB file in your program's \bin\Debug subdirectory for each of the hardware platforms supported by SDE. Assuming our application is named "HelloWorld", the file for the Pocket PC is named "HelloWorld_PPC.ARM.cab" and the equivalent one for the emulator is "HelloWorld_PPC.X86.cab".
At this point we can copy the program's CAB file to the device. Before doing that, however, we should first ensure that the .NET Compact Framework is already installed on the device. If you know that the device does not have the framework installed—or if you want to create a distribution to give other device users—you also need to provide the appropriate CAB file for the framework. By default, these CAB files are installed with SDE under the following directory:
C:\Program Files\Microsoft Visual Studio .NET\ CompactFrameworkSDK\v1.0.3300\Windows CE\wce300\
CAB files are stored in subdirectories according to device processor type, so the file for the Pocket PC version of the framework is in the \arm subdirectory and is named "netcf.cjk.ppc3.arm.cab". The framework for the emulator is in the \x86 subdirectory and is named "netcf.cjk.ppc3.x86.cab".
So, how do you get these files onto the device? Well, it depends on the device and you may have several options. Files could be copied using a removable storage card, accessed from a Web site, beamed from another device, or copied from a network share. Since the emulator doesn't support the hardware-based solutions, we'll use the network share approach (which will also work for hardware devices with network connectivity).
- Create a network share point for the application.
- Create a directory on your desktop machine to house the application and framework CAB files.
- Create a share to this directory.
- Copy the appropriate application and .NET Compact Framework CAB files to this directory.
- (optional) Devices typically have a significantly reduced screen size and thus visually truncate long names. So you may find it handy to rename the CAB files to have shorter filenames (so that the filenames will be clear when viewed on the device).
- Copy the files over the network.
- On the device, click the Network Share icon at the bottom of the device (see Figure 5).
Figure 5. Network Share icon on the device
- This brings up the network Open dialog box. Enter the name of your desktop machine to view the available shares, or enter the full UNC share name to connect to the appropriate directory.
Note You may receive an error message saying that a device of that name already exists on the network. If you get this error, you should rename your device. To do this, perform the following steps on the device:
1. Choose Settings from the Start menu
2. Select the System tab
3. Click or tap the About icon
4. Select the Device ID tab
5. Enter a new Device name
6. Click or tap the OK button in the upper right corner of the dialog box.
- If you receive the Logon to Network Server dialog box, enter your User name, Password, and Domain. Check Save password to prevent having to do this again.
- Your device should now show the contents of the shared directory (see Figure 6).
Figure 6. Shared Directory on the Desktop Machine
- To copy the .NET Compact Framework CAB file to your device, select the CAB file (by holding down the pen or mouse button) and choose Copy from the popup context menu.
- Now navigate to a directory on your device (Suggestion: \My Documents). Click Edit at the bottom of the device, and choose Paste. You should then see a dialog reporting the progress of the copy operation.
- Click or tap the CAB file to perform the installation. The .NET Compact Framework is installed on the device and the CAB file is deleted to save space.
Note You may receive an error message saying that "The application cannot run on this device type". This indicates that you have copied over the wrong CAB file, so you need to back up and get the right CAB file.
- Finally, repeat these steps for the application's CAB file. This creates a subdirectory under "\Program Files" with the name of the application and installs the application and any related files there (see Figure 7).
Figure 7. "HelloWorld" Application on the Device
- On the device, click the Network Share icon at the bottom of the device (see Figure 5).
- One final operation you may want to perform is to create a shortcut for the program on the device's Start menu.
- Locate the HelloWorld application file in the "\Windows\Hello World" subdirectory.
- Select the file and hold down the button (or stylus for a real device) to get the context menu, and select Copy.
- Navigate to the "\Windows\Start Menu\Programs" subdirectory, click or tap the Edit menu in the lower-left corner, and choose Paste Shortcut.
- Since the default name for the shortcut starts with "Shortcut to . . ." (see Figure 8), you might take this opportunity to rename the shortcut.
Figure 8. "HelloWorld" Shortcut on the Device
So, what really happened when you created and ran the "HelloWorld" SDE application? The most important thing to be aware of is that—when you chose to create an SDE project—you actually started with a different template than you would have for a desktop project. In particular, you were actually developing against the .NET Compact Framework rather than the full version of the framework.
Let's examine the structure of the "HelloWorld" program you just built (actually, you can use any SDE programming project). Figure 9 shows how the project is put together.
- Open the Solution Explorer window.
- Expand the References node.
- Select a reference (such as System).
- Look at the Path in the Properties window.
- C:\Program Files\Microsoft Visual Studio .NET\
Figure 9. SDE References
When developing desktop applications, you use the .NET Framework assemblies located in the Global Assembly Cache. And these assemblies are found in that location on every desktop machine that has the .NET Framework installed. When programming for a device, however, you need to use the assemblies that will actually be deployed to the device. When you installed the SDE, these assemblies were copied into the "\CompactFrameworkSDK\v1.0.3300\Windows CE" subdirectory below Microsoft Visual Studio .NET. And if you look below that directory, you will find subdirectories named "arm", "mips", "sh3", and "x86" that correspond to processor types that the .NET Compact Framework supports: These subdirectories contain the redistributable CAB files mentioned above in the section on deploying "HelloWorld".
A little bit of background information might make this easier to understand. When you build a project using Visual Studio .NET, your source code is compiled into one or more assemblies (with .EXE and .DLL file extensions). These .NET assemblies contain metadata and Microsoft Intermediate Language (MSIL) code. They do not contain natively executable code. Instead, the MSIL code is just-in-time (JIT) compiled into native code at runtime. Of course, your application is making extensive use of types defined in the .NET Framework class library, which in turn is really a collection of assemblies—with metadata and MSIL—compiled by Microsoft and stored in the .NET Framework runtime directory on your desktop machine.
As you may have guessed, this same process is used by the SDE to build assemblies that use the .NET Compact Framework. And because these assemblies contain MSIL rather than native code, you can actually program against the exact same .NET Compact Framework assembly on your development machine as is deployed to the device! You may wish to examine one of the .NET Compact Framework assemblies—for instance, system.dll—in detail using the ildasm.exe tool that comes with the .NET Framework SDK and is installed with Visual Studio .NET (see Figure 10).
Figure 10. ILDASM of system.dll for .NET Compact Framework
Installing the Smart Device Extensions (SDE) for Visual Studio .NET will also install the 111 MB .NET Compact Framework SDK in C:\Program Files\Microsoft Visual Studio .NET\CompactFrameworkSDK. SDE also updates Visual Studio .NET in several subtle ways. For instance, one of the features of SDE is the ability to deploy and test using a smart device emulator. To configure the emulator, choose Options from the Tools menu, select the Device Extensions tab, choose Devices, and finally select Pocket PC Emulator.
Figure 11. TabControl TabPages Collection Editor
The most important configuration option is the reduced screen size, which is typically 240 × 320 pixels.
SDE also gives you an additional Build menu option to deploy directly to the device. There are also Build menu items to handle a batch build—which builds for multiple project (device) configurations at one time—and for creating a CAB file for distribution.
Perhaps the biggest challenge of working with small devices is their hardware limitations. Screen size is obviously reduced—again, 320 × 240 pixels is common—but processing power is lower (primarily to conserve battery life), memory—which is normally also used for storage—is also much smaller, and input methods are somewhat different. In fact, the typical target device for SDE will have between 16 MB and 64 MB of memory, which must be shared between storage of programs as well as memory for those programs that are running.
The full .NET Framework includes a substantial class library as well as the Common Language Runtime (CLR) and other features, for instance ASP.NET. The complete .NET Framework—which is available in a 16 MB CAB file for distribution—consumes around 43 MB of disk space when installed on a desktop machine (the total disk space requirements are double that, most of which is the Global Assembly Cache). And the smallest Windows Forms program has a working set of greater than 8 MB. Both the storage and memory requirements of the full .NET Framework are clearly too large for portable devices with limited hardware capabilities.
Installing the .NET Compact Framework on a device consumes approximately 1.3MB of disk space (versus a total file size of 2.0 MB due to Windows CE file storage optimization). Running a SDE program on the device will load the Common Language Runtime (CLR) as well as the application code, so the minimum memory requirement of a Windows Forms SDE program is about 1 MB. Additional running copies of such an application will consume somewhat less memory (around .75 MB each).
Since the total file size of the .NET Compact Framework is approximately 1/20 the size of the full .NET Framework, and (for example) a Windows Forms device program requires about 1/8 as much memory, it should be obvious that the .NET Compact Framework has been heavily optimized in several ways.
Smart devices don't need to be ASP.NET Web servers (though this is certainly an intriguing idea), thus they also do not need support for Web Forms or any of the language compilers included with the full .NET Framework. And since you are developing the application on a desktop and then deploying to the device, you don't need support on the device for such developer-oriented features as visual designers or server features like Active Directory and Enterprise Services. The following table shows the total size (in KB) of the files that make up the major namespaces in both the full and compact versions of the .NET Framework:
Table 1. Class Library Namespace Sizes (in KB)
|1,374||140||Microsoft (languages & support)|
Note These sizes do not reflect the compressed size of the .NET Compact Framework on a Windows CE production device, which is around 1.5 MB.
Visual Basic Support Library
One of the areas where the most functionality was preserved when moving to device programming for .NET is the Visual Basic .NET support library, contained in the "Microsoft.VisualBasic.dll" assembly. While Visual Basic .NET no longer has its own runtime (it uses the same Common Language Runtime and .NET Framework as all other .NET application), Microsoft has provided this support assembly with many types, functions, and constants to provide compatibility with previous versions of Visual Basic. And the .NET Compact Framework version of this DLL preserves most of this functionality (it's around one half the size of the full version).
In particular, the device version of this library includes full support for the Collection class, type conversion functions, control characters, DateTime, MsgBox, and common constants such as CrLf. However, support for the following things was removed:
- FileAttributes, FileSystem, and Open constants
- Variants (vbArray, vbBoolean, vbNull, and other Variant data types, as well as VarType functions)
- Casing , language, and other string conversions
- Len function (other than for strings)
- AppActivate, Shell, and Environment functions
- CreateObject, GetObject, CallByName
Most of these make perfect sense when you think about the reduced features of the .NET Compact Framework. For instance, Windows CE has its own file system so device-based file I/O code is substantially different. And the .NET Compact Framework does not include support for interoperability with COM components, so there's no need for COM-related functions (like CreateObject) or Variants (to work with COM data types).
Most smart device programs involve some form of Windows-based user interface, so the changes made to the Windows Forms will be of great interest to developers wanting to write programs for these smaller form-factor devices. And since Visual Basic programmers are already familiar with forms-based applications, this is an area where much of your prior experience will carry forward.
To start with, here's a list of controls that are included with the .NET Compact Framework version of Windows Forms:
As you can see, the basics—and more—are still there and it's easy to build the kind of small applications and utilities that are particularly appropriate for smart devices. However, some of the more advanced controls from the full version of the .NET Framework are not available. Many of these advanced controls—such as Command, PropertyStore, and ToolTip—are either not appropriate for small devices or would have required very different implementations under Windows CE. Some controls—like the Splitter—would require involved user interface actions that are somewhat at odds with the way most users operate these devices. And still other controls—like the CheckedListBox—can be simulated anyway by combining other, lower-level controls. You will also find that some other functionality from the full version of Windows Forms are also not available, including HTML Help and features that communicate directly with the underlying operating system such as NativeWindows, SendKeys, OSFeature (used for Theme support), and SystemInformation.
Form and controls
As a rough guide, the .NET Compact Framework version of the Form supports more than three quarters of the events and methods and about half of the properties of the Form in the full version. You can set the colors, certain style properties, and include a menu. What you can't do is create an MDI application, show the form in the taskbar, implement drag and drop, and respond to certain keyboard events (like the Cancel button) that are not appropriate for small devices.
Let's look at one specific control—the TabControl—and see what has remained the same and what has changed for the .NET Compact Framework version. You still construct the tab pages using the TabPage Collection Editor:
Figure 12. TabControl TabPage Collection Editor
You have fewer options for customizing the appearance of individual tab pages, and you also don't have support for advanced feature areas as Behavior (Drag/Drop, ContextMenu, and IME mode) and AutoScroll. However, these properties are used infrequently and the only commonly used property that's missing is the Tag. The same is true for the TabControl itself: the basic user interface properties are there, but some features—such as ContextMenu and ToolTipText—aren't appropriate for Windows CE devices and aren't included. Others features were eliminated simply to reduce the size of the control. And some feature areas—like Accessibility and DataBinding—were dependent on yet other features of the .NET Compact Framework which were also not included.
The smaller screen size of mobile devices will likely mean that the user interface must be completely redesigned. For the most part, you only need to worry about these missing controls when you are attempting to port an existing application to the smart device, in which case you are likely to be redesigning the user interface anyway.
Because a mobile device may have a small keyboard or an on-screen representation of a keyboard, text entry is not as easy on a mobile device as it is on a desktop or laptop computer. You may need to rethink how the user interacts with the application to make the most of a touch screen or dedicated hardware buttons.
The .NET Compact Framework SDK that comes with SDE includes a selection of sample programs that illustrate the basics of what you might accomplish on the small device platform and may serve as starting points for you own application ideas. These samples include:
- Bubble—Drawing and filling graphics shapes on a Windows Form with a brush. Also demonstrates thread creation.
- Calculator—Demonstrates Windows Forms including controls and event handling.
- Scribbler—Classic "Scribble" drawing program, uses GDI+ to draw on a Windows Forms. Also illustrates utilizing an off-screen drawing surface and tracking mouse movement.
- Inventory—Demonstrates dataset-to-XML serialization, ADO.NET to SQL Server, and Windows Forms. Also shows loading image resources from content files.
- Stock Quote—Calls an XML Web service using Windows Forms. Also includes the XML Web service.
- WaitCursor—Declares and accesses the Win32 API.
There are also two samples that accompany this whitepaper to illustrate specific programming points about developing for smart devices using Visual Basic:
- Authors—Loads a ListView from a DataSet created from an XML document.
- PowerStatus—Declares and accesses the Win32 API on Windows CE.
Using the ListView
One of the controls that Visual Basic developers use most often is some form of grid for displaying tabular data. Though the .NET Compact Framework does not include a grid, developers can simulate much of a grid's appearance using the ListView control:
Figure 13. ListView Sample on device
The Authors sample that accompanies this whitepaper shows you how this works. The first thing we need to do is get the data onto the device, and this is done in this sample by copying an XML file across during the deployment process. First, the file is added to the project, normally using the Add Existing Item option from the Solution Explorer.
You may also specify where on the device the executable—and this file—are to be deployed. This is done by either setting the Output File Folder in the project's Properties window, or by accessing the project's Properties dialog box, selecting Device Extensions within the Common Properties node, and entering a path for the Output file folder. In this sample we used \Samples\VB.NET, so in the code itself we also point to the file in this location:
Private Const AUTHORSXML As String = "\Samples\VB.NET\AuthorsDB.xml"
We then declare a DataSet:
Private dsAuthors As System.Data.DataSet
Now we're ready to load the DataSet from the XML file using the ReadXml method:
Private Sub loadXMLData() dsAuthors = New DataSet("AuthorsDB") Try Dim fs As New FileStream(AUTHORSXML, FileMode.Open) Dim xr As New XmlTextReader(fs) dsAuthors.ReadXml(xr) xr.Close() fs.Close() Catch e As System.IO.FileNotFoundException MessageBox.Show("File " & AUTHORSXML & " not found.") Catch e As XmlException MessageBox.Show("XmlException occured") End Try End Sub
And here's the Form's Load event, which calls the loading routine and then iterates through the DataSet, adding each row to the ListView control:
Private Sub frmAuthors_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load loadXMLData() Dim dr As DataRow Dim it As ListViewItem For Each dr In dsAuthors.Tables("Authors").Rows it = New ListViewItem(dr("id").ToString()) it.SubItems.Add(dr("name").ToString()) it.SubItems.Add(dr("phone").ToString()) lvCompanies.Items.Add(it) Next End Sub
Finally, just like the ListView control in the full version of the .NET Framework, you can set up the properties—like the Columns—either at run time or using the Properties editor:
Figure 14. ListView Columns Collection
Calling a Web Service
Okay, let's now examine calling a Web Service from a device. The sample code for both the Web Service and the SDE project can be found in the StockQuoteService and StockQuote sample projects respectively. Unlike the XML file described in the ListView sample, in this sample we are including the XML file in the main assembly. To have the file built with the assembly, you need to set the Build Action property of the XML file to Embedded Resource.
The StockQuoteService Web service itself is not specific to desktop or smart devices and contains just a single WebMethod function (with error handling code not shown):
<WebMethod()> _ Public Function getQuoteDataSetX() As DataSet Dim dsIn As New DataSet() Dim sIn As Stream = [Assembly].GetExecutingAssembly(). _ GetManifestResourceStream _ ("StockQuoteService.stockdata.xml") Dim srXMLReader As New StreamReader(sIn) dsIn.ReadXml(srXMLReader) srXMLReader.Close() sIn.Close() Return dsIn End Function
Since the resource is part of the assembly, we need to use the GetManifestResourceStream method to pull the named resource into a Stream, from which we then read the XML using the DataSet.ReadXml method.
The StockQuote client that consumes the Web service looks like the following:
Figure 15. StockQuote Sample on device
And just like we would when developing a desktop client for a Web service, we need to obtain a reference to the StockQuoteService.asmx file:
After obtaining a reference to the Web service, retrieving the data into a DataSet can be as simple as using the following three lines of code:
Private sq As New StockQuoteService.StockQuoter() Private ds As DataSet ds = sq.getQuoteDataSet()
As with the XML file described in the Web service, this client sample also uses embedded graphic files, which are retrieved using the GetManifestResourceStream method.
Calling an API
Visual Basic programmers have traditionally made direct calls to Windows (and other) DLLs to access functionality that was not encapsulate and provided by the VB language and runtime. Originally used for working with INI files—and later the Windows registry, Microsoft Win32® APIs have commonly been used for more advanced functions like process synchronization (for example, WaitForMultipleObjects) and graphic operations (for example, BitBlit, StretchBlit, and so on). While most of these functions are now exposed through the literally thousands of classes in the base Framework Class Library, some applications may still choose to implement selected Win32 APIs—such as GetPrivateProfileString—that have no equivalent in the .NET Framework. In managed code, this process is part of the InterOp services called PInvoke (for Platform Invocation). Note that when using PInvoke, it is up to the author of the program to take into account—and program for—any security-related issues when calling unmanaged code.
And where the .NET Compact Framework implements a subset of the full Framework Class Library, PInvoke can be used to regain much of this omitted functionality by calling the underlying Windows CE APIs directly. For example, the .NET Compact Framework version of Windows Forms does not provide an implementation for the Cursor class. Fortunately, the LoadCursor and ShowCursor APIs in the Win32 API can be used to change cursors. In Windows CE, these functions are located in coredll.dll, and their declaration looks like the following:
Declare Function LoadCursor Lib "coredll.dll" (ByVal zeroValue As Integer, ByVal cursorID As Integer) As Integer Declare Function SetCursor Lib "coredll.dll" (ByVal cursorHandle As Integer) As Integer
You can use a tool—such as the API Text Viewer included with Visual Basic 6.0—to do most of the work in figuring out what an appropriate Declare statement. You may also need access to the Windows CE SDK to give you the specifics call as they relate to the Windows CE platform. In particular, you will also need to provide the appropriate constants and—where required—structures. For example, to set a cursor to one provided by Windows it is necessary to know the numeric value of the cursor, for instance:
Private hourGlassCursorID As Integer = 32514 ' &H7F02
At this point, setting the desired cursor is quite simple:
cursorHandle = LoadCursor(0, hourGlassCursorID)
A complete program showing how this works can be found in the WaitCursor sample included with the .NET Compact Framework SDK samples. Note that the "hourglass" cursor appears substantially different on the handheld device.
Windows CE API
Of course, there are also some features that are unique to the Windows CE platform that can also be called through PInvoke. The GetSystemPowerStatusEx API, for example, is unique to Windows CE and can be used to retrieve information about the Extended battery, which is not part of the standard Win32 API. The declaration of this function is slightly more complicated than the above examples:
Declare Function GetSystemPowerStatusEx Lib "coredll" _ Alias "GetSystemPowerStatusEx" _ (<[In](), Out()> ByVal lpSystemPowerStatus As SYSTEM_POWER_STATUS_EX, _ ByVal fUpdate As Boolean) As Long
The first thing to notice in the declaration is the specification of the parameter types. They can be used to specify which parameters are being passed out and which parameters will be returned containing the desired information. Since "In" is also a Visual Basic keyword, it is necessary to enclose it in square brackets. The "In" and "Out" types are actually defined by InteropServices and it is necessary to import this namespace:
The next thing you will note is the SYSTEM_POWER_STATUS_EX structure that is returned by the function. This can be handled using a Structure or by placing the structure definition in a class and by specifying that the members are arranged sequentially:
<StructLayout(LayoutKind.Sequential)> _ Public Class SYSTEM_POWER_STATUS_EX Public ACLineStatus As Byte Public BatteryFlag As Byte Public BatteryLifePercent As Byte Public Reserved1 As Byte Public BatteryLifeTime As Int16 Public BatteryFullLifeTime As Int16 Public Reserved2 As Byte Public BatteryBackupFlag As Byte Public BackupBatteryLifeTime As Byte ' DocBug Public Reserved3 As Byte Public BackupBatteryLifePercent As Byte 'DocBug Public BackupBatteryFullLifeTime As Byte End Class
Note that two of the members—BackupBatteryLifeTime and BackupBatteryLifePercent—are actually reversed from what is documented.
Now calling this function is also straightforward:
Dim sps As New SYSTEM_POWER_STATUS_EX() ret = GetSystemPowerStatusEx(sps, False)
Running the sample program and the corresponding Power tab from the System applet in Settings on an iPAQ with an external sleeve attached (which contains an external battery) and with the device running on battery and in a partially discharged state shows the following:
Figure 16. GetPowerStatusEx and Power on discharging device
It is important to note that not all of the fields of the structure are necessarily used. For example, the iPAQ does not report the Battery Backup Flag or Charging state for the external battery in the sleeve, so not all information can be displayed by either the sample program or the built-in Power display.
As a Visual Basic programmer, you will likely have existing application code that you may be interested in porting to this new platform based on the .NET Compact Framework. You may have a desktop application written against the full framework, or perhaps even programs developed using an older version of Microsoft's tools for small devices, particularly Embedded Visual Basic 3.0.
Migrating an application developed for the full version of the .NET Framework to SDE is not particularly difficult, though it can be time consuming. If you have your desktop version open in one instance of Visual Studio .NET and create an SDE project in a second instance, you will find that you can copy many of the controls from the desktop version of the form and paste them into an SDE form. Common properties will be preserved. Of course, you won't be able to do this with controls that aren't supported in the .NET Compact Framework so, if your application depends on event code associated with these controls, you will have to rework that part of your application. And you will also have to spend some time shrinking down the controls to fit the smaller screen size of the smart device.
Procedural code, on the other hand, should move over more easily. Within the definition for a Form, you will find that you can copy over most declarations and event handling code. Where you access objects and object members that are not present in the .NET Compact Framework, you will generate a list of TODO items in the Task List that will need attention before your application will compile.
Moving an application developed using Embedded Visual Basic 3.0 will require substantially more work. In particular, this older version of Visual Basic is more like VBScript than the familiar desktop Visual Basic. It only supported the Variant data type, User Defined Types (UDTs) were not supported, and most of the controls used in the desktop versions of Visual Basic were not available. And applications developed with this older generation of tools were built using COM-based components, data access and controls: none of these are available from the .NET Compact Framework. In the end, you will likely end up having to develop an entirely new application.
This whitepaper was written to give you, the Visual Basic developer, an understanding of what it is like to program for smart devices using the Smart Device Extensions (SDE) for Visual Studio .NET. We covered the differences between the .NET Framework and the .NET Compact Framework. We also walked you through the entire development, debugging, and deployment process. Even if you do not have access to a smart device, you can still develop for this platform using the full-function software emulator.
At the same time, we didn't cover every aspect of SDE development. There are additional areas for Visual Basic developers to explore after they get up to speed with developing applications for smart devices. In particular, developers might wish to experiment with writing their own custom controls. Also, a separate install is available for Microsoft SQL Server™ Windows CE Edition if your application requires rich database functionality on the device itself.
Note The screen captures in this whitepaper were taken both directly from the software emulator as well as using the Remote Display Control. If you want to capture screens from your device—perhaps for documentation—you can find the Remote Display Control on Microsoft's Mobile Devices Web site.
For more information about Visual Studio .NET and the .NET Compact Framework, see the Visual Studio .NET Device Development Web site.