![]() |
Platforms, Frameworks & Libraries »
Mobile Development »
User Interface
Intermediate
Optimizing your Mobile .NET 3.0 WPF Application for a UMPC or Touch-enabled PCBy Todd LandstadA simple application that is optimized for varying screen sizes and includes power/network status. |
C# 2.0, C# 3.0WinXP, Vista, .NET 3.0, Visual Studio, WPF, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||

The Ultra-Mobile PC is still a relatively new form factor in the PC World. I've written a sample application that illustrates some of the published design guidelines for UMPC's and includes a managed Power and Network aware class so you can add this functionality to your application.
Ultra-Mobile PC's are a great new addition to the set of hardware platforms to run your applications. They run XP, and now Vista, and being very small and light they are well suited for mobile use. From a development point of view there is not that much to do (if anything) in order to make sure your application runs well on this PC's. The sample I've created focuses on three things:
The sample includes the InkCube WPF sample that ships in the Windows Vista SDK as the main window content. I added this to have something of interest in this application, but this could be any XAML code.
The sample I chose allows you to create ink on any side of a cube and in real-time. The ink is rendered on the cube while it is rotating (see screen shot). In adding the sample, however, I did modify the layout and controls slightly to be optimized for the smaller resolution touch displays.
In looking at the Origami Experience product that Microsoft ships on UMPC's, I created a 'headerbar' in XAML with some C# back-end code to provide my user with information about the system. The information is comprised of items that add value to a mobile user: Battery status, network connection status and system time/date.
There are many articles that include sample code for this functionality (such as this one by Dr.Neil Roodyn: Mobile PC Power Management) but I have included the managed wrappers for both network and power notification for use in this WPF application. I also added a few simple icons and tooltip data for the user and combined the two sets of notifications (Power and Network Status) into one class in the application.
The following sections detail the code I used and reasons for some of the layout choices:
/// <summary />
/// Toggle between windowed and full-screen mode
/// to make use of the full abmount of screen real estate
/// </summary />
void OnFullScreenClick(object sender, RoutedEventArgs e)
{
if (Application.Current.MainWindow.WindowStyle != WindowStyle.None)
{
// Show the minimize/close buttons only when in full screen
this.MinimizeControl.Visibility = Visibility.Visible;
this.CloseControl.Visibility = Visibility.Visible;
//Set the window style and state to be borderless and maximized
Application.Current.MainWindow.WindowState = WindowState.Maximized;
Application.Current.MainWindow.WindowStyle = WindowStyle.None;
// Set the text to the restore symbol (using Martlett font)
this.FullScreentext.Text = "2";
}
else
{
// Hide the minimize/close buttons when windowed
this.MinimizeControl.Visibility = Visibility.Collapsed;
this.CloseControl.Visibility = Visibility.Collapsed;
//Set the window style and state to be 'normal' windowed
Application.Current.MainWindow.WindowStyle =
WindowStyle.SingleBorderWindow;
Application.Current.MainWindow.WindowState = WindowState.Normal;
// Set the text to the maximize symbol (using Martlett font)
FullScreentext.Text = "1";
}
}
Even though this is a WPF sample, I still work with a lot of developers using Native C++ Win32 APIs. Just in case you want this type of behavior in your Win32 application, here is the C++ version:
// Toggle the window mode to/from fullscreen
BOOL ToggleFullScreen(HWND hWnd)
{
WINDOWINFO wi;
WINDOWPLACEMENT wp;
long lWindowStyle = GetWindowLong(hWnd, GWL_STYLE);
GetWindowInfo(hWnd, &wi);
GetWindowPlacement(hWnd, &wp);
// Is the window in fullscreen mode right now?
if(wp.showCmd == SW_SHOWMAXIMIZED)
{
// We are full screen, switch to windowed
SetWindowLong(hWnd, GWL_STYLE, lWindowStyle | WS_BORDER );
wp.showCmd = SW_SHOWNORMAL;
wp.length = sizeof(wp);
SetWindowPlacement(hWnd, &wp);
}
else
{
// We are windowed, switch to full screen
SetWindowLong(hWnd, GWL_STYLE, lWindowStyle & ~WS_BORDER );
wp.showCmd = SW_SHOWMAXIMIZED;
wp.length = sizeof(wp);
SetWindowPlacement(hWnd, &wp);
}
return true;
}
PowerNetworkAware class and add handlers to watch for system changes to either power or network status. The calls for both of these topics are still from Win32, but the managed wrappers are included to make it easier to call from .NET. Here is a snippet of that code:
void OnLoaded(object sender, RoutedEventArgs e)
{
// Create the power and network aware class
powerAndNetworkStatus = new PowerNetworkAware();
// Register a delegate for the power related event
powerModeChangeHandler = new
PowerModeChangedEventHandler(OnPowerModeChange);
SystemEvents.PowerModeChanged += powerModeChangeHandler;
// Register a delegate for the network related event
networkChangedHandler = new NetworkAvailabilityChangedEventHandler(
NetworkChange_NetworkAvailabilityChanged);
NetworkChange.NetworkAvailabilityChanged += networkChangedHandler;
// Wire up power awareness
UpdatePowerStatus();
// Wire up network status
UpdateNetworkStatus();
}
The event handlers simply call the UpdatePowerStatus or UpdateNetworkStatus helpers to update the PowerNetworkAware class data and then choose which icons to display.
/// <summary />
/// Invoked when the network status changes.
/// Changes icon and tooltip accordingly.
/// </summary />
void UpdateNetworkStatus()
{
this.powerAndNetworkStatus.EnumerateNetworks();
ToolTip myTooltip = new ToolTip();
myTooltip.Content = powerAndNetworkStatus.currentNetworkLabel;
this.NetworkStatusIndicator.ToolTip = myTooltip;
String networkImageName = @"Images/wirelessgood.ico";
if (powerAndNetworkStatus.networkStatus == "Disconnected")
{
networkImageName = @"Images/wirelessnone.ico";
}
else if (powerAndNetworkStatus.networkStatus == "Connectivity Lo")
{
networkImageName = @"Images/wirelesslow.ico";
}
// Create source.
BitmapImage bi = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block.
bi.BeginInit();
bi.UriSource = new Uri(networkImageName, UriKind.RelativeOrAbsolute);
bi.EndInit();
this.NetworkStatusIndicator.Source = bi;
}
The icons for power and network will update themselves based on the system events above. Since your machine may be connected to more than one network, I've chosen to display the status, name and speed of the fastest available network. So if you're running on a notebook/tablet with both wireless and wired Ethernet, you'll get the status of the wired connection until you un-plug it.
I've added a click handler for these items as well so the user can get to the associated control panel applets. Following is the code I used for this:
void PowerStatusClick(object sender, RoutedEventArgs e)
{
Process.Start("rundll32", "shell32,Control_RunDLL powercfg.cpl");
}
void NetworkStatusClick(object sender, RoutedEventArgs e)
{
Process.Start("rundll32", "shell32,Control_RunDLL ncpa.cpl");
}
Microsoft has published a Mobile PC Development Guide that suggests best-practices for developing Mobile PC and UMPC applications. This sample attempts to use those principles in its design. The main items to consider here are to:
Other considerations for power management are to disable CPU intensive functionality if the PC is on battery or if the application is minimized. In this sample, I could have chosen to disable the rotating, animated cube if the application is minimized or not in the foreground. This would reduce the load on the CPU and in turn, save battery power.
Aside from the design guidelines and existing Power/Nework samples I used in researching this, I found the Viewbox in WPF to be the perfect control in making the content of my application scale well for any resolution/display. Each of the controls I used for the header bar are a gray-based gradient so they remain colourless. This is interesting since I chose to load whatever desktop image that Windows is currently using as the background of this sample. Having colourless controls enables them to work well with any background color/image.
9th of March, 2007 - Created article
| You must Sign In to use this message board. | ||||||||
|
||||||||
|
||||||||
|
||||||||
|
||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 20 Mar 2007 Editor: Sean Ewington |
Copyright 2007 by Todd Landstad Everything else Copyright © CodeProject, 1999-2009 Web20 | Advertise on the Code Project |