自制手机手电筒应用开发记

今年明尼苏达州的天气变化无常,经历了一些久违的雷暴。其中第一次雷暴,以及随后的几次,都在深夜让家中断电。喜欢尽可能地开着窗户,因此在黑暗中,不得不依靠Pocket PC手机来提供照明,以便在房间之间摸索。

不用说,小腿因此受了不少苦。可能会问:“为什么不在床边放一个真正的手电筒呢?”回答是:“为什么不写一个.NET Compact Framework应用程序呢?这样更有趣!”

使用代码

实现一个全屏的白色界面并不难,但手电筒的第一个要求是必须在运行时禁用背光超时(第一晚不得不频繁地点击屏幕,以保持尽可能的亮度)。

这是通过调用coredll.dll中的SetPowerRequirement函数来实现的(喜欢他们将DLL命名为CoreDll.dll,以防DLL扩展名不够直观)。SetPowerRequirement允许应用程序在运行时指定它需要来自特定设备的一定电力水平。背光设备的名称是BKL1。告诉操作系统需要背光的全功率,可以防止它超时。

使用这种方法的唯一技巧是,当完成后一定要调用ReleasePowerRequirement。将所有这些都封装在一个实现了IDisposable的PowerRequirement类中,以便可以轻松管理。

protected override void OnLoad(EventArgs e) { ... m_powerRequirement = new PowerRequirement("BKL1:", PowerState.FULL); ... } protected override void Dispose(bool disposing) { if (disposing) { if (m_powerRequirement != null) m_powerRequirement.Dispose(); } base.Dispose(disposing); }

设置和释放电力需求的CE API原型如下:

[DllImport("coredll.dll")] private static extern IntPtr SetPowerRequirement(string pvDevice, PowerState DeviceState, int DeviceFlags, IntPtr pvSystemState, int StateFlags); [DllImport("coredll.dll")] private static extern int ReleasePowerRequirement(IntPtr hPowerReq);

控制屏幕亮度

接下来,想出了一种调整背光亮度的方法。这需要在互联网上进行一些挖掘,但最终找到了一些线索,找到了一个可行的方法。也就是说,它在HTC Touch上运行Windows Mobile 6时有效。听起来背光管理可能非常依赖于设备和供应商,所以这可能不适用于设备。

在Touch上,背光亮度由注册表设置HKCU\ControlPanel\Backlight\Brightness管理,这足够简单。一旦知道了这一点,就只需要让操作系统知道已经改变了这个值。这是通过一个事件(Win32风格的,不是.NET风格的)来完成的。哦,还有关于亮度调整的一个警告:它在模拟器上不起作用;不管设置什么,它始终保持全亮度。

public int Brightness { ... set { PowerStatus power = new PowerStatus(); if (power.PowerLineStatus == PowerLineStatus.Online) SetBacklightValue("ACBrightness", value); else SetBacklightValue("Brightness", value); RaiseBackLightChangeEvent(); } } private void SetBacklightValue(string name, int v) { RegistryKey key = Registry.CurrentUser.OpenSubKey(@"ControlPanel\Backlight", true); if (key != null) { key.SetValue(name, v); key.Close(); } } private static void RaiseBackLightChangeEvent() { IntPtr hBackLightEvent = CreateEvent(IntPtr.Zero, false, true, "BackLightChangeEvent"); if (hBackLightEvent != IntPtr.Zero) { SetEvent(hBackLightEvent); CloseHandle(hBackLightEvent); } }

真正的全屏

可能认为将Form设置为最大化,去掉控制框,移除边框,并将其设置为最顶层窗口,就可以提供一个真正的全屏窗口。这有时有效,但并不总是有效。很多时候,标题栏和开始菜单仍然会显示在手电筒窗口之上。为了有效地获得真正的全屏模式,必须再次调用CE API。

protected override void OnLoad(EventArgs e) { ... SHFullScreen(this.Handle, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON); base.OnLoad(e); } private const int SHFS_SHOWTASKBAR = 0x0001; private const int SHFS_HIDETASKBAR = 0x0002; private const int SHFS_SHOWSIPBUTTON = 0x0004; private const int SHFS_HIDESIPBUTTON = 0x0008; private const int SHFS_SHOWSTARTICON = 0x0010; private const int SHFS_HIDESTARTICON = 0x0020; [DllImport("aygshell.dll")] static extern bool SHFullScreen(IntPtr hwnd, int dwState);

有趣的点

这个应用程序唯一真正的问题是还没有弄清楚电池寿命指标。想能够显示剩余的估计电池寿命(知道的,对于那些“紧急情况,被困在电梯里”的情况,可能需要节省电池)。从OpenNETCF.org得到了一些代码,它使用GetSystemPowerStatusEx函数,但它在Touch和Windows Mobile设备模拟器上从未返回过任何数据。

如果有人知道如何从该方法中获取有意义的数据,请告诉。已经将代码和功能包含在应用程序中,以防它在其他设备上有效。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485