CPowerThread更新至v1.1.0

时间:2021-03-09 09:21:12

//========================================================================
//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 ;
}