windows-nt/Source/XPSP1/NT/shell/osshell/cpls/powercfg/batmtrcf.c
2020-09-26 16:20:57 +08:00

336 lines
9.9 KiB
C

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORP., 1996
*
* TITLE: BATMTRCF.C
*
* VERSION: 2.0
*
* AUTHOR: ReedB
*
* DATE: 17 Oct, 1996
*
* DESCRIPTION:
* Support for the battery meter configuration page of PowerCfg.Cpl.
*
*******************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <commctrl.h>
#include <powercfp.h>
#include <dbt.h>
#include <objbase.h>
#include <initguid.h>
#include <ntpoapi.h>
#include <poclass.h>
#include "powercfg.h"
#include "pwrresid.h"
#include "PwrMn_cs.h"
/*******************************************************************************
*
* G L O B A L D A T A
*
*******************************************************************************/
extern UINT g_uiEnableSysTrayFlag;
// A systary change requires PowerSchemeDlgProc re-init.
extern BOOL g_bSystrayChange;
// Persistant storage of this data is managed by POWRPROF.DLL API's.
extern GLOBAL_POWER_POLICY g_gpp;
// Subclass variables:
WNDPROC g_fnOldPropShtProc;
// BatMeter creation parameters.
HWND g_hwndBatMeter;
BOOL g_bShowMulti;
HWND g_hwndBatMeterFrame;
// Show/hide multi-bat display check box.
DWORD g_dwShowMultiBatDispOpt = CONTROL_ENABLE;
// Static flags:
UINT g_uiEnableMultiFlag = EnableMultiBatteryDisplay;
#ifdef WINNT
// Used to track registration for WM_DEVICECHANGED message.
HDEVNOTIFY g_hDevNotify;
#endif
// Battery meter policies dialog controls descriptions:
#define NUM_BATMETERCFG_CONTROLS 1
POWER_CONTROLS g_pcBatMeterCfg[NUM_BATMETERCFG_CONTROLS] =
{// Control ID Control Type Data Address Data Size Parameter Pointer Enable/Visible State Pointer
IDC_ENABLEMULTI, CHECK_BOX, &(g_gpp.user.GlobalFlags), sizeof(g_gpp.user.GlobalFlags), &g_uiEnableMultiFlag, &g_dwShowMultiBatDispOpt,
};
// "Battery Meter" Dialog Box (IDD_BATMETERCFG == 102) help arrays:
const DWORD g_BatMeterCfgHelpIDs[]=
{
IDC_ENABLEMULTI, IDH_102_1204, // Battery Meter: "Show the status of all &batteries." (Button)
IDC_STATIC_FRAME_BATMETER, IDH_102_1205, // Battery Meter: "Batmeter frame" (Static)
IDC_POWERSTATUSGROUPBOX, IDH_102_1201, // Battery Meter: "Power status" (Button)
0, 0
};
#ifdef WINNT
// Private function prototypes
BOOL RegisterForDeviceNotification(HWND hWnd);
void UnregisterForDeviceNotification(void);
#endif
/*******************************************************************************
*
* P U B L I C E N T R Y P O I N T S
*
*******************************************************************************/
/*******************************************************************************
*
* PropShtSubclassProc
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
LRESULT PropShtSubclassProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRet;
lRet = CallWindowProc(g_fnOldPropShtProc, hWnd, uiMsg, wParam, lParam);
if ((uiMsg == WM_POWERBROADCAST) && (wParam == PBT_APMPOWERSTATUSCHANGE)) {
UpdateBatMeter(g_hwndBatMeter, g_bShowMulti, TRUE, NULL);
}
return lRet;
}
/*******************************************************************************
*
* BatMeterCfgDlgProc
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
INT_PTR CALLBACK BatMeterCfgDlgProc
(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static BOOL bDirty = FALSE;
#ifdef WINNT
static BOOL bRegisteredForDC = FALSE;
#endif
NMHDR *lpnm;
switch (uMsg)
{
case WM_INITDIALOG:
// If we can't read the global power policies
// disable the controls on this page.
if (!GetGlobalPwrPolicy(&g_gpp))
{
DisableControls(hWnd, NUM_BATMETERCFG_CONTROLS, g_pcBatMeterCfg);
}
else
{
if (g_gpp.user.GlobalFlags & EnableMultiBatteryDisplay)
{
g_bShowMulti = TRUE;
}
else
{
g_bShowMulti = FALSE;
}
// If we can't write the global power policies disable
// the controls this page.
if (!WriteGlobalPwrPolicyReport(hWnd, &g_gpp, FALSE))
{
HideControls(hWnd, NUM_BATMETERCFG_CONTROLS, g_pcBatMeterCfg);
}
SetControls(hWnd, NUM_BATMETERCFG_CONTROLS, g_pcBatMeterCfg);
}
g_hwndBatMeterFrame = GetDlgItem(hWnd, IDC_STATIC_FRAME_BATMETER);
g_hwndBatMeter = CreateBatMeter(hWnd,
g_hwndBatMeterFrame,
g_bShowMulti,
NULL);
// The top level window must be subclassed to receive
// the WM_POWERBROADCAST message.
if (g_hwndBatMeter) {
g_fnOldPropShtProc =
(WNDPROC) SetWindowLongPtr(GetParent(hWnd), DWLP_DLGPROC,
(LONG_PTR)PropShtSubclassProc);
#ifdef WINNT
// Do onetime registration for WM_DEVICECHANGED.
if (!bRegisteredForDC) {
bRegisteredForDC = RegisterForDeviceNotification(hWnd);
}
#endif
}
return TRUE;
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_APPLY:
if (bDirty)
{
GetControls(hWnd, NUM_BATMETERCFG_CONTROLS, g_pcBatMeterCfg);
WriteGlobalPwrPolicyReport(hWnd, &g_gpp, TRUE);
bDirty = FALSE;
}
break;
}
break;
case WM_COMMAND:
switch (wParam) {
case IDC_ENABLEMULTI:
GetControls(hWnd, NUM_BATMETERCFG_CONTROLS, g_pcBatMeterCfg);
if (g_gpp.user.GlobalFlags & EnableMultiBatteryDisplay) {
g_bShowMulti = TRUE;
}
else {
g_bShowMulti = FALSE;
}
UpdateBatMeter(g_hwndBatMeter, g_bShowMulti, TRUE, NULL);
// Enable the parent dialog Apply button on change.
MarkSheetDirty(hWnd, &bDirty);
break;
default:
// Notify battery meter of enter key events.
if (HIWORD(wParam) == BN_CLICKED) {
SendMessage(g_hwndBatMeter, uMsg, wParam, lParam);
}
}
break;
case PCWM_NOTIFYPOWER:
// Systray changed something. Get the flags and update controls.
if (GetGlobalPwrPolicy(&g_gpp)) {
SetControls(hWnd, NUM_BATMETERCFG_CONTROLS, g_pcBatMeterCfg);
}
g_bSystrayChange = TRUE;
break;
case WM_DEVICECHANGE:
if ((wParam == DBT_DEVICEARRIVAL) ||
#ifndef WINNT
(wParam == DBT_DEVICEREMOVECOMPLETE) ||
#endif
(wParam == DBT_DEVICEQUERYREMOVEFAILED)) {
if (g_hwndBatMeter) {
g_hwndBatMeter = DestroyBatMeter(g_hwndBatMeter);
}
g_hwndBatMeter = CreateBatMeter(hWnd,
g_hwndBatMeterFrame,
g_bShowMulti,
NULL);
InvalidateRect(hWnd, NULL, TRUE);
}
return TRUE;
#ifdef WINNT
case WM_DESTROY:
UnregisterForDeviceNotification();
break;
#endif
case WM_HELP: // F1
WinHelp(((LPHELPINFO)lParam)->hItemHandle, PWRMANHLP, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)g_BatMeterCfgHelpIDs);
return TRUE;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND)wParam, PWRMANHLP, HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)g_BatMeterCfgHelpIDs);
return TRUE;
}
return FALSE;
}
/*******************************************************************************
*
* P R I V A T E F U N C T I O N S
*
*******************************************************************************/
#ifdef WINNT
/*******************************************************************************
*
* 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) {
DebugPrint( "RegisterForDeviceNotification failed");
return FALSE;
}
return TRUE;
}
/*******************************************************************************
*
* UnregisterForDeviceNotification
*
* DESCRIPTION:
*
*
* PARAMETERS:
*
*******************************************************************************/
void UnregisterForDeviceNotification(void)
{
if (g_hDevNotify) {
UnregisterDeviceNotification(g_hDevNotify);
g_hDevNotify = NULL;
}
}
#endif