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
;
31 static BOOL g_IsRunning
= FALSE
;
37 * This function quantizes the mentioned quantity to nearest level.
40 * Should be a quantity in percentage.
42 * @return Nearest quantized level, can be directly used as array index based on context.
44 @remarks This function uses centred/symmetric logic for quantization.
45 For the case of lvl = 4, You will get following integer levels if given (p) value falls in between the range partitions:
46 0 <= p < 12.5 : returns 0; (corresponding to 0% centre)
47 12.5 <= p < 37.5 : returns 1; (corresponding to 25% centre)
48 37.5 <= p < 62.5 : returns 2; (corresponding to 50% centre)
49 62.5 <= p < 87.5 : returns 3; (corresponding to 75% centre)
50 87.5 <= p <= 100 : returns 4; (corresponding to 100% centre)
52 static UINT
Quantize(BYTE p
)
56 else if (p
> 12 && p
<= 37)
58 else if (p
> 37 && p
<= 62)
60 else if (p
> 62 && p
<= 87)
67 * @name DynamicLoadIcon
69 * Returns the respective icon as per the current battery capacity.
70 * It also does the work of setting global parameters of battery capacity and tooltips.
73 * A handle to a instance of the module.
75 * @return The handle to respective battery icon.
78 static HICON
DynamicLoadIcon(HINSTANCE hinst
)
80 SYSTEM_POWER_STATUS PowerStatus
;
84 if (!GetSystemPowerStatus(&PowerStatus
) ||
85 PowerStatus
.ACLineStatus
== AC_LINE_UNKNOWN
||
86 PowerStatus
.BatteryFlag
== BATTERY_FLAG_UNKNOWN
)
88 hBatIcon
= LoadIcon(hinst
, MAKEINTRESOURCE(IDI_BATTCAP_ERR
));
89 g_strTooltip
.LoadStringW(IDS_PWR_UNKNOWN_REMAINING
);
93 if (((PowerStatus
.BatteryFlag
& BATTERY_FLAG_NO_BATTERY
) == 0) &&
94 ((PowerStatus
.BatteryFlag
& BATTERY_FLAG_CHARGING
) == BATTERY_FLAG_CHARGING
))
96 index
= Quantize(PowerStatus
.BatteryLifePercent
);
97 hBatIcon
= LoadIcon(hinst
, MAKEINTRESOURCE(bc_icons
[index
]));
98 g_strTooltip
.Format(IDS_PWR_CHARGING
, PowerStatus
.BatteryLifePercent
);
100 else if (((PowerStatus
.BatteryFlag
& BATTERY_FLAG_NO_BATTERY
) == 0) &&
101 ((PowerStatus
.BatteryFlag
& BATTERY_FLAG_CHARGING
) == 0))
103 index
= Quantize(PowerStatus
.BatteryLifePercent
);
104 hBatIcon
= LoadIcon(hinst
, MAKEINTRESOURCE(br_icons
[index
]));
105 g_strTooltip
.Format(IDS_PWR_PERCENT_REMAINING
, PowerStatus
.BatteryLifePercent
);
109 hBatIcon
= LoadIcon(hinst
, MAKEINTRESOURCE(IDI_POWER_AC
));
110 g_strTooltip
.LoadStringW(IDS_PWR_AC
);
116 HRESULT STDMETHODCALLTYPE
Power_Init(_In_ CSysTray
* pSysTray
)
118 TRACE("Power_Init\n");
119 g_hIconBattery
= DynamicLoadIcon(g_hInstance
);
122 return pSysTray
->NotifyIcon(NIM_ADD
, ID_ICON_POWER
, g_hIconBattery
, g_strTooltip
);
125 HRESULT STDMETHODCALLTYPE
Power_Update(_In_ CSysTray
* pSysTray
)
127 TRACE("Power_Update\n");
128 g_hIconBattery
= DynamicLoadIcon(g_hInstance
);
130 return pSysTray
->NotifyIcon(NIM_MODIFY
, ID_ICON_POWER
, g_hIconBattery
, g_strTooltip
);
133 HRESULT STDMETHODCALLTYPE
Power_Shutdown(_In_ CSysTray
* pSysTray
)
135 TRACE("Power_Shutdown\n");
138 return pSysTray
->NotifyIcon(NIM_DELETE
, ID_ICON_POWER
, NULL
, NULL
);
141 static void _RunPower()
143 ShellExecuteW(NULL
, NULL
, L
"powercfg.cpl", NULL
, NULL
, SW_SHOWNORMAL
);
146 static void _ShowContextMenu(CSysTray
* pSysTray
)
148 CString
strOpen((LPCSTR
)IDS_PWR_PROPERTIES
);
149 HMENU hPopup
= CreatePopupMenu();
150 AppendMenuW(hPopup
, MF_STRING
, IDS_PWR_PROPERTIES
, strOpen
);
152 SetForegroundWindow(pSysTray
->GetHWnd());
153 DWORD flags
= TPM_RETURNCMD
| TPM_NONOTIFY
| TPM_RIGHTALIGN
| TPM_BOTTOMALIGN
;
157 DWORD id
= TrackPopupMenuEx(hPopup
, flags
,
159 pSysTray
->GetHWnd(), NULL
);
163 case IDS_PWR_PROPERTIES
:
173 PowerSchemesEnumProc(
182 PPWRSCHEMECONTEXT PowerSchemeContext
= (PPWRSCHEMECONTEXT
)lParam
;
184 if (AppendMenuW(PowerSchemeContext
->hPopup
, MF_STRING
, uiIndex
+ 1, sName
))
186 if (PowerSchemeContext
->uiFirst
== 0)
187 PowerSchemeContext
->uiFirst
= uiIndex
+ 1;
189 PowerSchemeContext
->uiLast
= uiIndex
+ 1;
197 ShowPowerSchemesPopupMenu(
200 PWRSCHEMECONTEXT PowerSchemeContext
= {NULL
, 0, 0};
204 PowerSchemeContext
.hPopup
= CreatePopupMenu();
205 EnumPwrSchemes(PowerSchemesEnumProc
, (LPARAM
)&PowerSchemeContext
);
207 if (GetActivePwrScheme(&uiActiveScheme
))
209 CheckMenuRadioItem(PowerSchemeContext
.hPopup
,
210 PowerSchemeContext
.uiFirst
,
211 PowerSchemeContext
.uiLast
,
216 SetForegroundWindow(pSysTray
->GetHWnd());
219 id
= TrackPopupMenuEx(PowerSchemeContext
.hPopup
,
220 TPM_RETURNCMD
| TPM_NONOTIFY
| TPM_RIGHTALIGN
| TPM_BOTTOMALIGN
,
226 DestroyMenu(PowerSchemeContext
.hPopup
);
229 SetActivePwrScheme(id
- 1, NULL
, NULL
);
232 HRESULT STDMETHODCALLTYPE
Power_Message(_In_ CSysTray
* pSysTray
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
)
234 TRACE("Power_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg
, wParam
, lParam
);
239 TRACE("Power_Message: WM_USER+220\n");
243 return Power_Init(pSysTray
);
245 return Power_Shutdown(pSysTray
);
250 TRACE("Power_Message: WM_USER+221\n");
253 lResult
= (LRESULT
)g_IsRunning
;
259 if (wParam
== POWER_TIMER_ID
)
261 KillTimer(pSysTray
->GetHWnd(), POWER_TIMER_ID
);
262 ShowPowerSchemesPopupMenu(pSysTray
);
267 Power_Update(pSysTray
);
272 SetTimer(pSysTray
->GetHWnd(), POWER_TIMER_ID
, GetDoubleClickTime(), NULL
);
278 case WM_LBUTTONDBLCLK
:
279 KillTimer(pSysTray
->GetHWnd(), POWER_TIMER_ID
);
287 _ShowContextMenu(pSysTray
);
290 case WM_RBUTTONDBLCLK
:
299 TRACE("Power_Message received for unknown ID %d, ignoring.\n");