//========================================================================
//TITLE:
// CPowerThread更新至v1.1.0
//AUTHOR:
// norains
//DATE:
// Tuesday 25-December-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
// EVC4.0 + SDK-WINCE5.0-MIPSII
// VS2005 + SDK-WINCE5.0-MIPSII
//========================================================================
相对于v1.0.0版本,有如下变动:
1.去掉GetInstance()函数,不用获取对象实例,可以直接声明对象实例使用
2.改进该类以令其在继承之后能正常工作.
3.增加OnNotifyPower()函数,可以不设置回调函数而通过重载该函数监视电源的变化.
v1.0.0版本:http://blog.csdn.net/norains/archive/2007/07/20/1700980.aspx
//////////////////////////////////////////////////////////////////////
// PowerThread.h: interface for the CPowerThread class.
//
//Version:
// 1.1.0
//Date:
// 2007.11.15
//////////////////////////////////////////////////////////////////////
#ifndef POWERTHREAD_H
#define POWERTHREAD_H
#include "Pm.h"
//-----------------------------------------------------------------
//Enum data type
enum PowerStatusType
{
POW_UNKNOW, //Unknow the status
POW_CHARGING, //It's charging now
POW_CHARGEFULL, //Full charge
POW_VLOW, //The battery level is very low
POW_LOW,
POW_NORMAL,
POW_HIGH,
POW_VHIGH //The battery level is very high
};
//----------------------------------------------------------------
class CPowerThread
{
public:
BOOL ResumnSign(); //Not support now
void GetCallbackFunction(void (* *pCallbackFunc)(PowerStatusType powStatus, int iBatteryPercent));
void SetCallbackFunction(void (*pCallbackFunc)(PowerStatusType powStatus, int iBatteryPercent));
void StopCapture();
BOOL StartCapture();
BOOL GetRunStatus();
void SetTimeout(ULONG ulTime);
CPowerThread();
virtual ~CPowerThread();
protected:
virtual void OnNotifyPower(PowerStatusType powStatus, int iBatteryPercent);
//The critical section function
inline void InitLock() { InitializeCriticalSection(&m_csLock); }
inline void LockThis() { EnterCriticalSection(&m_csLock); }
inline void UnLockThis() { LeaveCriticalSection(&m_csLock); }
inline void DelLock() { DeleteCriticalSection(&m_csLock); }
private:
PowerStatusType GetPowerStatus(PPOWER_BROADCAST pPowerInfo, int *piPercent);
static DWORD WINAPI PowerThread(PVOID pArg);
BOOL m_bExitThread;
ULONG m_ulWaitTime;
BOOL m_bRunning;
CRITICAL_SECTION m_csLock;
//This is for callback function.
void (*m_pNotifyPower)(PowerStatusType powStatus, int iBatteryPercent);
};
#endif //#ifndef POWERTHREAD_H
//////////////////////////////////////////////////////////////////////
// PowerThread.cpp: implementation of the CPowerThread class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "PowerThread.h"
#include "Msgqueue.h"
//--------------------------------------------------------------------
//Macro define
#define DEFAULT_TIMEOUT 1000//1000ms
//----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPowerThread::CPowerThread():
m_bExitThread(TRUE),
m_ulWaitTime(DEFAULT_TIMEOUT),
m_bRunning(FALSE),
m_pNotifyPower(NULL)
{
InitLock();
}
CPowerThread::~CPowerThread()
{
DelLock();
}
//------------------------------------------------------------------
//Description:
// Get the level of power from the PPOWER_BROADCAST struct
//
//Parameters:
// pPowerInfo:[in] The struct includes the power information
// piPercent:[out] The battery life percent.
//
//Return Values:
// The power status
//----------------------------------------------------------------
PowerStatusType CPowerThread::GetPowerStatus(PPOWER_BROADCAST pPowerInfo, int *piPercent)
{
PowerStatusType powStatus = POW_UNKNOW;
if ( !pPowerInfo )
{
return POW_UNKNOW;
}
PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pPowerInfo->SystemPowerState;
if ( !ppbpi )
{
return POW_UNKNOW;
}
*piPercent = ppbpi->bBatteryLifePercent;
if(ppbpi->bACLineStatus == AC_LINE_ONLINE)
{
if(ppbpi->bBatteryFlag == BATTERY_FLAG_CHARGING)
{
//Charging
powStatus = POW_CHARGING;
}
else
{
//May be full charging,or may be no battery
powStatus = POW_CHARGEFULL;
}
}
else
{
//Use battery
if(0 <= ppbpi->bBatteryLifePercent && ppbpi->bBatteryLifePercent <= 20)
{
powStatus = POW_VLOW;
}
else if(20 < ppbpi->bBatteryLifePercent && ppbpi->bBatteryLifePercent <= 40)
{
powStatus = POW_LOW;
}
else if(40 < ppbpi->bBatteryLifePercent && ppbpi->bBatteryLifePercent <=60)
{
powStatus = POW_NORMAL;
}
else if(60 < ppbpi->bBatteryLifePercent && ppbpi->bBatteryLifePercent <=80)
{
powStatus = POW_HIGH;
}
else if(80 < ppbpi->bBatteryLifePercent && ppbpi->bBatteryLifePercent <= 100)
{
powStatus = POW_VHIGH;
}
else
{
powStatus = POW_UNKNOW;
}
}
return powStatus;
}
//------------------------------------------------------------------
//Description:
// Thread to get the power status
//----------------------------------------------------------------
DWORD WINAPI CPowerThread::PowerThread(PVOID pArg)
{
CPowerThread *pObject = (CPowerThread *) pArg;
pObject->m_bRunning = TRUE;
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(pObject->m_bExitThread == FALSE)
{
DWORD dwWaitCode = MsgWaitForMultipleObjectsEx( 1, rghWaits, pObject->m_ulWaitTime, QS_ALLINPUT, MWMO_INPUTAVAILABLE );
if ( dwWaitCode == WAIT_OBJECT_0 )
{
DWORD dwSize, dwFlags;
BOOL bReadResult = ReadMsgQueue(rghWaits[0], ppb, sizeof(pbMsgBuf), &dwSize, 0, &dwFlags);
if (bReadResult == TRUE)
{
int iPowPercent;
PowerStatusType powStatus = pObject->GetPowerStatus(ppb,&iPowPercent);
pObject->LockThis();
if(pObject->m_pNotifyPower != NULL)
{
pObject->m_pNotifyPower(powStatus,iPowPercent);
}
pObject->OnNotifyPower(powStatus,iPowPercent);
pObject->UnLockThis();
}
else
{
// We should never get here
break;
}
}
}
pObject->m_bRunning = FALSE;
return 0;
}
//------------------------------------------------------------------
//Description:
// Set the timeout for the wait thread. It is only for the MsgWaitForMultipleObjectsEx()
//The default value is DEFAULT_TIMEOUT
//----------------------------------------------------------------
void CPowerThread::SetTimeout(ULONG ulTime)
{
m_ulWaitTime = ulTime;
}
//------------------------------------------------------------------
//Description:
// Get the status of thread
//
//Return Values:
// TRUE: The thread is running for capturing the power status.
// FALSE: No thread running.
//----------------------------------------------------------------
BOOL CPowerThread::GetRunStatus()
{
return m_bRunning;
}
//------------------------------------------------------------------
//Description:
// start capturing the power status.If there is thread running,
//it will return FALSE;
//
//------------------------------------------------------------------
BOOL CPowerThread::StartCapture()
{
if(m_bRunning == TRUE)
{
return FALSE;
}
m_bExitThread = FALSE;
//Create the thread for batter sampled
DWORD dwPwrThdID;
HANDLE hdThrd = CreateThread(NULL,0,PowerThread,(void *)this,0,&dwPwrThdID);
if(hdThrd == NULL)
{
return FALSE;
}
CloseHandle(hdThrd);
return TRUE;
}
//-----------------------------------------------------------------------------
//Description:
// Stop capturing.
//
//--------------------------------------------------------------------------------
void CPowerThread::StopCapture()
{
m_bExitThread = TRUE;
}
//------------------------------------------------------------------
//Description:
// Set the callback function for receive the power status
//------------------------------------------------------------------
void CPowerThread::SetCallbackFunction(void (*pCallbackFunc)(PowerStatusType powStatus, int iBatteryPercent))
{
LockThis();
m_pNotifyPower = pCallbackFunc;
UnLockThis();
}
//------------------------------------------------------------------
//Description:
// Get the callback function
//------------------------------------------------------------------
void CPowerThread::GetCallbackFunction(void (* *pCallbackFunc)(PowerStatusType powStatus, int iBatteryPercent))
{
LockThis();
*pCallbackFunc = m_pNotifyPower;
UnLockThis();
}
//------------------------------------------------------------------
//Description:
// Resumn the sign order to get the current power status,or the power
//status will return untill the power status changed.
//------------------------------------------------------------------
BOOL CPowerThread::ResumnSign()
{
/*
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 FALSE;
}
// Request notifications
HANDLE hReq = RequestPowerNotifications(rghWaits[0], PBT_POWERINFOCHANGE);
if (!hReq)
{
CloseHandle( rghWaits[ 0 ] );
//erro
return FALSE;
}
return TRUE;
*/
return FALSE;
}
//------------------------------------------------------------------
//Description:
// Notify the power. It's used as call back funtion.
//------------------------------------------------------------------
void CPowerThread::OnNotifyPower(PowerStatusType powStatus, int iBatteryPercent)
{
return;
}