Question

Has anyone successfully trapped the power/standby button on a WM5 device such that your code prevented users "switching off" even the screen?

I have an application that uses the screen in a landscape orientation and I'd like to trap the power key press so that (a) users can hold the device with both hands and not accidentally power-down the screen and (as a bonus - b) use it as a UI button.

Perhaps someone has a low level hack? I'm using WM5 as delivered on iPaq RX1950(s).

Remember, there is no such thing as impossible - especially with WM5. If I answer it myself in the meantime, I'll update the question.


Update!

I discovered three tricks that work, in reverse order of usability:

  1. Patch keybddr.dll (on this device), re-inject into the ROM via your favourite means. On this device with this factory ROM - it works, but I didn't want to permanently disable it.

  2. Sync to the Power Management message queue and turn the device "on" whenever it says it's going down.

  3. Change the "Power States" in the registry so they're all (most of them) "on". This way, I can use RAPI to disable the power button and have the software on the device "reset" the registry on event x, y and z.

Was it helpful?

Solution

The implementation of the power button is OEM dependent, so a solution on one device is not likely to work on another device. Because of the wide variance of implementations in Windows Mobile devices you'll find this is true with many low level features.

The alternative involves a combination of things

  • Run your application in unattended mode
  • Monitor for power change events
  • when the device changes to unattended mode request full on mode

A full discussion of power management is beyond what I can discuss here. You can read more about it here: http://www.codeproject.com/KB/mobile/WiMoPower1.aspx

There's also a sample that shows how one can register for power events here: http://www.codeproject.com/KB/mobile/WiMoQueue.aspx

OTHER TIPS

The following code will not disable the power button, but if the device is turned off, it will turn the device back on again within 10 seconds. It will also disable any power saving functionality.

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;

namespace Core.Mobile
{
    /// <summary>
    /// Allows manipulation the power management i.e. system standby
    /// </summary>
    public static class PowerManipulation
    {
        #region Private variables
        private static System.Threading.Timer _timer = null;
        private const int INTERVAL = 10000; //10 seconds
        #endregion
        #region Public methods
        /// <summary>
        /// Prevents the application from suspending/sleeping
        /// </summary>
        public static void DisableSleep()
        {
            if (_timer == null)
            {
                _timer = new System.Threading.Timer(new System.Threading.TimerCallback(Timer_Tick), null, 0, INTERVAL);
            }
            try
            {
                PowerPolicyNotify(PPN_UNATTENDEDMODE, 1);  //Ensure the application still runs in suspend mode
            }
            catch { }
        }
        /// <summary>
        /// Allows suspend/sleep operations
        /// </summary>
        public static void EnableSleep()
        {
            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }
            try
            {
                PowerPolicyNotify(PPN_UNATTENDEDMODE, 0);
            }
            catch { }
        }
        #endregion
        #region Private methods
        /// <summary>
        /// Internal timer for preventing standby
        /// </summary>
        private static void Timer_Tick(object state)
        {
            try
            {
                SystemIdleTimerReset();
                SetSystemPowerState(null, POWER_STATE_ON, POWER_FORCE);
            }
            catch { }
        }
        #endregion
        #region PInvoke
        private const int PPN_UNATTENDEDMODE = 0x00000003;
        private const int POWER_STATE_ON = 0x00010000;
        private const int POWER_STATE_OFF = 0x00020000;
        private const int POWER_STATE_SUSPEND = 0x00200000;
        private const int POWER_FORCE = 4096;
        private const int POWER_STATE_RESET = 0x00800000;
        /// <summary>
        /// This function resets a system timer that controls whether or not the
        /// device will automatically go into a suspended state.
        /// </summary>
        [DllImport("CoreDll.dll")]
        private static extern void SystemIdleTimerReset();
        /// <summary>
        /// This function resets a system timer that controls whether or not the
        /// device will automatically go into a suspended state.
        /// </summary>
        [DllImport("CoreDll.dll")]
        private static extern void SHIdleTimerReset();
        /// <summary>
        /// This function allows the current power state to be manipulated, i.e. turn the device on
        /// </summary>
        [DllImport("coredll.dll", SetLastError = true)]
        static extern int SetSystemPowerState(string psState, int StateFlags, int Options);
        /// <summary>
        /// This function sets any power notification options
        /// </summary>
        [DllImport("CoreDll.dll")]
        static extern bool PowerPolicyNotify(int dwMessage, int onOrOff);
        #endregion
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top