787 lines
22 KiB
C
787 lines
22 KiB
C
|
/*******************************************************************************
|
||
|
*
|
||
|
* (C) COPYRIGHT MICROSOFT CORP., 1993-1995
|
||
|
*
|
||
|
* TITLE: POWER.C
|
||
|
*
|
||
|
* VERSION: 2.0
|
||
|
*
|
||
|
* AUTHOR: TCS/RAL
|
||
|
*
|
||
|
* DATE: 08 Feb 1994
|
||
|
*
|
||
|
********************************************************************************
|
||
|
*
|
||
|
* CHANGE LOG:
|
||
|
*
|
||
|
* DATE REV DESCRIPTION
|
||
|
* ----------- --- -------------------------------------------------------------
|
||
|
* 08 Feb 1994 TCS Original implementation.
|
||
|
* 11 Nov 1994 RAL Converted from batmeter to systray
|
||
|
* 11 Aug 1995 JEM Split batmeter functions into power.c & minor enahncements
|
||
|
* 23 Oct 1995 Shawnb UNICODE Enabled
|
||
|
* 24 Jan 1997 Reedb ACPI power management, common battery meter code.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
|
||
|
#include <initguid.h>
|
||
|
#include <ntpoapi.h>
|
||
|
#include <poclass.h>
|
||
|
|
||
|
#include "systray.h"
|
||
|
|
||
|
#include "batmeter.h"
|
||
|
#include "powrprof.h"
|
||
|
#include "powercfp.h"
|
||
|
|
||
|
#define UPDATE_REGISTRY TRUE
|
||
|
#define NO_REGISTRY_UPDATE FALSE
|
||
|
|
||
|
// Structure to manage the power profile enum proc parameters.
|
||
|
typedef struct _POWER_PROFILE_ENUM_PROC_PARAMS
|
||
|
{
|
||
|
UINT uiCurActiveIndex;
|
||
|
HMENU hMenu;
|
||
|
UINT uiCurActiveID;
|
||
|
} POWER_PROFILE_ENUM_PROC_PARAMS, *PPOWER_PROFILE_ENUM_PROC_PARAMS;
|
||
|
|
||
|
|
||
|
// G L O B A L D A T A -------------------------------------------------------
|
||
|
BOOL g_bPowerEnabled; // Tracks the power service state.
|
||
|
UINT g_uiPowerSchemeCount; // Number of power schemes, left context menu.
|
||
|
HMENU g_hMenu[2]; // Context menus.
|
||
|
|
||
|
// BatMeter creation parameters.
|
||
|
HWND g_hwndBatMeter;
|
||
|
BOOL g_bShowMulti;
|
||
|
HWND g_hwndBatMeterFrame;
|
||
|
|
||
|
GLOBAL_POWER_POLICY g_gpp;
|
||
|
|
||
|
// Context sensitive help must be added to the windows.hlp file,
|
||
|
// for now we will use this dummy array define. Remove when windows.hlp updated.
|
||
|
|
||
|
#define IDH_POWERCFG_ENABLEMULTI IDH_POWERCFG_POWERSTATUSBAR
|
||
|
|
||
|
const DWORD g_ContextMenuHelpIDs[] = {
|
||
|
IDC_POWERSTATUSGROUPBOX, IDH_COMM_GROUPBOX,
|
||
|
IDC_ENABLEMETER, IDH_POWERCFG_ENABLEMETER,
|
||
|
IDC_ENABLEMULTI, IDH_POWERCFG_ENABLEMULTI,
|
||
|
0, 0
|
||
|
};
|
||
|
|
||
|
// Used to track registration for WM_DEVICECHANGED message.
|
||
|
HDEVNOTIFY g_hDevNotify;
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* RunningOffLine
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
BOOLEAN RunningOffLine(void)
|
||
|
{
|
||
|
SYSTEM_POWER_STATUS sps;
|
||
|
BOOLEAN bRet = FALSE;
|
||
|
|
||
|
if (GetSystemPowerStatus(&sps)) {
|
||
|
if (sps.ACLineStatus == 0) {
|
||
|
bRet = TRUE;
|
||
|
}
|
||
|
}
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* Power_OnCommand
|
||
|
*
|
||
|
* Process WM_COMMAND msgs for the battery meter dialog.
|
||
|
*
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void
|
||
|
Power_OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
BOOL Checked;
|
||
|
DWORD dwMask;
|
||
|
UINT uiCommandID = GET_WM_COMMAND_ID(wParam, lParam);
|
||
|
|
||
|
switch (uiCommandID) {
|
||
|
|
||
|
case IDC_ENABLEMETER:
|
||
|
dwMask = EnableSysTrayBatteryMeter;
|
||
|
goto DoUpdateFlags;
|
||
|
|
||
|
case IDC_ENABLEMULTI:
|
||
|
dwMask = EnableMultiBatteryDisplay;
|
||
|
goto DoUpdateFlags;
|
||
|
|
||
|
DoUpdateFlags:
|
||
|
Checked = (IsDlgButtonChecked(hWnd, uiCommandID) == BST_CHECKED);
|
||
|
Update_PowerFlags(dwMask, Checked);
|
||
|
if (uiCommandID == IDC_ENABLEMETER) {
|
||
|
PowerCfg_Notify();
|
||
|
SysTray_EnableService(STSERVICE_POWER, g_gpp.user.GlobalFlags & EnableSysTrayBatteryMeter);
|
||
|
}
|
||
|
else {
|
||
|
g_bShowMulti = Checked;
|
||
|
Power_UpdateStatus(hWnd, NIM_MODIFY, TRUE);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case IDCANCEL:
|
||
|
EndDialog(hWnd, wParam);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
// Notify battery meter of enter key events.
|
||
|
if (HIWORD(wParam) == BN_CLICKED) {
|
||
|
SendMessage(g_hwndBatMeter, WM_COMMAND, wParam, lParam);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* Power_OnPowerBroadcast
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Process WM_POWERBROADCAS message for the battery meter dialog.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
void Power_OnPowerBroadcast(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
if (wParam == PBT_APMPOWERSTATUSCHANGE) {
|
||
|
|
||
|
// If the power icon is not showing (power service disabled) and
|
||
|
// we are running on batteries, enable the systray power service.
|
||
|
if (!g_bPowerEnabled && RunningOffLine()) {
|
||
|
PostMessage(hWnd, STWM_ENABLESERVICE, STSERVICE_POWER, TRUE);
|
||
|
} else
|
||
|
|
||
|
// If the power icon is showing (power service enabled) and
|
||
|
// we are not running on batteries, disable the systray power service.
|
||
|
if (g_bPowerEnabled && !RunningOffLine()) {
|
||
|
PostMessage(hWnd, STWM_ENABLESERVICE, STSERVICE_POWER, FALSE);
|
||
|
}
|
||
|
|
||
|
// Don't change the state of the power service, just update the icon.
|
||
|
Power_UpdateStatus(hWnd, NIM_MODIFY, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* Power_OnDeviceChange
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Process WM_DEVICECHANGE message for the battery meter dialog.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
void Power_OnDeviceChange(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
//
|
||
|
// Only listen to the WM_DEVICECHANGE if it is for GUID_DEVICE_BATTERY and
|
||
|
// it is a DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE, or DBT_DEVICEQUERYREMOVEFAILED.
|
||
|
//
|
||
|
if (((wParam == DBT_DEVICEARRIVAL) ||
|
||
|
(wParam == DBT_DEVICEREMOVECOMPLETE) ||
|
||
|
(wParam == DBT_DEVICEQUERYREMOVEFAILED)) &&
|
||
|
(lParam) &&
|
||
|
(((PDEV_BROADCAST_DEVICEINTERFACE)lParam)->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE) &&
|
||
|
(IsEqualGUID(&((PDEV_BROADCAST_DEVICEINTERFACE)lParam)->dbcc_classguid, &GUID_DEVICE_BATTERY))) {
|
||
|
|
||
|
// Make sure BatMeter has been initialized.
|
||
|
if (g_hwndBatMeterFrame) {
|
||
|
if (g_hwndBatMeter) {
|
||
|
g_hwndBatMeter = DestroyBatMeter(g_hwndBatMeter);
|
||
|
}
|
||
|
g_hwndBatMeter = CreateBatMeter(hWnd,
|
||
|
g_hwndBatMeterFrame,
|
||
|
g_bShowMulti,
|
||
|
NULL);
|
||
|
InvalidateRect(hWnd, NULL, TRUE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* Power_OnActivate
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
BOOLEAN Power_OnActivate(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
if (g_hwndBatMeter) {
|
||
|
SendMessage(g_hwndBatMeter, WM_ACTIVATE, wParam, lParam);
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* PowerProfileEnumProc
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#define POWERMENU_SCHEME 300
|
||
|
|
||
|
BOOLEAN CALLBACK PowerProfileEnumProc(
|
||
|
UINT uiID,
|
||
|
DWORD dwNameSize,
|
||
|
LPTSTR lpszName,
|
||
|
DWORD dwDescSize,
|
||
|
LPTSTR lpszDesc,
|
||
|
PPOWER_POLICY ppp,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
PPOWER_PROFILE_ENUM_PROC_PARAMS pppepp;
|
||
|
MENUITEMINFO mii;
|
||
|
|
||
|
if ((pppepp = (PPOWER_PROFILE_ENUM_PROC_PARAMS) lParam) == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
AppendMenu(pppepp->hMenu, MF_STRING,
|
||
|
POWERMENU_SCHEME + g_uiPowerSchemeCount, lpszName);
|
||
|
|
||
|
// Store the power scheme ID in the menu info.
|
||
|
mii.cbSize = sizeof(mii);
|
||
|
mii.fMask = MIIM_DATA;
|
||
|
mii.dwItemData = uiID;
|
||
|
SetMenuItemInfo(pppepp->hMenu,
|
||
|
POWERMENU_SCHEME + g_uiPowerSchemeCount,
|
||
|
FALSE, &mii);
|
||
|
|
||
|
if (uiID == pppepp->uiCurActiveID) {
|
||
|
pppepp->uiCurActiveIndex = POWERMENU_SCHEME + g_uiPowerSchemeCount;
|
||
|
}
|
||
|
|
||
|
g_uiPowerSchemeCount++;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* GetPowerMenu()
|
||
|
*
|
||
|
* Build a menu containing battery meter/power selections.
|
||
|
*
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
#define POWERMENU_OPEN 100
|
||
|
#define POWERMENU_PROPERTIES 101
|
||
|
|
||
|
#define POWERMENU_ENABLEWARN 200
|
||
|
#define POWERMENU_SHOWTIME 201
|
||
|
#define POWERMENU_SHOWPERCENT 202
|
||
|
|
||
|
|
||
|
HMENU
|
||
|
GetPowerMenu(LONG l)
|
||
|
{
|
||
|
LPTSTR lpszMenu;
|
||
|
UINT uiCurActiveID;
|
||
|
|
||
|
POWER_PROFILE_ENUM_PROC_PARAMS ppepp;
|
||
|
|
||
|
if (l > 0)
|
||
|
{
|
||
|
// Right button menu -- can change, rebuild each time.
|
||
|
if (g_hMenu[0])
|
||
|
{
|
||
|
DestroyMenu(g_hMenu[0]);
|
||
|
}
|
||
|
|
||
|
g_hMenu[1] = CreatePopupMenu();
|
||
|
|
||
|
// Properties for Power, PowerCfg.
|
||
|
if ((lpszMenu = LoadDynamicString(IDS_PROPFORPOWER)) != NULL)
|
||
|
{
|
||
|
AppendMenu(g_hMenu[1], MF_STRING, POWERMENU_PROPERTIES, lpszMenu);
|
||
|
DeleteDynamicString(lpszMenu);
|
||
|
}
|
||
|
|
||
|
// If we have a battery meter, add it's menu item and set as default.
|
||
|
if (g_hwndBatMeter) {
|
||
|
if ((lpszMenu = LoadDynamicString(IDS_OPEN)) != NULL)
|
||
|
{
|
||
|
AppendMenu(g_hMenu[1], MF_STRING, POWERMENU_OPEN, lpszMenu);
|
||
|
DeleteDynamicString(lpszMenu);
|
||
|
}
|
||
|
// Open BatMeter is default (double click action)
|
||
|
SetMenuDefaultItem(g_hMenu[1], POWERMENU_OPEN, FALSE);
|
||
|
}
|
||
|
else {
|
||
|
// Use open PowerCfg as default (double click action)
|
||
|
SetMenuDefaultItem(g_hMenu[1], POWERMENU_PROPERTIES, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Left button menu -- can change, rebuild each time.
|
||
|
if (g_hMenu[0])
|
||
|
{
|
||
|
DestroyMenu(g_hMenu[0]);
|
||
|
}
|
||
|
|
||
|
g_hMenu[0] = CreatePopupMenu();
|
||
|
|
||
|
// Get the currently active power policies.
|
||
|
if (GetActivePwrScheme(&uiCurActiveID)) {
|
||
|
g_uiPowerSchemeCount = 0;
|
||
|
ppepp.hMenu = g_hMenu[0];
|
||
|
ppepp.uiCurActiveID = uiCurActiveID;
|
||
|
EnumPwrSchemes(PowerProfileEnumProc, (LPARAM)&ppepp);
|
||
|
|
||
|
// Check the currently active menu item.
|
||
|
CheckMenuRadioItem(g_hMenu[0],
|
||
|
POWERMENU_SCHEME,
|
||
|
POWERMENU_SCHEME + g_uiPowerSchemeCount - 1,
|
||
|
ppepp.uiCurActiveIndex,
|
||
|
MF_BYCOMMAND);
|
||
|
}
|
||
|
return g_hMenu[l];
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* Power_Open
|
||
|
*
|
||
|
* Update and display the battery meter dialog
|
||
|
*
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void
|
||
|
Power_Open(HWND hWnd)
|
||
|
{
|
||
|
if (g_hwndBatMeter) {
|
||
|
SetFocus(GetDlgItem(hWnd, IDC_ENABLEMETER));
|
||
|
CheckDlgButton(hWnd, IDC_ENABLEMULTI,
|
||
|
(g_gpp.user.GlobalFlags & EnableMultiBatteryDisplay) ?
|
||
|
BST_CHECKED : BST_UNCHECKED);
|
||
|
|
||
|
CheckDlgButton(hWnd, IDC_ENABLEMETER,
|
||
|
(g_gpp.user.GlobalFlags & EnableSysTrayBatteryMeter) ?
|
||
|
BST_CHECKED : BST_UNCHECKED);
|
||
|
|
||
|
Power_UpdateStatus(hWnd, NIM_MODIFY, FALSE); // show current info
|
||
|
ShowWindow(hWnd, SW_SHOW);
|
||
|
SetForegroundWindow(hWnd);
|
||
|
}
|
||
|
else {
|
||
|
SysTray_RunProperties(IDS_RUNPOWERPROPERTIES);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* DoPowerMenu
|
||
|
*
|
||
|
* Create and process a right or left button menu.
|
||
|
*
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void
|
||
|
DoPowerMenu(HWND hwnd, UINT uMenuNum, UINT uButton)
|
||
|
{
|
||
|
POINT pt;
|
||
|
UINT iCmd;
|
||
|
MENUITEMINFO mii;
|
||
|
|
||
|
SetForegroundWindow(hwnd);
|
||
|
GetCursorPos(&pt);
|
||
|
|
||
|
iCmd = (UINT)TrackPopupMenu(GetPowerMenu(uMenuNum),
|
||
|
uButton | TPM_RETURNCMD | TPM_NONOTIFY,
|
||
|
pt.x, pt.y, 0, hwnd, NULL);
|
||
|
|
||
|
if (iCmd >= POWERMENU_SCHEME) {
|
||
|
mii.cbSize = sizeof(mii);
|
||
|
mii.fMask = MIIM_DATA;
|
||
|
if (GetMenuItemInfo(g_hMenu[uMenuNum], iCmd, FALSE, &mii)) {
|
||
|
SetActivePwrScheme((UINT)mii.dwItemData, NULL, NULL);
|
||
|
PowerCfg_Notify();
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
switch (iCmd) {
|
||
|
|
||
|
case POWERMENU_OPEN:
|
||
|
Power_Open(hwnd);
|
||
|
break;
|
||
|
|
||
|
case POWERMENU_PROPERTIES:
|
||
|
SysTray_RunProperties(IDS_RUNPOWERPROPERTIES);
|
||
|
break;
|
||
|
|
||
|
case 0:
|
||
|
// The user cancelled the menu without choosing.
|
||
|
SetIconFocus(hwnd, STWM_NOTIFYPOWER);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* Power_Notify
|
||
|
*
|
||
|
* Handle a notification from the power tray icon.
|
||
|
*
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
#define PN_TIMER_CLEAR 0
|
||
|
#define PN_TIMER_SET 1
|
||
|
#define PN_DBLCLK 2
|
||
|
|
||
|
UINT g_uiTimerSet = PN_TIMER_CLEAR;
|
||
|
LARGE_INTEGER g_liHoverUpdateTime = {0,0};
|
||
|
|
||
|
void Power_Notify(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LARGE_INTEGER liPerformanceFrequency;
|
||
|
LARGE_INTEGER liPerformanceCount;
|
||
|
|
||
|
switch (lParam)
|
||
|
{
|
||
|
case WM_RBUTTONUP:
|
||
|
DoPowerMenu(hWnd, 1, TPM_RIGHTBUTTON); // right button menu
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONUP:
|
||
|
// start timing for left button menu
|
||
|
if (g_uiTimerSet == PN_TIMER_CLEAR) {
|
||
|
SetTimer(hWnd, POWER_TIMER_ID, GetDoubleClickTime()+100, NULL);
|
||
|
g_uiTimerSet = PN_TIMER_SET;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONDBLCLK:
|
||
|
g_uiTimerSet = PN_DBLCLK;
|
||
|
Power_Open(hWnd); // show battery meter dialog
|
||
|
break;
|
||
|
|
||
|
case WM_MOUSEMOVE:
|
||
|
if (QueryPerformanceFrequency (&liPerformanceFrequency)) {
|
||
|
if (QueryPerformanceCounter (&liPerformanceCount)) {
|
||
|
// Update no more than once a second
|
||
|
if ((liPerformanceCount.QuadPart - g_liHoverUpdateTime.QuadPart) >
|
||
|
liPerformanceFrequency.QuadPart) {
|
||
|
g_liHoverUpdateTime = liPerformanceCount;
|
||
|
Power_UpdateStatus(hWnd, NIM_MODIFY, FALSE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*-----------------------------------------------------------------------------
|
||
|
* Power_Timer
|
||
|
*
|
||
|
* Execute the left button menu on WM_LBUTTONDOWN time-out.
|
||
|
*
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void Power_Timer(HWND hwnd)
|
||
|
{
|
||
|
KillTimer(hwnd, POWER_TIMER_ID);
|
||
|
if (g_uiTimerSet != PN_DBLCLK) {
|
||
|
DoPowerMenu(hwnd, 0, TPM_LEFTBUTTON);
|
||
|
}
|
||
|
g_uiTimerSet = PN_TIMER_CLEAR;
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* Update_PowerFlags
|
||
|
*
|
||
|
* Set power flags using powrprof.dll API's.
|
||
|
*
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void Update_PowerFlags(DWORD dwMask, BOOL bEnable)
|
||
|
{
|
||
|
if (bEnable) {
|
||
|
g_gpp.user.GlobalFlags |= dwMask;
|
||
|
}
|
||
|
else {
|
||
|
g_gpp.user.GlobalFlags &= ~dwMask;
|
||
|
}
|
||
|
WriteGlobalPwrPolicy(&g_gpp);
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* Get_PowerFlags
|
||
|
*
|
||
|
* Get power flags using powrprof.dll API's.
|
||
|
*
|
||
|
*----------------------------------------------------------------------------*/
|
||
|
|
||
|
DWORD Get_PowerFlags(void)
|
||
|
{
|
||
|
ReadGlobalPwrPolicy(&g_gpp);
|
||
|
return g_gpp.user.GlobalFlags;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* BatteryMeterInit
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* NOTE: Can be called multiple times. Simply re-init.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* (returns), TRUE if the Battery Meter could be enabled
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
BOOL PASCAL BatteryMeterInit(HWND hWnd)
|
||
|
{
|
||
|
PUINT puiBatCount = NULL;
|
||
|
|
||
|
if (!BatMeterCapabilities(&puiBatCount)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!g_hwndBatMeter) {
|
||
|
g_hwndBatMeterFrame = GetDlgItem(hWnd, IDC_STATIC_FRAME_BATMETER);
|
||
|
g_bShowMulti = g_gpp.user.GlobalFlags & EnableMultiBatteryDisplay;
|
||
|
g_hwndBatMeter = CreateBatMeter(hWnd,
|
||
|
g_hwndBatMeterFrame,
|
||
|
g_bShowMulti,
|
||
|
NULL);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* Power_UpdateStatus
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
VOID PASCAL Power_UpdateStatus(
|
||
|
HWND hWnd,
|
||
|
DWORD NotifyIconMessage,
|
||
|
BOOL bForceUpdate
|
||
|
)
|
||
|
{
|
||
|
static TCHAR szTipCache[64];
|
||
|
static HICON hIconCache;
|
||
|
|
||
|
TCHAR szTip[64];
|
||
|
LPTSTR lpsz;
|
||
|
BATTERY_STATE bs;
|
||
|
UINT uiHour, uiMin;
|
||
|
|
||
|
*szTip = 0;
|
||
|
|
||
|
bs.ulSize = sizeof(BATTERY_STATE);
|
||
|
UpdateBatMeter(g_hwndBatMeter,
|
||
|
g_bShowMulti,
|
||
|
bForceUpdate,
|
||
|
&bs);
|
||
|
|
||
|
// Build up a new tool tip.
|
||
|
if (g_hwndBatMeter &&
|
||
|
!(((bs.ulPowerState & BATTERY_POWER_ON_LINE) &&
|
||
|
!(bs.ulPowerState & BATTERY_CHARGING)))) {
|
||
|
|
||
|
if (bs.ulBatLifePercent <= 100) {
|
||
|
if (bs.ulBatLifeTime != (UINT) -1) {
|
||
|
uiHour = bs.ulBatLifeTime / 3600;
|
||
|
uiMin = (bs.ulBatLifeTime % 3600) / 60;
|
||
|
if (uiHour) {
|
||
|
lpsz = LoadDynamicString(IDS_TIMEREMFORMATHOUR,
|
||
|
uiHour, uiMin,
|
||
|
bs.ulBatLifePercent);
|
||
|
}
|
||
|
else {
|
||
|
lpsz = LoadDynamicString(IDS_TIMEREMFORMATMIN, uiMin,
|
||
|
bs.ulBatLifePercent);
|
||
|
}
|
||
|
if (lpsz) {
|
||
|
lstrcpy(szTip, lpsz);
|
||
|
LocalFree(lpsz);
|
||
|
if (bs.ulPowerState & BATTERY_CHARGING) {
|
||
|
if ((lpsz = LoadDynamicString(IDS_CHARGING)) != NULL) {
|
||
|
lstrcat(szTip, lpsz);
|
||
|
LocalFree(lpsz);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if ((lpsz = LoadDynamicString(IDS_REMAINING,
|
||
|
bs.ulBatLifePercent)) != NULL) {
|
||
|
lstrcpy(szTip, lpsz);
|
||
|
LocalFree(lpsz);
|
||
|
if (bs.ulPowerState & BATTERY_CHARGING) {
|
||
|
if ((lpsz = LoadDynamicString(IDS_CHARGING)) != NULL) {
|
||
|
lstrcat(szTip, lpsz);
|
||
|
LocalFree(lpsz);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
lpsz = LoadDynamicString(IDS_UNKNOWN);
|
||
|
lstrcpy(szTip, lpsz);
|
||
|
LocalFree(lpsz);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
lpsz = LoadDynamicString(IDS_ACPOWER);
|
||
|
lstrcpy(szTip, lpsz);
|
||
|
LocalFree(lpsz);
|
||
|
}
|
||
|
|
||
|
if ((NotifyIconMessage == NIM_ADD) ||
|
||
|
(hIconCache != bs.hIconCache16) ||
|
||
|
(lstrcmp(szTip, szTipCache))) {
|
||
|
|
||
|
hIconCache = bs.hIconCache16;
|
||
|
lstrcpy(szTipCache, szTip);
|
||
|
|
||
|
SysTray_NotifyIcon(hWnd, STWM_NOTIFYPOWER, NotifyIconMessage,
|
||
|
hIconCache, szTipCache);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* RegisterForDeviceNotification
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Do onetime registration for WM_DEVICECHANGED.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
BOOL RegisterForDeviceNotification(HWND hWnd)
|
||
|
{
|
||
|
DEV_BROADCAST_DEVICEINTERFACE dbc;
|
||
|
|
||
|
memset(&dbc, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
|
||
|
dbc.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
||
|
dbc.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||
|
dbc.dbcc_classguid = GUID_DEVICE_BATTERY;
|
||
|
g_hDevNotify = RegisterDeviceNotification(hWnd,
|
||
|
&dbc,
|
||
|
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||
|
if (!g_hDevNotify) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* Power_WmDestroy
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
void Power_WmDestroy(HWND hWnd)
|
||
|
{
|
||
|
if (g_hDevNotify) {
|
||
|
UnregisterDeviceNotification(g_hDevNotify);
|
||
|
g_hDevNotify = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* Power_CheckEnable
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Return TRUE if the power service icon was enabled.
|
||
|
* Can be called multiple times. Simply re-init.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* bSvcEnabled - Request to enable/disable power service on tray.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
BOOL Power_CheckEnable(HWND hWnd, BOOL bSvcEnable)
|
||
|
{
|
||
|
static BOOL bRegisteredForDC = FALSE;
|
||
|
|
||
|
// Is there any reason to display the systray power icon?
|
||
|
if (!PowerCapabilities()) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Do onetime registration for WM_DEVICECHANGED.
|
||
|
if (!bRegisteredForDC) {
|
||
|
bRegisteredForDC = RegisterForDeviceNotification(hWnd);
|
||
|
}
|
||
|
|
||
|
// Get current battery meter flags from the registry
|
||
|
Get_PowerFlags();
|
||
|
|
||
|
// Are we running on battery power or has the user set
|
||
|
// the systray power icon to always on? If so, force enable.
|
||
|
if ((g_gpp.user.GlobalFlags & EnableSysTrayBatteryMeter) ||
|
||
|
(RunningOffLine())) {
|
||
|
bSvcEnable = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
bSvcEnable = FALSE;
|
||
|
}
|
||
|
|
||
|
// Set the power service state.
|
||
|
if (bSvcEnable) {
|
||
|
if (g_bPowerEnabled) {
|
||
|
Power_UpdateStatus(hWnd, NIM_MODIFY, FALSE);
|
||
|
}
|
||
|
else {
|
||
|
BatteryMeterInit(hWnd);
|
||
|
Power_UpdateStatus(hWnd, NIM_ADD, FALSE);
|
||
|
}
|
||
|
g_bPowerEnabled = TRUE;
|
||
|
}
|
||
|
else {
|
||
|
SysTray_NotifyIcon(hWnd, STWM_NOTIFYPOWER, NIM_DELETE, NULL, NULL);
|
||
|
g_bPowerEnabled = FALSE;
|
||
|
}
|
||
|
return g_bPowerEnabled;
|
||
|
}
|