EVC获取电源属性

2019-07-14 00:41发布

 //========================================================================
//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)
      {
          .......
      }
      
      ......
                
  }  
 
}