2 * PROJECT: ReactOS system libraries
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/shellext/stobject/power.cpp
5 * PURPOSE: Power notification icon handler
6 * PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
7 Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
8 * David Quintana <gigaherz@gmail.com>
19 int br_icons
[5] = { IDI_BATTCAP0
, IDI_BATTCAP1
, IDI_BATTCAP2
, IDI_BATTCAP3
, IDI_BATTCAP4
}; // battery mode icons.
20 int bc_icons
[5] = { IDI_BATTCHA0
, IDI_BATTCHA1
, IDI_BATTCHA2
, IDI_BATTCHA3
, IDI_BATTCHA4
}; // charging mode icons.
22 typedef struct _PWRSCHEMECONTEXT
27 } PWRSCHEMECONTEXT
, *PPWRSCHEMECONTEXT
;
30 static HICON g_hIconBattery
= NULL
;
36 * This function quantizes the mentioned quantity to nearest level.
39 * Should be a quantity in percentage.
41 * @return Nearest quantized level, can be directly used as array index based on context.
43 @remarks This function uses centred/symmetric logic for quantization.
44 For the case of lvl = 4, You will get following integer levels if given (p) value falls in between the range partitions:
45 0 <= p < 12.5 : returns 0; (corresponding to 0% centre)
46 12.5 <= p < 37.5 : returns 1; (corresponding to 25% centre)
47 37.5 <= p < 62.5 : returns 2; (corresponding to 50% centre)
48 62.5 <= p < 87.5 : returns 3; (corresponding to 75% centre)
49 87.5 <= p <= 100 : returns 4; (corresponding to 100% centre)
51 static UINT
Quantize(BYTE p
)
55 else if (p
> 12 && p
<= 37)
57 else if (p
> 37 && p
<= 62)
59 else if (p
> 62 && p
<= 87)
66 * @name DynamicLoadIcon
68 * Returns the respective icon as per the current battery capacity.
69 * It also does the work of setting global parameters of battery capacity and tooltips.
72 * A handle to a instance of the module.
74 * @return The handle to respective battery icon.
77 static HICON
DynamicLoadIcon(HINSTANCE hinst
)
79 SYSTEM_POWER_STATUS PowerStatus
;
83 if (!GetSystemPowerStatus(&PowerStatus
) ||
84 PowerStatus
.ACLineStatus
== AC_LINE_UNKNOWN
||
85 PowerStatus
.BatteryFlag
== BATTERY_FLAG_UNKNOWN
)
87 hBatIcon
= LoadIcon(hinst
, MAKEINTRESOURCE(IDI_BATTCAP_ERR
));
88 g_strTooltip
.LoadStringW(IDS_PWR_UNKNOWN_REMAINING
);
92 if (((PowerStatus
.BatteryFlag
& BATTERY_FLAG_NO_BATTERY
) == 0) &&
93 ((PowerStatus
.BatteryFlag
& BATTERY_FLAG_CHARGING
) == BATTERY_FLAG_CHARGING
))
95 index
= Quantize(PowerStatus
.BatteryLifePercent
);
96 hBatIcon
= LoadIcon(hinst
, MAKEINTRESOURCE(bc_icons
[index
]));
97 g_strTooltip
.Format(IDS_PWR_CHARGING
, PowerStatus
.BatteryLifePercent
);
99 else if (((PowerStatus
.BatteryFlag
& BATTERY_FLAG_NO_BATTERY
) == 0) &&
100 ((PowerStatus
.BatteryFlag
& BATTERY_FLAG_CHARGING
) == 0))
102 index
= Quantize(PowerStatus
.BatteryLifePercent
);
103 hBatIcon
= LoadIcon(hinst
, MAKEINTRESOURCE(br_icons
[index
]));
104 g_strTooltip
.Format(IDS_PWR_PERCENT_REMAINING
, PowerStatus
.BatteryLifePercent
);
108 hBatIcon
= LoadIcon(hinst
, MAKEINTRESOURCE(IDI_POWER_AC
));
109 g_strTooltip
.LoadStringW(IDS_PWR_AC
);
115 HRESULT STDMETHODCALLTYPE
Power_Init(_In_ CSysTray
* pSysTray
)
117 TRACE("Power_Init\n");
118 g_hIconBattery
= DynamicLoadIcon(g_hInstance
);
120 return pSysTray
->NotifyIcon(NIM_ADD
, ID_ICON_POWER
, g_hIconBattery
, g_strTooltip
);
123 HRESULT STDMETHODCALLTYPE
Power_Update(_In_ CSysTray
* pSysTray
)
125 TRACE("Power_Update\n");
126 g_hIconBattery
= DynamicLoadIcon(g_hInstance
);
128 return pSysTray
->NotifyIcon(NIM_MODIFY
, ID_ICON_POWER
, g_hIconBattery
, g_strTooltip
);
131 HRESULT STDMETHODCALLTYPE
Power_Shutdown(_In_ CSysTray
* pSysTray
)
133 TRACE("Power_Shutdown\n");
135 return pSysTray
->NotifyIcon(NIM_DELETE
, ID_ICON_POWER
, NULL
, NULL
);
138 static void _RunPower()
140 ShellExecuteW(NULL
, NULL
, L
"powercfg.cpl", NULL
, NULL
, SW_SHOWNORMAL
);
143 static void _ShowContextMenu(CSysTray
* pSysTray
)
145 CString
strOpen((LPCSTR
)IDS_PWR_PROPERTIES
);
146 HMENU hPopup
= CreatePopupMenu();
147 AppendMenuW(hPopup
, MF_STRING
, IDS_PWR_PROPERTIES
, strOpen
);
148 SetMenuDefaultItem(hPopup
, IDS_PWR_PROPERTIES
, FALSE
);
150 SetForegroundWindow(pSysTray
->GetHWnd());
151 DWORD flags
= TPM_RETURNCMD
| TPM_NONOTIFY
| TPM_RIGHTALIGN
| TPM_BOTTOMALIGN
;
155 DWORD id
= TrackPopupMenuEx(hPopup
, flags
,
157 pSysTray
->GetHWnd(), NULL
);
161 case IDS_PWR_PROPERTIES
:
171 PowerSchemesEnumProc(
180 PPWRSCHEMECONTEXT PowerSchemeContext
= (PPWRSCHEMECONTEXT
)lParam
;
182 if (AppendMenuW(PowerSchemeContext
->hPopup
, MF_STRING
, uiIndex
+ 1, sName
))
184 if (PowerSchemeContext
->uiFirst
== 0)
185 PowerSchemeContext
->uiFirst
= uiIndex
+ 1;
187 PowerSchemeContext
->uiLast
= uiIndex
+ 1;
195 ShowPowerSchemesPopupMenu(
198 PWRSCHEMECONTEXT PowerSchemeContext
= {NULL
, 0, 0};
202 PowerSchemeContext
.hPopup
= CreatePopupMenu();
203 EnumPwrSchemes(PowerSchemesEnumProc
, (LPARAM
)&PowerSchemeContext
);
205 if (GetActivePwrScheme(&uiActiveScheme
))
207 CheckMenuRadioItem(PowerSchemeContext
.hPopup
,
208 PowerSchemeContext
.uiFirst
,
209 PowerSchemeContext
.uiLast
,
214 SetForegroundWindow(pSysTray
->GetHWnd());
217 id
= TrackPopupMenuEx(PowerSchemeContext
.hPopup
,
218 TPM_RETURNCMD
| TPM_NONOTIFY
| TPM_RIGHTALIGN
| TPM_BOTTOMALIGN
,
224 DestroyMenu(PowerSchemeContext
.hPopup
);
227 SetActivePwrScheme(id
- 1, NULL
, NULL
);
230 HRESULT STDMETHODCALLTYPE
Power_Message(_In_ CSysTray
* pSysTray
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
)
232 TRACE("Power_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg
, wParam
, lParam
);
237 TRACE("Power_Message: WM_USER+220\n");
238 if (wParam
== POWER_SERVICE_FLAG
)
242 pSysTray
->EnableService(POWER_SERVICE_FLAG
, TRUE
);
243 return Power_Init(pSysTray
);
247 pSysTray
->EnableService(POWER_SERVICE_FLAG
, FALSE
);
248 return Power_Shutdown(pSysTray
);
254 TRACE("Power_Message: WM_USER+221\n");
255 if (wParam
== POWER_SERVICE_FLAG
)
257 lResult
= (LRESULT
)pSysTray
->IsServiceEnabled(POWER_SERVICE_FLAG
);
263 if (wParam
== POWER_TIMER_ID
)
265 KillTimer(pSysTray
->GetHWnd(), POWER_TIMER_ID
);
266 ShowPowerSchemesPopupMenu(pSysTray
);
271 Power_Update(pSysTray
);
276 SetTimer(pSysTray
->GetHWnd(), POWER_TIMER_ID
, GetDoubleClickTime(), NULL
);
282 case WM_LBUTTONDBLCLK
:
283 KillTimer(pSysTray
->GetHWnd(), POWER_TIMER_ID
);
291 _ShowContextMenu(pSysTray
);
294 case WM_RBUTTONDBLCLK
:
303 TRACE("Power_Message received for unknown ID %d, ignoring.\n");