//========================================================================
//TITLE:
// EVC获取电源属性
//AUTHOR:
// norains
//DATE:
// Tuesday 29-August-2006
//========================================================================
在evc中获取电源的属性不算太复杂,但在文档中却没有提及,所以当时在获取电源属性时走了不少弯路.
WinCE的电源是通过电源管理器(Power manager,以下简称PM)来进行管理,自然我们要获取其电源信息也必须通过PM接口.当底层驱动检测到电源状态发生变化时,PM就会广播消息,我们所需要做的就是接收此消息,并把包含的参数转换为我们所需要的数值.
要捕获电源消息,最重要就是创建消息队列:
HANDLE hReq = NULL;
hReq = RequestPowerNotifications(rghWaits[0], PBT_POWERINFOCHANGE);
"PBT_POWERINFOCHANGE"形参意味着只要电源信息有变动,就会收到信号.
除此以外,还有三个形参,分别是:
PBT_TRANSITION:系统的电源状态改变时,比如"挂起"
PBT_RESUME:状态恢复时,将把现在状态设置为前状态
PBT_POWERSTATUSCHANGE: 当AC->DC 或DC->AC转换时发出信号
接下来我们需要做的就是采用MsgWaitForMultipleObjectsEx()函数来等待消息.如果返回的数值是WAIT_OBJECT_0,那么我们已经收到我们所需要的信号,然后要做的就是通过ReadMsgQueue()函数读取电源信息.
ReadMsgQueue(rghWaits[0], ppb, sizeof(pbMsgBuf), &dwSize, 0, &dwFlags);
因为所有信息都包含于缓存ppb中,我们只要通过强制转换就能够比较方便地获取电源的状态信息.
PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) ppb->SystemPowerState;
PPOWER_BROADCAST_POWER_INFO结构信息丰富,如果仅仅意在检测电源的状态,我们只需要关注这两个变量即可:bACLineStatus和bBatteryLifePercent.前者标识是否插入AC,后者表明当前电池的电量百分比.
我们可以先判断bACLineStatus的状态.如果为TRUE,一定接上AC,然后此时又可分为"正在充电"和"充电完毕"两种状态;如果为FALSE,那么就在使用备用电池,我们只需要关注电量的百分比即可.
代码的结构如下:
void BeginSample()
{
......
//Create the thread for batter sampled
DWORD dwPwrThdID = 0;
g_hPwrThd = CreateThread(NULL,0,PowerThread,NULL,0,&dwPwrThdID);
......
}
DWORD WINAPI PowerThread(PVOID pArg)
{
__try
{
BYTE pbMsgBuf[sizeof(POWER_BROADCAST) + sizeof(POWER_BROADCAST_POWER_INFO)];
PPOWER_BROADCAST ppb = (PPOWER_BROADCAST) pbMsgBuf;
MSGQUEUEOPTIONS msgopts;
// Create our message queue
memset(&msgopts, 0, sizeof(msgopts));
msgopts.dwSize = sizeof(msgopts);
msgopts.dwFlags = 0;
msgopts.dwMaxMessages = 0;
msgopts.cbMaxMessage = sizeof(pbMsgBuf);
msgopts.bReadAccess = TRUE;
HANDLE rghWaits[1] = { NULL };
rghWaits[0] = CreateMsgQueue(NULL, &msgopts);
if (!rghWaits[0])
{
//erro
return 0x10;
}
HANDLE hReq = NULL;
// Request notifications
hReq = RequestPowerNotifications(rghWaits[0], PBT_POWERINFOCHANGE);
if (!hReq)
{
CloseHandle( rghWaits[ 0 ] );
//erro
return 0x15;
}
while(TRUE)
{
DWORD dwWaitCode = MsgWaitForMultipleObjectsEx( 1, rghWaits, INFINITE, QS_ALLINPUT, MWMO_INPUTAVAILABLE );
if ( dwWaitCode == WAIT_OBJECT_0 )
{
DWORD dwSize, dwFlags;
if (ReadMsgQueue(rghWaits[0], ppb, sizeof(pbMsgBuf), &dwSize, 0, &dwFlags))
{
UpdatePower(ppb);
}
else
{
return 0x20; // We should never get here
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
return 0;
}
void UpdatePower(PPOWER_BROADCAST pPowerInfo)
{
if ( !pPowerInfo )
{
DEBUGMSG(1,(L"pPowerInfo is empty/r/n"));
return;
}
PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pPowerInfo->SystemPowerState;
if ( !ppbpi )
{
DEBUGMSG(1,(L"ppbpi is empty/r/n"));
return;
}
static BOOL bFirstTime = TRUE;
RECT rc = {IMG_PWR_X,IMG_PWR_Y,IMG_PWR_CX,IMG_PWR_CY};
if(ppbpi->bACLineStatus == AC_LINE_ONLINE)
{
if(ppbpi->bBatteryFlag == BATTERY_FLAG_CHARGING)
{
//Charging
......
}
else
{
//May be full charging
......
}
}
else
{
//Use battery
if(0 <= ppbpi->bBatteryLifePercent && ppbpi->bBatteryLifePercent <= 20)
{
.......
}
......
}
}