最近我用笔记本发现电池容量的notifyicon经常不会正常出现(虽然设置了始终显示),并且我以前在PDA软件上写过显示电池容量的功能,所以可以写一个在桌面上显示电量的轻量级程序。查询电量主要通过API函数GetSystemPowerStatus来实现,这里不讲这个API函数(可参阅在api文档中有详细介绍)。
[DllImport(KERNEL32)]
public static extern bool GetSystemPowerStatus(
ref SYSTEM_POWER_STATUS pSystemPowerStatus
);
最初我用一个progressbar和一个label分别显示,这样做非常简单。但是progressbar的style属性是否不起作用,无法显示成连续样式,而是始终用绿色的小方块显示进度(XP系统),这样的显示不是很精确,所以决定自己绘制。同时把label也省略掉,直接在进度条上绘制百分比。所以这就引出下面的绘制问题,如何使绘制文本始终可见,采用下面的方法,下图:
放大为800%的效果图:
我们把窗口放置在这样的位置,当一个窗口最大化时,它贴近标题栏右侧,但不会遮挡controlbuttons。(如上图)
这需要获取显示器尺寸,在vc中是使用GetSystemMatrix函数,在c#中可以使用Screen.PrimaryScreen.Bounds属性。
上图中字符串被切分为两个部分,因此我们在绘制时先准备两个图片,bitmap1和2,分别采用不同的前景和背景,当进度条处于文字中间位置时,我们贴两次图。
百分比字符串的尺寸可以测量:
sizef=graphics.measurestring(text,font)
绘制字符串的起始位置(居中):
startX=(this.width-sizef.width)/2;
startY=(this.height-sizef.height)/2;
注意,贴图时,一定要使用整数坐标,而不使用float坐标,否则会产生图像的插值计算而导致模糊。
因为这是窗口程序,因此大多数情况下应该是一个对鼠标消息“透明”的窗口,即鼠标穿透功能,由于程序很小,因此我们不设置单独选项来控制。这个功能是通过API函数设置窗口样式实现的,代码如下:
//设置为鼠标穿透
SetWindowLong(this.Handle, GWL_EXSTYLE,
GetWindowLong(this.Handle,GWL_EXSTYLE)| WS_EX_TRANSPARENT | WS_EX_LAYERED);
未来需要添加的功能包括:允许移动(由于无标题栏,所以需要一些处理windows消息的技巧)。
源代码:
http://files.cnblogs.com/hoodlum1980/PowerStatus.rar
附录:维护历史
2008.01.16:增加了通知栏多图标切换,充电提示,电量低于25%时通知栏图标闪烁。
2008.01.18:鼠标穿透功能。
2008.01.22:修正了立即刷新电量时,界面未能更新的BUG。
2008.01.24:增加两个Tray图标,使通知托盘区的图标选择(根据实际剩余电量)更加合理。
2008.12.16:增加了交流电源在线时的图标,并绘制了更符合电池外观的轮廓。