Developing Power Efficient Desktop Applications for Ultrabook™ on Windows* 8

Mobile computing has been one of the most disruptive technological advancements we have seen in this decade. As mobile devices are gaining ground rapidly, power-efficiency continues to be a critical factor of mobile design. Hardware OEMs and operating system vendors are all taking the necessary precautions to utilize power judicially. The availability of smart sensors on devices, like smartphones, tablets, and Ultrabook™ devices, enables application developers to create power-aware applications that contribute to increased battery life of a mobile device. An application can monitor changes in battery percentage and can disable or optimize resource intensive tasks when the battery level falls below certain thresholds.

For example, consider a Photo Application with geo-tag functionality that allows users to tag the location of the picture automatically using the GPS data available on the device. When this application detects low battery, it could notify the user and disable geo-tagging to conserve power, thereby extending battery life.

In this article, we discuss the current power source type and its different readings. We can use unmanaged Windows* APIs to detect the current source and readings. An effort is made to illustrate event-raising and event-handling mechanisms when power source changes. The article also demonstrates incorporating unmanaged code into the managed application.

Implementation

There are no direct APIs available in .NET that provide access to power management functions such as detecting the current power source, current power policy, change in power source, etc. Windows has native unmanaged DLLs that developers can use to access power-related functions. DllImport is a way to access native DLLs in .NET. We can create a Utility class, PowerMngrHelper, in .NET that provides various methods to deal with power-related activities. PowerMngrHelper is a wrapper class that uses DllImport and provides simpler methods for power management. It also has various methods that provide notifications about power-related events.

Step: 1

Declare the private variable of the PowerMngrHelper type into the MainWindow class.

 class MainWindow : Window { //Member variables //Provides power management functions. PowerMngrHelper powerHelper; ..... } 

Step: 2 Register for power source change and battery capacity change events

In MainWindow_Loaded() method, create an instance of PowerMngrHelper and register for PowerSourceChanged and BatteryCapacityChanged events. These events will be invoked whenever there is a change in the power source and a change in the battery capacity, respectively. PowerMngrHelper's constructor accepts "Window" as an argument, so pass 'this' as an argument variable.

 class MainWindow : Window { public MainWindow_Loaded() { //Create instance of PowerMngrHelper. powerHelper = new PowerMngrHelper(this); //Register for power source change notification. powerHelper.PowerSourceChanged += powerHelper_PowerSourceChanged; //Register for battery capacity change notification. powerHelper.BatteryCapacityChanged += powerHelper_BatteryCapacityChanged; ..... } ..... } 

Step: 3

When a device detects a change in power source, it notifies the event handler. We have already registered for this "PowerSourceChanged" event in the MainWindow_Loaded() method. Call the SetPowerSource() method of MainWindowViewModel to set the new power source value.

 class MainWindow : Window { //Event handler notified when power source is changed void powerHelper_PowerSourceChanged(object sender, EventArgs args) { //Set the current power source. vm.SetPowerSource() } ..... } 

In the MainWindowViewModel class, write a method SetPowerSource() to set the new power source value. MainWindow will call this method when it is notified with PowerSourceChanged event as mentioned above. If the system is running on AC power, set the PowerState accordingly; if it is running on battery, then set the battery percentage. It uses the PowerMngrHelper static method GetBatteryState() to get the current power source.

 class MainWindowViewModel : ViewModelBase { //Detects current power source using PowerMngrHelper and assigns value to "PowerState" property. public void SetPowerSource() { SYSTEM_POWER_STATUS power_status = PowerMngrHelper.GetPowerState(); if (power_status.LineStatus == ACLineStatus.Online) // AC Power { PowerState = "AC Power"; //System is running on AC power. } else { SetBatteryLife(); //Set the battery percentage. } } ..... } 

Step: 4

When the device detects a change in battery capacity, it notifies the event handler. We have already registered for this "BatteryCapacityChanged" event in the MainWindow_Loaded() method. Call the SetBatteryLife() method of MainWindowViewModel to set the new battery percentage value.

 class MainWindow : Window { //Event handler notified when battery capacity is changed void powerHelper_BatteryCapacityChanged(object sender, EventArgs args) { //Set the battery percentage. vm.SetBatteryLife(); } ..... } 

In the MainWindowViewModel class, write a method SetBatteryLife() to set the new battery percentage value. MainWindow will call this method when it is notified with a BatteryCapacityChanged event as mentioned above. It uses the PowerMngrHelper static method GetPowerState() to get the current battery percentage.

 class MainWindowViewModel : ViewModelBase { // Detects current battery level using PowerMngrHelper and assigns value to "PowerState" property. public void SetBatteryLife() { //Set the battery percentage. SYSTEM_POWER_STATUS power_status = PowerMngrHelper.GetPowerState(); PowerState = string.Format("{0}%", power_status.BatteryLifePercent.ToString()); .…. } ..... } 

Step: 5

Declare public property to provide access to the power source or battery percentage if running on battery. Implement INotifyPropertChanged interface to provide auto-notification when a new value is set to the underlying "_powerSource" variable.

 class MainWindowViewModel : ViewModelBase { //Create public property public string PowerSource { get { return _powerSource; } set { if (_ powerSource != value) { _ powerSource = value; //Raises notification when new value is set for this variable. OnNotifyPropertyChanged("PowerSource"); } } } ..... } 

Step: 6

PowerMngrHelper class also provides methods to deal with power policies, such as get or set the current power policy (scheme). Let’s consider a case where we want to activate the power saver scheme when the battery falls below a certain threshold value (say 25%) and restore the previous scheme when the battery capacity moves above that threshold value, or the system is running on AC power. This can be achieved by the following code.

Step: 6.1

In the MainwindowViewModel class, create a variable of type Guid to store the original power scheme.

 class MainWindowViewModel : ViewModelBase { // Member variables. //Store the device current power scheme. private Guid originalPowerScheme; .…. } 

Step: 6.2

In the SetPowerSouce() method, add the code below to restore the saved power scheme when the system is running on AC power.

 class MainWindowViewModel : ViewModelBase { public void SetPowerSource() { SYSTEM_POWER_STATUS power_status = PowerMngrHelper.GetPowerState(); if (power_status.LineStatus == ACLineStatus.Online) // AC Power { …. //Restore to previous power scheme. if (originalPowerScheme != null) PowerMngrHelper.SetActivePowerScheme(originalPowerScheme); …. } else { …. //Store the current power scheme. originalPowerScheme = PowerMngrHelper.GetActivePowerScheme(); …. } } ..... } 

Step: 6.3

In the SetBatteryLife() method, add the following code to activate the power saver scheme when the battery is below the threshold value and activate the stored power scheme when the battery is above the threshold value.

 class MainWindowViewModel : ViewModelBase { public void SetBatteryLife() { ….. //Check whether battery under threshold value or not. if (power_status.BatteryLifePercent < BatteryThreshold) { …. //Activate the "Power Saver" power scheme. PowerMngrHelper.ActivePowerSaverScheme(); …. } else { …. //Restore to previous power scheme. if (originalPowerScheme != null) PowerMngrHelper.SetActivePowerScheme(originalPowerScheme); …. } .…. } ..... } 

Step: 7 Enable/Disable GPS sensor for location

As we know, using the PowerMngrHelper utility we can get the battery capacity changed notification. Upon receiving such notifications, we can start/stop some specific resource intensive tasks like GPS sensor, camera, etc. Let’s consider a case where we want to disable the location access when the battery falls below a certain value (say 25%) and enable it again when the battery capacity goes beyond that value or the system is running on AC power. This can be achieved by following these steps.

Step: 7.1

In the MainWindowViewModel class, create two event handlers as shown below to let the view know when the battery moves above or below the threshold value.

 class MainWindowViewModel : ViewModelBase { // Member variables. …. // Event handler to notify the battery percentage is below threshold value. public event EventHandler<EventArgs> BatteryBelowThreshold; // Event handler to notify the battery percentage is above threshold value. public event EventHandler<EventArgs> BatteryAboveThreshold; .…. } 

Step: 7.2

In the MainWindow constructor, register for the previous two event handlers.

 class MainWindow : Window { public MainWindow() { //Register to get battery below threshold notification. vm.BatteryBelowThreshold += vm_BatteryBelowThreshold; //Register to get battery above threshold notification. vm.BatteryAboveThreshold += vm_BatteryAboveThreshold; ..... } ..... } 

Step: 7.3

In the MainWindow class, create two methods as per below. These methods are event handlers that are invoked when the battery moves above or below the threshold value, respectively. Upon receiving these events, we can perform some resource intensive tasks. Here we will enable or disable the location access. While receiving these notifications, we are setting the GeoLocationEnable flag of ViewModel, which actually starts or stops the location access service.

 class MainWindow : Window { …. //Notification method invoked when battery is above threshold value or power is plugged in. void vm_BatteryAboveThreshold(object sender, EventArgs e) { …. //Enable location access if (!locationAccessEnabled && canAccessLocation) { if (PowerMngrHelper.GetPowerState().LineStatus == ACLineStatus.Online) { //Automatic enable geo location if power plugged in. vm.GeoLocationEnable = true; EnableLocation(true); } else { //Ask to enable geo location if battery percentage above Threshold value. if (!vm.GeoLocationEnable && !vm.userClickedGeoTagBtn && !locationAccepted) { //Ask user to enable. if (AskLocationPermission("Battery is above threshold value, do you want to enable geo tagging?")) { locationAccepted = true; EnableLocation(true); vm.GeoLocationEnable = true; } } } } } //Notification method invoked when battery is below threshold value. void vm_BatteryBelowThreshold(object sender, EventArgs e) { isBatteryBelowThreshold = true; …. //Disable location access if (locationAccessEnabled && canAccessLocation && !locationAccepted) { //Automatic disable geo location if battery percentage falls down below Threshold value. if (vm.GeoLocationEnable && !vm.userClickedGeoTagBtn) { vm.GeoLocationEnable = false; } EnableLocation(false); } .... } 

Step: 7.4

In the MainWindowViewModel class’s methods SetBatteryLife() and SetPowerSouce(), add the following code to notify the view when the battery moves above or below the threshold.

 class MainWindowViewModel : ViewModelBase { public void SetPowerSouce() { ….. //Notify view about battery above threshold value (i.e. power plugged in) if (BatteryAboveThreshold != null) BatteryAboveThreshold(this, new EventArgs()); .…. } public void SetBatteryLife() { ….. //Check whether battery under threshold value or not. if (power_status.BatteryLifePercent < BatteryThreshold) { …. //Notify the view about battery below threshold value if (BatteryBelowThreshold != null) BatteryBelowThreshold(this, new EventArgs()); …. } else { …. //Notify the view about battery above threshold value. if (BatteryAboveThreshold != null) BatteryAboveThreshold(this, new EventArgs()); …. } .…. } ..... } 

Step: 7.5

In the MainWindowViewModel class, declare a public property to provide access to the current status of location access. Implement INotifyPropertChanged interface to provide auto-notification when a new value is set to the underlying "_geoLocationEnable" variable. If this property is set to true, call a function to start the locator; otherwise, call a function to stop the locator.

 class MainWindowViewModel : ViewModelBase { … private bool _geoLocationEnable; // Enables or disables geo location public bool GeoLocationEnable { get { return _geoLocationEnable; } set { if (_geoLocationEnable != value) { _geoLocationEnable = value; OnNotifyPropertyChanged("GeoLocationEnable"); } if (value == true) StartGeoLoctor(); else StopGeoLocator(); } } } 

Step: 7.6

In the MainWindowViewModel class, create an instance of GeoLocationHelper. This instance will be used to start or stop location access. GeoLocationHelper is a utility class that uses COM type lib to access location data. We will explore this further.

 class MainWindowViewModel : ViewModelBase { … //Member variables. private GeoLocationHelper geoLocator; … } 

Step: 7.7

In the MainWindowViewModel class, create two methods to start or stop locator functionality when the GeoLocationEnable flag is set to true or false, respectively, as mentioned in Step 7.5.

 class MainWindowViewModel : ViewModelBase { … //Starts the GeoLocator to get the geo position. void StartGeoLoctor() { if (geoLocator != null) geoLocator.StartGettingLocationUpdate(); } //Stops the GeoLocator. void StopGeoLocator() { if (geoLocator != null) geoLocator.StopGettingLocationUpdate(); } … } 

GeoLocationHelper Class

GeoLocationHelper is a utility class that provides access to location-related functions. It uses type library "LocationApiLib".

Implementation

GeoLocationHelper imports functions from Type lib "LocationApiLib". LocationApiLib is a COM Type lib that provides functions and event notifications related to user location. It has methods to start/stop location access. It also provides event handlers to register for location events like position and status changes.

Step: 1

Add a reference to LocationApiLib in the project following the steps below.

  • In Solution Explorer, right click on "References" and select "Add Reference…"
  • Select the "COM" tab and browse/search for "LocationApi 1.0 Type Library", select it and press OK.

Step: 2

Add a class named GeoLocationHelper and add name space for LocationApiLib. Derive the class from ILocationEvents interface. This interface provides methods to get notifications about location-related events.

 using System; using LocationApiLib; namespace PhotoApp.Utility { /// <summary> /// This class provides methods to start or stop geo location events. /// Class is derived from 'ILocationEvents' interface which has methods to get notification while position or status changed. /// We have used COM "LocationApi Type Library" as a reference. /// </summary> class GeoLocationHelper : ILocationEvents { ..... } } 

Step: 3

In the GeoLocationHelper class, create an instance of Location class and an instance of Guid for a latitude-longitude update report. This Guid will be used to start or stop reporting updates about location changes. Location is a class from a library, which is used to start or stop the location updates and get notifications when the location status or position changes.

 class GeoLocationHelper : ILocationEvents { //Member variables. //Location class's object to get geo position. Location geoLoc; //Guid for Lat-Long report. Guid guidLatLong = new Guid("7FED806D-0EF8-4F07-80AC-36A0BEAE3134"); ..... } } 

Step: 4

In the GeoLocationHelper class, create public methods to start or stop location update. The external code will call these methods to start or stop getting location updates.

 class GeoLocationHelper : ILocationEvents { //Starts to get location update. public void StartGettingLocationUpdate() { //Start to get geo position. if (geoLoc == null) { geoLoc = new Location(); } if (geoLoc != null) { geoLoc.RegisterForReport(this, guidLatLong, 0); } } // Stops to get location update. public void StopGettingLocationUpdate() { if (geoLoc != null) { geoLoc.UnregisterForReport(guidLatLong); } } ..... } } 

PowerMngrHelper Class

PowerMngrHelper is a utility class that provides access to power-related functions from unmanaged DLLs. There are two ways to call unmanaged code from C#:

  1. Directly call a function exported from a DLL using DllImport attribute.
  2. Call an interface method on a COM object.

For both techniques, we have to provide a declaration of an unmanaged function and may also need to provide a description of how to marshal the parameters and return values to and from the unmanaged code to C#. PowerMngrHelper uses the first technique mentioned above to access the functions from the unmanaged DLL.

Calling a DLL Export Directly from C# Using DllImport Attribute

To declare a method that has been implemented in a DLL, do the following:

  • Declare the method with the static and extern C# keywords.
  • Attach the DllImport attribute to the method. The DllImport attribute allows specifying the name of the DLL that contains the method.
  • Optionally, specify custom marshaling information for the method's parameters and return values.

Implementation

PowerMngrHelper imports functions from powrprof.dll, kernel32.dll, and User32.dll that allow you to retrieve the current power source, battery percentage, etc. It also provides for events to be invoked when a device detects a change in power source or battery capacity.

Step: 1

Declare a global structure. This structure will be used in functions to get the power source, battery capacity, etc. This structure is a C# version of "SYSTEM_POWER_STATUS" win32 structure.

 public struct SYSTEM_POWER_STATUS { public ACLineStatus LineStatus; public BatteryFlag flgBattery; public Byte BatteryLifePercent; public Byte Reserved1; public Int32 BatteryLifeTime; public Int32 BatteryFullLifeTime; } public enum ACLineStatus : byte { Offline = 0, Online = 1, Unknown = 255 } public enum BatteryFlag : byte { High = 1, Low = 2, Critical = 4, Charging = 8, NoSystemBattery = 128, Unknown = 255 } 

Step: 2

In the PowerMngrHelper class, declare variables. These variables will be used while registering and unregistering for the notifications.

 public class PowerMngrHelper { ... //GUID for power source. internal static readonly Guid PowerSourceChange = new Guid(0x5d3e9a59, 0xe9D5, 0x4b00, 0xa6, 0xbd, 0xff, 0x34, 0xff, 0x51, 0x65, 0x48); //GUID for remaining battery percentage. internal static readonly Guid BatteryCapacityChange = new Guid(0xa7ad8041, 0xb45a, 0x4cae, 0x87, 0xa3, 0xee, 0xcb, 0xb4, 0x68, 0xa9, 0xe1); internal const uint PowerBroadcastMessage = 536; internal const uint PowerSettingChangeMessage = 32787; //Handler to the power source change notification. IntPtr hPowerSrc; //Handler to the battery capacity change notification. IntPtr hBatteryCapacity; //Number of events registered for notification. int eventCount = 0; //Interop Helper used to get the handle to WPF window. WindowInteropHelper interopHelper; //Stores the event handlers. List<EventHandler> eventsList = new List<EventHandler>(); ... } 

Step: 3

In the PowerMngrHelper class, declare the following function using DllImport to get the power status.

 public class PowerMngrHelper { ... [DllImport("kernel32.dll", SetLastError = true)] private static extern Boolean GetSystemPowerStatus(out SYSTEM_POWER_STATUS sps); ... } 

Step: 4

In the PowerMngrHelper class, declare the following functions using DllImport to register and unregister the power setting change events. When we register for power setting notifications, we will get the updates about power-related event changes. When we unregister, we will not further receive the power-related event change notifications. When closing the application or at a certain event, if we want to stop getting power-related updates, we can unregister using the function below.

 public class PowerMngrHelper { ... [DllImport("User32", SetLastError = true, EntryPoint = "RegisterPowerSettingNotification", CallingConvention = CallingConvention.StdCall)] private static extern IntPtr RegisterPowerSettingNotification( IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags); [DllImport("User32", SetLastError = true, EntryPoint = "UnregisterPowerSettingNotification", CallingConvention = CallingConvention.StdCall)] private static extern bool UnregisterPowerSettingNotification( IntPtr hRecipient); ... } 

Step: 5

In the PowerMngrHelper class, write GetPowerState() public static function, this function will be used by external code to get the status of power. This function will use the unmanaged DLL's function GetSystemPowerStatus(), which we declared in step 3. The function returns SYSTEM_POWER_STATUS structure containing the information about the current power state of the system.

 public class PowerMngrHelper { ... public static SYSTEM_POWER_STATUS GetPowerState() { SYSTEM_POWER_STATUS powerStatus = new SYSTEM_POWER_STATUS(); bool b = GetSystemPowerStatus(out powerStatus); return powerStatus; } ... } 

Step: 6

In the PowerMngrHelper class, write functions to register and unregister the notifications about device power source changes and device battery capacity changes. These functions will use the unmanaged DLL functions that we declared in step 4. For handling system messages in Windows Presentation Foundation applications, we need to add the hook to the Window Procedure. We will add the hook only if this is the first event count; otherwise, it will be already added, so no need to add again. We will increment the event counter each time. Now, the WndProc method will receive the system's WM messages as we have hooked this method for system messages. While unregistering the notification, we will decrease the event counter; while it is zero, we will remove the hook. This is done to ensure we will not further receive the system messages.

 public class PowerMngrHelper { ... //Method to register for power source change notification. void RegisterPowerSourceChangeNotification(IntPtr aHandle) { //Add message hook if (eventCount <= 0) { HwndSource source = HwndSource.FromHwnd(interopHelper.Handle); source.AddHook(WndProc); } eventCount++; Guid g = PowerSourceChange; hPowerSrc = RegisterPowerSettingNotification(aHandle, ref g, 0); } //Method to unregister for power source change notification. void UnregisterPowerSourceChangeNotification() { UnregisterPowerSettingNotification(hPowerSrc); eventCount--; //Remove message hook if (eventCount <= 0) { HwndSource src = HwndSource.FromHwnd(interopHelper.Handle); src.RemoveHook(WndProc); } } //Method to register for battery capacity change notification. void RegisterBatteryCapacityChangeNotification(IntPtr aHandle) { //Add message hook if (eventCount <= 0) { HwndSource source = HwndSource.FromHwnd(interopHelper.Handle); source.AddHook(WndProc); } eventCount++; Guid g = BatteryCapacityChange; hBatteryCapacity = RegisterPowerSettingNotification(aHandle, ref g, 0); } //Method to unregister for battery capacity change notification. void UnRegisterBatteryCapacityChangeNotification() { UnregisterPowerSettingNotification(hBatteryCapacity); eventCount--; //Remove message hook if (eventCount <= 0) { HwndSource src = HwndSource.FromHwnd(interopHelper.Handle); src.RemoveHook(WndProc); } } ... } 

Step: 7

In the PowerMngrHelper class, write the event handlers for power source change and battery capacity change notifications. The external code will use these to register for notifications. Upon adding an event each time, we will add this handler to the list and upon removing we will remove it from the list. This events list will be used to execute the event or fire the notification when WndProc receives the power-related system message.

 public class PowerMngrHelper { ... // Notification called when power source changed (i.e. from AC power to Battery power or vice versa) public event EventHandler PowerSourceChanged { add { if (!eventList.Contains(PowerSourceChange)) { RegisterPowerSourceChangeNotification(interopHelper.Handle); ArrayList newList = new ArrayList(); newList.Add(value); eventList.Add(PowerSourceChange, newList); } else { ArrayList currList = (ArrayList)eventList[PowerSourceChange]; currList.Add(value); } } remove { UnregisterPowerSourceChangeNotification(); ArrayList currList = (ArrayList)eventList[PowerSourceChange]; currList.Remove(value); } } // Notification called when battery capacity changed. public event EventHandler BatteryCapacityChanged { add { if (!eventList.Contains(BatteryCapacityChange)) { RegisterBatteryCapacityChangeNotification(interopHelper.Handle); ArrayList newList = new ArrayList(); newList.Add(value); eventList.Add(BatteryCapacityChange, newList); } else { ArrayList currList = (ArrayList)eventList[BatteryCapacityChange]; currList.Add(value); } } remove { UnRegisterBatteryCapacityChangeNotification(); ArrayList currList = (ArrayList)eventList[BatteryCapacityChange]; currList.Remove(value); } } ... } 

Step: 8

In the PowerMngrHelper class, write the following method. This method will be invoked by the system, which will send each WM message to this method, but we will handle only power-related messages.

 public class PowerMngrHelper { … // This method will be called when a Windows message will be sent to this window. // The method calls the registered event handlers, if there is power related message. IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { // Make sure it is a Power Management message. if (msg == PowerBroadcastMessage && (int)wParam == PowerSettingChangeMessage) { PowerBroadcastSetting ps = (PowerBroadcastSetting)Marshal.PtrToStructure( lParam, typeof(PowerBroadcastSetting)); IntPtr pData = new IntPtr(lParam.ToInt64() + Marshal.SizeOf(ps)); Guid currentEvent = ps.PowerSetting; //Make sure event executed only once. if (!IsMessageCaught(currentEvent)) { ExecuteEvents((ArrayList)eventList[currentEvent]); } handled = true; } return IntPtr.Zero; } ... } 

Step: 9

In the PowerMngrHelper class, write the following method. This method will be called by WndProc to ensure that each message is caught only once.

 public class PowerMngrHelper { … // Used to catch the initial message Windows sends when you first register for a power notification. // We do not want to fire any event handlers when this happens. private bool powerSrcCaught; private bool batteryLifeCaught; // Determines if a message should be caught, preventing the event handler from executing. This is needed when an event is initially registered. private bool IsMessageCaught(Guid eventGuid) { bool isMessageCaught = false; if (eventGuid == BatteryCapacityChange) { if (!batteryLifeCaught) { batteryLifeCaught = true; isMessageCaught = true; } } else if (eventGuid == PowerSourceChange) { if (!powerSrcCaught) { powerSrcCaught = true; isMessageCaught = true; } } return isMessageCaught; } ... } 

Step: 10

In the PowerMngrHelper class, write the following method. This method will be called by WndProc to execute the event registered with event handlers, i.e., the external class will receive the notifications about PowerSourceChanged and BatteryCapacityChanged if they have registered for the events.

 public class PowerMngrHelper { ... // Executes any registered event handlers. private static void ExecuteEvents(ArrayList eventHandlerList) { foreach (EventHandler handler in eventHandlerList) { handler.Invoke(null, new EventArgs()); } } ... } 

Additional Resources:

Developing Power-Efficient Apps for Ultrabook™ Devices

UltrabookTM Desktop Applications Development on Windows* 8: Photo Application with Touch and Sensors

Notices

INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT.

UNLESS OTHERWISE AGREED IN WRITING BY INTEL, THE INTEL PRODUCTS ARE NOT DESIGNED NOR INTENDED FOR ANY APPLICATION IN WHICH THE FAILURE OF THE INTEL PRODUCT COULD CREATE A SITUATION WHERE PERSONAL INJURY OR DEATH MAY OCCUR.

Intel may make changes to specifications and product descriptions at any time, without notice. Designers must not rely on the absence or characteristics of any features or instructions marked "reserved" or "undefined." Intel reserves these for future definition and shall have no responsibility whatsoever for conflicts or incompatibilities arising from future changes to them. The information here is subject to change without notice. Do not finalize a design with this information.

The products described in this document may contain design defects or errors known as errata which may cause the product to deviate from published specifications. Current characterized errata are available on request.

Contact your local Intel sales office or your distributor to obtain the latest specifications and before placing your product order.

Copies of documents which have an order number and are referenced in this document, or other Intel literature, may be obtained by calling 1-800-548-4725, or go to: http://www.intel.com/design/literature.htm

Software and workloads used in performance tests may have been optimized for performance only on Intel microprocessors. Performance tests, such as SYSmark and MobileMark, are measured using specific computer systems, components, software, operations, and functions. Any change to any of those factors may cause the results to vary. You should consult other information and performance tests to assist you in fully evaluating your contemplated purchases, including the performance of that product when combined with other products.

Any software source code reprinted in this document is furnished under a software license and may only be used or copied in accordance with the terms of that license.

Intel, Ultrabook, and the Intel logo are trademarks of Intel Corporation in the US and/or other countries.

Copyright © 2012 Intel Corporation. All rights reserved.

*Other names and brands may be claimed as the property of others.

Einzelheiten zur Compiler-Optimierung finden Sie in unserem Optimierungshinweis.