https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7fbc5f42302be64db4d3383060e3c14bcc1dfac6
commit 7fbc5f42302be64db4d3383060e3c14bcc1dfac6 Author: Shriraj Sawant <sr.offic...@hotmail.com> AuthorDate: Mon Oct 16 17:11:10 2017 +0300 [STOBJECT] Implement the hotplug and the power icons in the system tray --- dll/shellext/stobject/CMakeLists.txt | 4 + dll/shellext/stobject/csystray.cpp | 53 ++-- dll/shellext/stobject/csystray.h | 3 +- dll/shellext/stobject/hotplug.cpp | 315 ++++++++++++++++----- dll/shellext/stobject/lang/cs-CZ.rc | 4 +- dll/shellext/stobject/lang/de-DE.rc | 4 +- dll/shellext/stobject/lang/en-US.rc | 4 +- dll/shellext/stobject/lang/es-ES.rc | 4 +- dll/shellext/stobject/lang/fr-FR.rc | 4 +- dll/shellext/stobject/lang/it-IT.rc | 4 +- dll/shellext/stobject/lang/pl-PL.rc | 4 +- dll/shellext/stobject/lang/ro-RO.rc | 4 +- dll/shellext/stobject/lang/ru-RU.rc | 4 +- dll/shellext/stobject/lang/zh-CN.rc | 4 +- dll/shellext/stobject/lang/zh-TW.rc | 4 +- dll/shellext/stobject/power.cpp | 301 ++++++++++++++++---- dll/shellext/stobject/precomp.h | 3 - dll/shellext/stobject/resource.h | 16 ++ dll/shellext/stobject/resources/battery/0.ico | Bin 0 -> 9062 bytes dll/shellext/stobject/resources/battery/1.ico | Bin 0 -> 9062 bytes dll/shellext/stobject/resources/battery/2.ico | Bin 0 -> 9062 bytes dll/shellext/stobject/resources/battery/3.ico | Bin 0 -> 9062 bytes dll/shellext/stobject/resources/battery/4.ico | Bin 0 -> 9062 bytes dll/shellext/stobject/resources/battery/5.ico | Bin 0 -> 9062 bytes .../stobject/resources/battery/charging0.ico | Bin 0 -> 2550 bytes .../stobject/resources/battery/charging1.ico | Bin 0 -> 2550 bytes .../stobject/resources/battery/charging2.ico | Bin 0 -> 2550 bytes .../stobject/resources/battery/charging3.ico | Bin 0 -> 2550 bytes .../stobject/resources/battery/charging4.ico | Bin 0 -> 2550 bytes dll/shellext/stobject/resources/battery/error.ico | Bin 0 -> 9062 bytes dll/shellext/stobject/resources/hotplug/0.ico | Bin 0 -> 2550 bytes dll/shellext/stobject/resources/hotplug/1.ico | Bin 0 -> 2550 bytes dll/shellext/stobject/stobject.rc | 19 ++ dll/shellext/stobject/volume.cpp | 29 +- 34 files changed, 592 insertions(+), 195 deletions(-) diff --git a/dll/shellext/stobject/CMakeLists.txt b/dll/shellext/stobject/CMakeLists.txt index 2fa34e6144..341fe672ae 100644 --- a/dll/shellext/stobject/CMakeLists.txt +++ b/dll/shellext/stobject/CMakeLists.txt @@ -12,6 +12,9 @@ include_directories( ${REACTOS_SOURCE_DIR}/sdk/lib/atl ${REACTOS_SOURCE_DIR}) +add_definitions( + -D_ATL_NO_EXCEPTIONS) + spec2def(stobject.dll stobject.spec) file(GLOB_RECURSE stobject_rc_deps resources/*.*) @@ -30,6 +33,7 @@ set_module_type(stobject win32dll UNICODE) target_link_libraries(stobject uuid wine atlnew) add_importlibs(stobject + setupapi advapi32 winmm ole32 diff --git a/dll/shellext/stobject/csystray.cpp b/dll/shellext/stobject/csystray.cpp index 8551fbcf23..e4a2afe403 100644 --- a/dll/shellext/stobject/csystray.cpp +++ b/dll/shellext/stobject/csystray.cpp @@ -4,6 +4,7 @@ * FILE: dll/shellext/stobject/csystray.cpp * PURPOSE: Systray shell service object implementation * PROGRAMMERS: David Quintana <gigah...@gmail.com> +* Shriraj Sawant a.k.a SR13 <sr.offic...@hotmail.com> */ #include "precomp.h" @@ -97,7 +98,27 @@ HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, LR return S_FALSE; } -HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip) +/*++ +* @name NotifyIcon +* +* Basically a Shell_NotifyIcon wrapper. +* Based on the parameters provided, it changes the current state of the notification icon. +* +* @param code +* Determines whether to add, delete or modify the notification icon (represented by uId). +* @param uId +* Represents the particular notification icon. +* @param hIcon +* A handle to an icon for the notification object. +* @param szTip +* A string for the tooltip of the notification. +* @param dwstate +* Determines whether to show or hide the notification icon. +* +* @return The error code. +* +*--*/ +HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip, DWORD dwstate) { NOTIFYICONDATA nim = { 0 }; @@ -108,8 +129,8 @@ HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip) nim.hIcon = hIcon; nim.uID = uId; nim.uCallbackMessage = uId; - nim.dwState = 0; - nim.dwStateMask = 0; + nim.dwState = dwstate; + nim.dwStateMask = NIS_HIDDEN; nim.hWnd = m_hWnd; nim.uVersion = NOTIFYICON_VERSION; if (szTip) @@ -219,30 +240,8 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM return TRUE; case WM_TIMER: - switch (wParam) - { - case 1: - UpdateIcons(); - return TRUE; - - case POWER_TIMER_ID: - Power_OnTimer(hWnd); - break; - - case VOLUME_TIMER_ID: - Volume_OnTimer(hWnd); - break; - - case HOTPLUG_TIMER_ID: - Hotplug_OnTimer(hWnd); - break; - } - break; - - case WM_DEVICECHANGE: - ERR("WM_DEVICECHANGE\n"); - break; - + UpdateIcons(); + return TRUE; case WM_DESTROY: KillTimer(1); ShutdownIcons(); diff --git a/dll/shellext/stobject/csystray.h b/dll/shellext/stobject/csystray.h index 04f7c1e292..b95cd65577 100644 --- a/dll/shellext/stobject/csystray.h +++ b/dll/shellext/stobject/csystray.h @@ -5,6 +5,7 @@ * PURPOSE: Systray shell service object * PROGRAMMERS: Robert Naumann * David Quintana <gigah...@gmail.com> + * Shriraj Sawant a.k.a SR13 <sr.offic...@hotmail.com> */ #pragma once @@ -43,7 +44,7 @@ class CSysTray : HRESULT ShutdownNetShell(); public: - HRESULT NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip); + HRESULT NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip, DWORD dwstate = 0); HWND GetHWnd() { return m_hWnd; } diff --git a/dll/shellext/stobject/hotplug.cpp b/dll/shellext/stobject/hotplug.cpp index fbc22ea078..4b17a1baf2 100644 --- a/dll/shellext/stobject/hotplug.cpp +++ b/dll/shellext/stobject/hotplug.cpp @@ -2,38 +2,152 @@ * PROJECT: ReactOS system libraries * LICENSE: GPL - See COPYING in the top level directory * FILE: dll/shellext/stobject/hotplug.cpp - * PURPOSE: Hotplug notification icon handler - * PROGRAMMERS: Eric Kohl <eric.k...@reactos.org> - * David Quintana <gigah...@gmail.com> + * PURPOSE: Removable devices notification icon handler + * PROGRAMMERS: Shriraj Sawant a.k.a SR13 <sr.offic...@hotmail.com> */ - +#include <windows.h> #include "precomp.h" +#include <mmsystem.h> +#include <mmddk.h> +#include <atlstr.h> +#include <atlsimpcoll.h> +#include <dbt.h> +#include <setupapi.h> +#include <cfgmgr32.h> WINE_DEFAULT_DEBUG_CHANNEL(stobject); +#define DISPLAY_NAME_LEN 40 + +//BOOL WINAPI UnregisterDeviceNotification(HDEVNOTIFY Handle); +CSimpleArray<DEVINST> g_devList; +/*static HDEVNOTIFY g_hDevNotify = NULL;*/ static HICON g_hIconHotplug = NULL; +static LPCWSTR g_strTooltip = L"Safely Remove Hardware and Eject Media"; +static WCHAR g_strMenuSel[DISPLAY_NAME_LEN]; static BOOL g_IsRunning = FALSE; - - -HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray) +static BOOL g_IsRemoving = FALSE; + +/*++ +* @name EnumHotpluggedDevices +* +* Enumerates the connected safely removable devices. +* +* @param devList +* List of device instances, representing the currently attached devices. +* +* @return The error code. +* +*--*/ +HRESULT EnumHotpluggedDevices(CSimpleArray<DEVINST> &devList) { - WCHAR strTooltip[128]; + devList.RemoveAll(); // Clear current devList + HDEVINFO hdev = SetupDiGetClassDevs(NULL, NULL, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT); + if (INVALID_HANDLE_VALUE == hdev) + return E_HANDLE; + SP_DEVINFO_DATA did = { 0 }; + did.cbSize = sizeof(did); + + // Enumerate all the attached devices. + for (int idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); idev++) + { + DWORD dwCapabilities = 0, dwSize = sizeof(dwCapabilities); + WCHAR dispName[DISPLAY_NAME_LEN]; + ULONG ulStatus = 0, ulPnum = 0, ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR); + CONFIGRET cr = CM_Get_DevNode_Status(&ulStatus, &ulPnum, did.DevInst, 0); + if (cr != CR_SUCCESS) + continue; + cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_DEVICEDESC, NULL, dispName, &ulLength, 0); + if (cr != CR_SUCCESS) + continue; + cr = CM_Get_DevNode_Registry_Property(did.DevInst, CM_DRP_CAPABILITIES, NULL, &dwCapabilities, &dwSize, 0); + if (cr != CR_SUCCESS) + continue; + + // Filter and make list of only the appropriate safely removable devices. + if ( (dwCapabilities & CM_DEVCAP_REMOVABLE) && + !(dwCapabilities & CM_DEVCAP_DOCKDEVICE) && + !(dwCapabilities & CM_DEVCAP_SURPRISEREMOVALOK) && + ((dwCapabilities & CM_DEVCAP_EJECTSUPPORTED) || (ulStatus & DN_DISABLEABLE)) && + !ulPnum) + { + devList.Add(did.DevInst); + } + } + SetupDiDestroyDeviceInfoList(hdev); - TRACE("Hotplug_Init\n"); + if (NO_ERROR != GetLastError() && ERROR_NO_MORE_ITEMS != GetLastError()) + { + return E_UNEXPECTED; + } - g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_EXTRACT)); + return S_OK; +} - LoadStringW(g_hInstance, IDS_HOTPLUG_REMOVE_1, strTooltip, _countof(strTooltip)); +/*++ +* @name NotifyBalloon +* +* Pops the balloon notification of the given notification icon. +* +* @param pSysTray +* Provides interface for acquiring CSysTray information as required. +* @param szTitle +* Title for the balloon notification. +* @param szInfo +* Main content for the balloon notification. +* @param uId +* Represents the particular notification icon. +* +* @return The error code. +* +*--*/ +HRESULT NotifyBalloon(CSysTray* pSysTray, LPCWSTR szTitle = NULL, LPCWSTR szInfo = NULL, UINT uId = ID_ICON_HOTPLUG) +{ + NOTIFYICONDATA nim = { 0 }; + nim.cbSize = sizeof(NOTIFYICONDATA); + nim.uID = uId; + nim.hWnd = pSysTray->GetHWnd(); + + nim.uFlags = NIF_INFO; + nim.uTimeout = 10; + nim.dwInfoFlags = NIIF_INFO; + + StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), szTitle); + StringCchCopy(nim.szInfo, _countof(nim.szInfo), szInfo); + BOOL ret = Shell_NotifyIcon(NIM_MODIFY, &nim); + + Sleep(10000); /* As per windows, the balloon notification remains visible for atleast 10 sec. + This timer maintains the same condition. + Also it is required so that the icon doesn't hide instantly after last device is removed, + as that will prevent popping of notification. + */ + StringCchCopy(nim.szInfoTitle, _countof(nim.szInfoTitle), L""); + StringCchCopy(nim.szInfo, _countof(nim.szInfo), L""); + ret = Shell_NotifyIcon(NIM_MODIFY, &nim); + g_IsRemoving = FALSE; /* This flag is used to prevent instant icon hiding after last device is removed. + The above timer maintains the required state for the same. + */ + return ret ? S_OK : E_FAIL; +} +HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray) +{ + TRACE("Hotplug_Init\n"); + g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_HOTPLUG_OK)); g_IsRunning = TRUE; + EnumHotpluggedDevices(g_devList); - return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_HOTPLUG, g_hIconHotplug, strTooltip); + return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip, NIS_HIDDEN); } HRESULT STDMETHODCALLTYPE Hotplug_Update(_In_ CSysTray * pSysTray) { TRACE("Hotplug_Update\n"); - return S_OK; + + if(g_devList.GetSize() || g_IsRemoving) + return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip); + else + return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_HOTPLUG, g_hIconHotplug, g_strTooltip, NIS_HIDDEN); } HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray) @@ -45,79 +159,112 @@ HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray) return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_HOTPLUG, NULL, NULL); } -static void RunHotplug() +static void _RunHotplug(CSysTray * pSysTray) { - ShellExecuteW(NULL, NULL, L"rundll32.exe", L"shell32.dll,Control_RunDLL hotplug.dll", NULL, SW_SHOWNORMAL); + ShellExecuteW(pSysTray->GetHWnd(), L"open", L"rundll32.exe shell32.dll,Control_RunDLL hotplug.dll", NULL, NULL, SW_SHOWNORMAL); } -static void ShowContextMenu(CSysTray *pSysTray) +static void _ShowContextMenu(CSysTray * pSysTray) { - WCHAR szBuffer[128]; - DWORD id, msgPos; - HMENU hPopup; - - LoadStringW(g_hInstance, IDS_HOTPLUG_REMOVE_2, szBuffer, _countof(szBuffer)); + HMENU hPopup = CreatePopupMenu(); + ULONG ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR); - hPopup = CreatePopupMenu(); - AppendMenuW(hPopup, MF_STRING, 1, szBuffer); + for (INT index = 0; index < g_devList.GetSize(); index++) + { + WCHAR dispName[DISPLAY_NAME_LEN], menuName[DISPLAY_NAME_LEN + 10]; + CONFIGRET cr = CM_Get_DevNode_Registry_Property(g_devList[index], CM_DRP_DEVICEDESC, NULL, dispName, &ulLength, 0); + if (cr != CR_SUCCESS) + StrCpyW(dispName, L"Unknown Device"); - msgPos = GetMessagePos(); + swprintf(menuName, L"Eject %wS", dispName); + AppendMenuW(hPopup, MF_STRING, index+1, menuName); + } SetForegroundWindow(pSysTray->GetHWnd()); - id = TrackPopupMenuEx(hPopup, - TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN, - GET_X_LPARAM(msgPos), - GET_Y_LPARAM(msgPos), - pSysTray->GetHWnd(), - NULL); + DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN; + POINT pt; + GetCursorPos(&pt); - DestroyMenu(hPopup); + DWORD id = TrackPopupMenuEx(hPopup, flags, + pt.x, pt.y, + pSysTray->GetHWnd(), NULL); + + if (id > 0) + { + id--; // since array indices starts from zero. + CONFIGRET cr = CM_Get_DevNode_Registry_Property(g_devList[id], CM_DRP_DEVICEDESC, NULL, g_strMenuSel, &ulLength, 0); + if (cr != CR_SUCCESS) + StrCpyW(g_strMenuSel, L"Unknown Device"); + + cr = CM_Request_Device_Eject_Ex(g_devList[id], 0, 0, 0, 0, 0); + if (cr != CR_SUCCESS) + { + WCHAR strInfo[128]; + swprintf(strInfo, L"Problem Ejecting %wS", g_strMenuSel); + MessageBox(0, L"The device cannot be stopped right now! Try stopping it again later!", strInfo, MB_OKCANCEL | MB_ICONEXCLAMATION); + } + else + { + //MessageBox(0, L"Device ejected successfully!! You can safely remove the device now!", L"Safely Remove Hardware", MB_OKCANCEL | MB_ICONINFORMATION); + g_IsRemoving = TRUE; + g_devList.RemoveAt(id); /* thing is.. even after removing id at this point, the devnode_change occurs after some seconds of sucessful removal + and since pendrive is still plugged in it gets enumerated, if problem number is not filtered. + */ + } + } - if (id == 1) - RunHotplug(); + DestroyMenu(hPopup); } -static -VOID -ShowHotplugPopupMenu( - HWND hWnd) +static void _ShowContextMenuR(CSysTray * pSysTray) { -#if 0 - DWORD id, msgPos; - + CString strMenu((LPWSTR)IDS_HOTPLUG_REMOVE_2); HMENU hPopup = CreatePopupMenu(); + AppendMenuW(hPopup, MF_STRING, IDS_HOTPLUG_REMOVE_2, strMenu); - // FIXME - AppendMenuW(hPopup, MF_STRING, IDS_VOL_OPEN, strOpen); - - msgPos = GetMessagePos(); - - SetForegroundWindow(hWnd); - id = TrackPopupMenuEx(hPopup, - TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN, - GET_X_LPARAM(msgPos), - GET_Y_LPARAM(msgPos), - hWnd, - NULL); + SetForegroundWindow(pSysTray->GetHWnd()); + DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN; + POINT pt; + GetCursorPos(&pt); - DestroyMenu(hPopup); + DWORD id = TrackPopupMenuEx(hPopup, flags, + pt.x, pt.y, + pSysTray->GetHWnd(), NULL); - if (id != 0) + if (id == IDS_HOTPLUG_REMOVE_2) { - // FIXME + _RunHotplug(pSysTray); } -#endif + + DestroyMenu(hPopup); } -HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult) +HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult) { + HRESULT hr = E_FAIL; TRACE("Hotplug_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg, wParam, lParam); switch (uMsg) { + /*case WM_CREATE: + TRACE("Hotplug_Message: WM_CREATE\n"); + DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; + + ZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); + NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + + g_hDevNotify = RegisterDeviceNotification(pSysTray->GetHWnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); + if (g_hDevNotify != NULL) + { + lResult = true; + return S_OK; + } + return S_FALSE;*/ + case WM_USER + 220: TRACE("Hotplug_Message: WM_USER+220\n"); - if (wParam == 2) + if (wParam == 1) { if (lParam == FALSE) return Hotplug_Init(pSysTray); @@ -128,7 +275,7 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WP case WM_USER + 221: TRACE("Hotplug_Message: WM_USER+221\n"); - if (wParam == 2) + if (wParam == 1) { lResult = (LRESULT)g_IsRunning; return S_OK; @@ -141,22 +288,21 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WP switch (lParam) { case WM_LBUTTONDOWN: - SetTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID, 500, NULL); break; case WM_LBUTTONUP: + _ShowContextMenu(pSysTray); break; case WM_LBUTTONDBLCLK: - KillTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID); - RunHotplug(); + _RunHotplug(pSysTray); break; case WM_RBUTTONDOWN: break; case WM_RBUTTONUP: - ShowContextMenu(pSysTray); + _ShowContextMenuR(pSysTray); break; case WM_RBUTTONDBLCLK: @@ -167,6 +313,41 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WP } return S_OK; + case WM_DEVICECHANGE: + switch (wParam) + { + case DBT_DEVNODES_CHANGED: + hr = EnumHotpluggedDevices(g_devList); + if (FAILED(hr)) + return hr; + + lResult = true; + break; + case DBT_DEVICEARRIVAL: + break; + case DBT_DEVICEQUERYREMOVE: + break; + case DBT_DEVICEQUERYREMOVEFAILED: + break; + case DBT_DEVICEREMOVECOMPLETE: + WCHAR strInfo[128]; + swprintf(strInfo, L"The %wS can now be safely removed from the system.", g_strMenuSel); + NotifyBalloon(pSysTray, L"Safe to Remove Hardware", strInfo); + + lResult = true; + break; + case DBT_DEVICEREMOVEPENDING: + break; + } + return S_OK; + + /*case WM_CLOSE: + if (!UnregisterDeviceNotification(hDeviceNotify)) + { + return S_FALSE; + } + return S_OK;*/ + default: TRACE("Hotplug_Message received for unknown ID %d, ignoring.\n"); return S_FALSE; @@ -174,11 +355,3 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WP return S_FALSE; } - -VOID -Hotplug_OnTimer(HWND hWnd) -{ - TRACE("Hotplug_OnTimer\n!"); - KillTimer(hWnd, HOTPLUG_TIMER_ID); - ShowHotplugPopupMenu(hWnd); -} diff --git a/dll/shellext/stobject/lang/cs-CZ.rc b/dll/shellext/stobject/lang/cs-CZ.rc index 84fe3d4fb1..57ec1bca55 100644 --- a/dll/shellext/stobject/lang/cs-CZ.rc +++ b/dll/shellext/stobject/lang/cs-CZ.rc @@ -18,8 +18,8 @@ BEGIN IDS_PWR_PROPERTIES "&Upravit možnosti napájení" IDS_PWR_METER "&Otevřít ukazatel spotřeby" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "zbývá %1!u!%%" - IDS_PWR_CHARGING " (nabíjení)" + IDS_PWR_PERCENT_REMAINING "zbývá %.2f%%" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Zbývá neznámo" IDS_PWR_AC "On AC power" IDS_PWR_HOURS_REMAINING "zbývá %1!u!:%2!02u! hodin (%3!u!%%)" diff --git a/dll/shellext/stobject/lang/de-DE.rc b/dll/shellext/stobject/lang/de-DE.rc index 1563baf172..cdb3aa2d48 100644 --- a/dll/shellext/stobject/lang/de-DE.rc +++ b/dll/shellext/stobject/lang/de-DE.rc @@ -18,8 +18,8 @@ BEGIN IDS_PWR_PROPERTIES "&Energieverwaltungseigenschaften einstellen" IDS_PWR_METER "Batterieanzeige ö&ffnen" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "%1!u!%% verbleibend" - IDS_PWR_CHARGING " (wird aufgeladen)" + IDS_PWR_PERCENT_REMAINING "%.2f%% verbleibend" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Unbekannt verbleibend" IDS_PWR_AC "Mit Wechselstrom" IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! Stunden (%3!u!%%) verbleibend" diff --git a/dll/shellext/stobject/lang/en-US.rc b/dll/shellext/stobject/lang/en-US.rc index e10c25c3cc..ea1f17ffcd 100644 --- a/dll/shellext/stobject/lang/en-US.rc +++ b/dll/shellext/stobject/lang/en-US.rc @@ -18,8 +18,8 @@ BEGIN IDS_PWR_PROPERTIES "&Adjust Power Properties" IDS_PWR_METER "&Open Power Meter" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "%1!u!%% remaining" - IDS_PWR_CHARGING " (charging)" + IDS_PWR_PERCENT_REMAINING "%.2f%% remaining" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Unknown remaining" IDS_PWR_AC "On AC power" IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! hours (%3!u!%%) remaining" diff --git a/dll/shellext/stobject/lang/es-ES.rc b/dll/shellext/stobject/lang/es-ES.rc index c7a3d0d6b2..ac008f2dd9 100644 --- a/dll/shellext/stobject/lang/es-ES.rc +++ b/dll/shellext/stobject/lang/es-ES.rc @@ -19,8 +19,8 @@ BEGIN IDS_PWR_PROPERTIES "&Ajustar propiedades de energía" IDS_PWR_METER "Abrir &medidor de energía" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "Queda un %1!u!%%" - IDS_PWR_CHARGING " (cargando)" + IDS_PWR_PERCENT_REMAINING "Queda un %.2f%%" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Estado de batería desconocido" IDS_PWR_AC "En corriente alterna" IDS_PWR_HOURS_REMAINING "Quedan %1!u!:%2!02u! horas (%3!u!%%)" diff --git a/dll/shellext/stobject/lang/fr-FR.rc b/dll/shellext/stobject/lang/fr-FR.rc index 273cb83b89..de393af36f 100644 --- a/dll/shellext/stobject/lang/fr-FR.rc +++ b/dll/shellext/stobject/lang/fr-FR.rc @@ -18,8 +18,8 @@ BEGIN IDS_PWR_PROPERTIES "&Adjust Power Properties" IDS_PWR_METER "&Open Power Meter" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "%1!u!%% remaining" - IDS_PWR_CHARGING " (charging)" + IDS_PWR_PERCENT_REMAINING "%.2f%% remaining" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Unknown remaining" IDS_PWR_AC "On AC power" IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! hours (%3!u!%%) remaining" diff --git a/dll/shellext/stobject/lang/it-IT.rc b/dll/shellext/stobject/lang/it-IT.rc index a4d715427c..628466edbe 100644 --- a/dll/shellext/stobject/lang/it-IT.rc +++ b/dll/shellext/stobject/lang/it-IT.rc @@ -18,8 +18,8 @@ BEGIN IDS_PWR_PROPERTIES "&Modifica proprietà alimentazione" IDS_PWR_METER "&Apri misuratore alimentazione" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "%1!u!%% rimanenti" - IDS_PWR_CHARGING " (in carica)" + IDS_PWR_PERCENT_REMAINING "%.2f%% rimanenti" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Autonomia sconosciuta" IDS_PWR_AC "Alimentazione da rete AC" IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! ore (%3!u!%%) rimanenti" diff --git a/dll/shellext/stobject/lang/pl-PL.rc b/dll/shellext/stobject/lang/pl-PL.rc index 0a2889edc4..def3249946 100644 --- a/dll/shellext/stobject/lang/pl-PL.rc +++ b/dll/shellext/stobject/lang/pl-PL.rc @@ -18,8 +18,8 @@ BEGIN IDS_PWR_PROPERTIES "&Opcje zasilania" IDS_PWR_METER "&Otwórz miernik baterii" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "Pozostało %1!u!%%" - IDS_PWR_CHARGING " (ładowanie)" + IDS_PWR_PERCENT_REMAINING "Pozostało %.2f%%" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Stan naładowania nieznany" IDS_PWR_AC "Podłączony do zasilacza" IDS_PWR_HOURS_REMAINING "Pozostało %1!u!:%2!02u! godzin (%3!u!%%)" diff --git a/dll/shellext/stobject/lang/ro-RO.rc b/dll/shellext/stobject/lang/ro-RO.rc index 0de2e8de7c..bb19bd1d74 100644 --- a/dll/shellext/stobject/lang/ro-RO.rc +++ b/dll/shellext/stobject/lang/ro-RO.rc @@ -19,8 +19,8 @@ BEGIN IDS_PWR_PROPERTIES "&Ajustare proprietăți de consum energie" IDS_PWR_METER "&Deschide Contor de energie" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "Au mai rămas %1!u!%%" - IDS_PWR_CHARGING " (în încărcare)" + IDS_PWR_PERCENT_REMAINING "Au mai rămas %.2f%%" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Nu este disponibil cât a mai rămas" IDS_PWR_AC "În rețea de CA" IDS_PWR_HOURS_REMAINING "Au mai rămas %1!u!:%2!02u! ore (%3!u!%%)" diff --git a/dll/shellext/stobject/lang/ru-RU.rc b/dll/shellext/stobject/lang/ru-RU.rc index 572f1613fd..af307d3024 100644 --- a/dll/shellext/stobject/lang/ru-RU.rc +++ b/dll/shellext/stobject/lang/ru-RU.rc @@ -20,8 +20,8 @@ BEGIN IDS_PWR_PROPERTIES "&Настройка параметров электропитания" IDS_PWR_METER "&Открыть показатели питания" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "%1!u!%% осталось" - IDS_PWR_CHARGING " (зарядка)" + IDS_PWR_PERCENT_REMAINING "%.2f%% осталось" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "Неизвестно" IDS_PWR_AC "От сети переменного тока" IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! часов (%3!u!%%) осталось" diff --git a/dll/shellext/stobject/lang/zh-CN.rc b/dll/shellext/stobject/lang/zh-CN.rc index 6ba1f37f4b..1d402493d0 100644 --- a/dll/shellext/stobject/lang/zh-CN.rc +++ b/dll/shellext/stobject/lang/zh-CN.rc @@ -20,8 +20,8 @@ BEGIN IDS_PWR_PROPERTIES "调整电源属性(&A)" IDS_PWR_METER "开放式电源表(&O)" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "剩余 %1!u!%%" - IDS_PWR_CHARGING " (充电中)" + IDS_PWR_PERCENT_REMAINING "剩余 %.2f%%" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "未知剩余" IDS_PWR_AC "交流电源" IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! 小时 剩余 (%3!u!%%) " diff --git a/dll/shellext/stobject/lang/zh-TW.rc b/dll/shellext/stobject/lang/zh-TW.rc index 35ae8c4a6f..3d9a5265b8 100644 --- a/dll/shellext/stobject/lang/zh-TW.rc +++ b/dll/shellext/stobject/lang/zh-TW.rc @@ -20,8 +20,8 @@ BEGIN IDS_PWR_PROPERTIES "調整電源屬性(&A)" IDS_PWR_METER "開放式電源表(&O)" IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl" - IDS_PWR_PERCENT_REMAINING "剩餘 %1!u!%%" - IDS_PWR_CHARGING " (充電中)" + IDS_PWR_PERCENT_REMAINING "剩餘 %.2f%%" + IDS_PWR_CHARGING "%.2f%% and charging" IDS_PWR_UNKNOWN_REMAINING "未知剩餘" IDS_PWR_AC "交流電源" IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! 小時 剩餘 (%3!u!%%) " diff --git a/dll/shellext/stobject/power.cpp b/dll/shellext/stobject/power.cpp index 24b5feb416..5853b2bdbf 100644 --- a/dll/shellext/stobject/power.cpp +++ b/dll/shellext/stobject/power.cpp @@ -4,14 +4,30 @@ * FILE: dll/shellext/stobject/power.cpp * PURPOSE: Power notification icon handler * PROGRAMMERS: Eric Kohl <eric.k...@reactos.org> + Shriraj Sawant a.k.a SR13 <sr.offic...@hotmail.com> * David Quintana <gigah...@gmail.com> */ +#include <Windows.h> +#include <SetupAPI.h> +#include <devguid.h> +#include <BatClass.h> + #include "precomp.h" #include "powrprof.h" +#include <mmsystem.h> +#include <mmddk.h> +#include <atlstr.h> + +#define GBS_HASBATTERY 0x1 +#define GBS_ONBATTERY 0x2 + WINE_DEFAULT_DEBUG_CHANNEL(stobject); +int br_icons[5] = { IDI_BATTCAP0, IDI_BATTCAP1, IDI_BATTCAP2, IDI_BATTCAP3, IDI_BATTCAP4 }; // battery mode icons. +int bc_icons[5] = { IDI_BATTCHA0, IDI_BATTCHA1, IDI_BATTCHA2, IDI_BATTCHA3, IDI_BATTCHA4 }; // charging mode icons. + typedef struct _PWRSCHEMECONTEXT { HMENU hPopup; @@ -19,71 +35,261 @@ typedef struct _PWRSCHEMECONTEXT UINT uiLast; } PWRSCHEMECONTEXT, *PPWRSCHEMECONTEXT; +CString g_strTooltip; +static float g_batCap = 0; static HICON g_hIconBattery = NULL; static BOOL g_IsRunning = FALSE; +/*++ +* @name GetBatteryState +* +* Enumerates the available battery devices and provides the remaining capacity. +* +* @param cap +* If no error occurs, then this will contain average remaining capacity. +* @param dwResult +* Helps in making battery type checks. +* { +* Returned value includes GBS_HASBATTERY if the system has a non-UPS battery, +* and GBS_ONBATTERY if the system is running on a battery. +* dwResult & GBS_ONBATTERY means we have not yet found AC power. +* dwResult & GBS_HASBATTERY means we have found a non-UPS battery. +* } +* +* @return The error code. +* +*--*/ +static HRESULT GetBatteryState(float& cap, DWORD& dwResult) +{ + cap = 0; + dwResult = GBS_ONBATTERY; -HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray) + HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (INVALID_HANDLE_VALUE == hdev) + return E_HANDLE; + + // Limit search to 100 batteries max + for (int idev = 0, count = 0; idev < 100; idev++) + { + SP_DEVICE_INTERFACE_DATA did = { 0 }; + did.cbSize = sizeof(did); + + if (SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVCLASS_BATTERY, idev, &did)) + { + DWORD cbRequired = 0; + + SetupDiGetDeviceInterfaceDetail(hdev, &did, 0, 0, &cbRequired, 0); + if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) + { + PSP_DEVICE_INTERFACE_DETAIL_DATA pdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, cbRequired); + if (pdidd) + { + pdidd->cbSize = sizeof(*pdidd); + if (SetupDiGetDeviceInterfaceDetail(hdev, &did, pdidd, cbRequired, &cbRequired, 0)) + { + // Enumerated a battery. Ask it for information. + HANDLE hBattery = CreateFile(pdidd->DevicePath, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (INVALID_HANDLE_VALUE != hBattery) + { + // Ask the battery for its tag. + BATTERY_QUERY_INFORMATION bqi = { 0 }; + + DWORD dwWait = 0; + DWORD dwOut; + + if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, + sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag) + { + // With the tag, you can query the battery info. + BATTERY_INFORMATION bi = { 0 }; + bqi.InformationLevel = BatteryInformation; + + if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, + sizeof(bi), &dwOut, NULL)) + { + // Only non-UPS system batteries count + if (bi.Capabilities & BATTERY_SYSTEM_BATTERY) + { + if (!(bi.Capabilities & BATTERY_IS_SHORT_TERM)) + dwResult |= GBS_HASBATTERY; + + // Query the battery status. + BATTERY_WAIT_STATUS bws = { 0 }; + bws.BatteryTag = bqi.BatteryTag; + + BATTERY_STATUS bs; + if (DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), + &bs, sizeof(bs), &dwOut, NULL)) + { + if (bs.PowerState & BATTERY_POWER_ON_LINE) + dwResult &= ~GBS_ONBATTERY; + + // Take average of total capacity of batteries detected! + cap = cap*(count)+(float)bs.Capacity / bi.FullChargedCapacity * 100; + cap /= count + 1; + count++; + } + } + } + } + CloseHandle(hBattery); + } + } + LocalFree(pdidd); + } + } + } + else if (ERROR_NO_MORE_ITEMS == GetLastError()) + { + break; // Enumeration failed - perhaps we're out of items + } + } + SetupDiDestroyDeviceInfoList(hdev); + + // Final cleanup: If we didn't find a battery, then presume that we + // are on AC power. + + if (!(dwResult & GBS_HASBATTERY)) + dwResult &= ~GBS_ONBATTERY; + + return S_OK; +} + +/*++ +* @name Quantize +* +* This function quantizes the mentioned quantity to nearest level. +* +* @param p +* Should be a quantity in percentage. +* @param lvl +* Quantization level (this excludes base level 0, which will always be present), default is 10. +* +* @return Nearest quantized level, can be directly used as array index based on context. +* +*--*/ +static UINT Quantize(float p, UINT lvl = 10) { - WCHAR strTooltip[128]; + int i = 0; + float f, q = (float)100 / lvl, d = q / 2; + for (f = 0; f < p; f += q, i++); + + if ((f - d) <= p) + return i; + else + return i - 1; +/* + @remarks This function uses centred/symmetric logic for quantization. + For the case of lvl = 4, You will get following integer levels if given (p) value falls in between the range partitions: + 0 <= p < 12.5 : returns 0; (corresponding to 0% centre) + 12.5 <= p < 37.5 : returns 1; (corresponding to 25% centre) + 37.5 <= p < 62.5 : returns 2; (corresponding to 50% centre) + 62.5 <= p < 87.5 : returns 3; (corresponding to 75% centre) + 87.5 <= p <= 100 : returns 4; (corresponding to 100% centre) +*/ +} - TRACE("Power_Init\n"); +/*++ +* @name DynamicLoadIcon +* +* Returns the respective icon as per the current battery capacity. +* It also does the work of setting global parameters of battery capacity and tooltips. +* +* @param hinst +* A handle to a instance of the module. +* +* @return The handle to respective battery icon. +* +*--*/ +static HICON DynamicLoadIcon(HINSTANCE hinst) +{ + HICON hBatIcon; + float cap = 0; + DWORD dw = 0; + UINT index = -1; + HRESULT hr = GetBatteryState(cap, dw); + + if (!FAILED(hr) && (dw & GBS_HASBATTERY)) + { + index = Quantize(cap, 4); + g_batCap = cap; + } + else + { + g_batCap = 0; + hBatIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_BATTCAP_ERR)); + g_strTooltip.LoadStringW(IDS_PWR_UNKNOWN_REMAINING); + return hBatIcon; + } - g_hIconBattery = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BATTERY)); + if (dw & GBS_ONBATTERY) + { + hBatIcon = LoadIcon(hinst, MAKEINTRESOURCE(br_icons[index])); + g_strTooltip.Format(IDS_PWR_PERCENT_REMAINING, cap); + } + else + { + hBatIcon = LoadIcon(hinst, MAKEINTRESOURCE(bc_icons[index])); + g_strTooltip.Format(IDS_PWR_CHARGING, cap); + } - LoadStringW(g_hInstance, IDS_PWR_AC, strTooltip, _countof(strTooltip)); + return hBatIcon; +} +HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray) +{ + TRACE("Power_Init\n"); + g_hIconBattery = DynamicLoadIcon(g_hInstance); g_IsRunning = TRUE; - return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_POWER, g_hIconBattery, strTooltip); + return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_POWER, g_hIconBattery, g_strTooltip); } HRESULT STDMETHODCALLTYPE Power_Update(_In_ CSysTray * pSysTray) { TRACE("Power_Update\n"); - return S_OK; + g_hIconBattery = DynamicLoadIcon(g_hInstance); + + return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_POWER, g_hIconBattery, g_strTooltip); } HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray) { TRACE("Power_Shutdown\n"); - g_IsRunning = FALSE; return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_POWER, NULL, NULL); } -static void RunPower() +static void _RunPower() { - ShellExecuteW(NULL, NULL, L"rundll32.exe", L"shell32.dll,Control_RunDLL powercfg.cpl", NULL, SW_SHOWNORMAL); + ShellExecuteW(NULL, NULL, L"powercfg.cpl", NULL, NULL, SW_SHOWNORMAL); } -static void ShowContextMenu(CSysTray * pSysTray) +static void _ShowContextMenu(CSysTray * pSysTray) { - WCHAR szBuffer[128]; - DWORD id, msgPos; - HMENU hPopup; - - LoadStringW(g_hInstance, IDS_PWR_PROPERTIES, szBuffer, _countof(szBuffer)); - - hPopup = CreatePopupMenu(); - AppendMenuW(hPopup, MF_STRING, IDS_PWR_PROPERTIES, szBuffer); - SetMenuDefaultItem(hPopup, IDS_PWR_PROPERTIES, FALSE); - - msgPos = GetMessagePos(); + CString strOpen((LPCSTR)IDS_PWR_PROPERTIES); + HMENU hPopup = CreatePopupMenu(); + AppendMenuW(hPopup, MF_STRING, IDS_PWR_PROPERTIES, strOpen); SetForegroundWindow(pSysTray->GetHWnd()); - id = TrackPopupMenuEx(hPopup, - TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN, - GET_X_LPARAM(msgPos), - GET_Y_LPARAM(msgPos), - pSysTray->GetHWnd(), - NULL); + DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN; + POINT pt; + GetCursorPos(&pt); - DestroyMenu(hPopup); + DWORD id = TrackPopupMenuEx(hPopup, flags, + pt.x, pt.y, + pSysTray->GetHWnd(), NULL); - if (id == IDS_PWR_PROPERTIES) - RunPower(); + switch (id) + { + case IDS_PWR_PROPERTIES: + _RunPower(); + break; + } + DestroyMenu(hPopup); } static @@ -114,12 +320,12 @@ PowerSchemesEnumProc( static VOID ShowPowerSchemesPopupMenu( - HWND hWnd) + CSysTray *pSysTray) { PWRSCHEMECONTEXT PowerSchemeContext = {NULL, 0, 0}; UINT uiActiveScheme; - DWORD id, msgPos; - + DWORD id; + POINT pt; PowerSchemeContext.hPopup = CreatePopupMenu(); EnumPwrSchemes(PowerSchemesEnumProc, (LPARAM)&PowerSchemeContext); @@ -132,14 +338,14 @@ ShowPowerSchemesPopupMenu( MF_BYCOMMAND); } - msgPos = GetMessagePos(); - - SetForegroundWindow(hWnd); + SetForegroundWindow(pSysTray->GetHWnd()); + GetCursorPos(&pt); + id = TrackPopupMenuEx(PowerSchemeContext.hPopup, TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN, - GET_X_LPARAM(msgPos), - GET_Y_LPARAM(msgPos), - hWnd, + pt.x, + pt.y, + pSysTray->GetHWnd(), NULL); DestroyMenu(PowerSchemeContext.hPopup); @@ -180,22 +386,21 @@ HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPA switch (lParam) { case WM_LBUTTONDOWN: - SetTimer(pSysTray->GetHWnd(), POWER_TIMER_ID, 500, NULL); break; case WM_LBUTTONUP: + ShowPowerSchemesPopupMenu(pSysTray); break; case WM_LBUTTONDBLCLK: - KillTimer(pSysTray->GetHWnd(), POWER_TIMER_ID); - RunPower(); + _RunPower(); break; case WM_RBUTTONDOWN: break; case WM_RBUTTONUP: - ShowContextMenu(pSysTray); + _ShowContextMenu(pSysTray); break; case WM_RBUTTONDBLCLK: @@ -213,11 +418,3 @@ HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPA return S_FALSE; } - -VOID -Power_OnTimer(HWND hWnd) -{ - TRACE("Power_OnTimer\n!"); - KillTimer(hWnd, POWER_TIMER_ID); - ShowPowerSchemesPopupMenu(hWnd); -} diff --git a/dll/shellext/stobject/precomp.h b/dll/shellext/stobject/precomp.h index fd2ea78836..64824ba825 100644 --- a/dll/shellext/stobject/precomp.h +++ b/dll/shellext/stobject/precomp.h @@ -69,19 +69,16 @@ extern HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Volume_Shutdown(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult); -extern VOID Volume_OnTimer(HWND hWnd); extern HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Hotplug_Update(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult); -extern VOID Hotplug_OnTimer(HWND hWnd); extern HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Power_Update(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult); -extern VOID Power_OnTimer(HWND hWnd); #define POWER_TIMER_ID 2 #define VOLUME_TIMER_ID 3 diff --git a/dll/shellext/stobject/resource.h b/dll/shellext/stobject/resource.h index 2637a12aea..a7466f77d3 100644 --- a/dll/shellext/stobject/resource.h +++ b/dll/shellext/stobject/resource.h @@ -39,4 +39,20 @@ #define IDS_KEYS_MOUSE 331 #define IDS_KEYS_FILTER 332 +#define IDI_BATTCAP0 400 +#define IDI_BATTCAP1 401 +#define IDI_BATTCAP2 402 +#define IDI_BATTCAP3 403 +#define IDI_BATTCAP4 404 +#define IDI_BATTCAP5 405 +#define IDI_BATTCHA0 406 +#define IDI_BATTCHA1 407 +#define IDI_BATTCHA2 408 +#define IDI_BATTCHA3 409 +#define IDI_BATTCHA4 410 +#define IDI_BATTCAP_ERR 412 + +#define IDI_HOTPLUG_ERR 420 +#define IDI_HOTPLUG_OK 421 + #define IDR_SYSTRAY 11001 diff --git a/dll/shellext/stobject/resources/battery/0.ico b/dll/shellext/stobject/resources/battery/0.ico new file mode 100644 index 0000000000..1610499aa3 Binary files /dev/null and b/dll/shellext/stobject/resources/battery/0.ico differ diff --git a/dll/shellext/stobject/resources/battery/1.ico b/dll/shellext/stobject/resources/battery/1.ico new file mode 100644 index 0000000000..9c2f526f9e Binary files /dev/null and b/dll/shellext/stobject/resources/battery/1.ico differ diff --git a/dll/shellext/stobject/resources/battery/2.ico b/dll/shellext/stobject/resources/battery/2.ico new file mode 100644 index 0000000000..f1dc98aa7f Binary files /dev/null and b/dll/shellext/stobject/resources/battery/2.ico differ diff --git a/dll/shellext/stobject/resources/battery/3.ico b/dll/shellext/stobject/resources/battery/3.ico new file mode 100644 index 0000000000..59fabc2ef3 Binary files /dev/null and b/dll/shellext/stobject/resources/battery/3.ico differ diff --git a/dll/shellext/stobject/resources/battery/4.ico b/dll/shellext/stobject/resources/battery/4.ico new file mode 100644 index 0000000000..edc24a071e Binary files /dev/null and b/dll/shellext/stobject/resources/battery/4.ico differ diff --git a/dll/shellext/stobject/resources/battery/5.ico b/dll/shellext/stobject/resources/battery/5.ico new file mode 100644 index 0000000000..cd4e3b8ee7 Binary files /dev/null and b/dll/shellext/stobject/resources/battery/5.ico differ diff --git a/dll/shellext/stobject/resources/battery/charging0.ico b/dll/shellext/stobject/resources/battery/charging0.ico new file mode 100644 index 0000000000..7504162423 Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging0.ico differ diff --git a/dll/shellext/stobject/resources/battery/charging1.ico b/dll/shellext/stobject/resources/battery/charging1.ico new file mode 100644 index 0000000000..3a6210c19a Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging1.ico differ diff --git a/dll/shellext/stobject/resources/battery/charging2.ico b/dll/shellext/stobject/resources/battery/charging2.ico new file mode 100644 index 0000000000..7c1c919a35 Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging2.ico differ diff --git a/dll/shellext/stobject/resources/battery/charging3.ico b/dll/shellext/stobject/resources/battery/charging3.ico new file mode 100644 index 0000000000..fb92ab6213 Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging3.ico differ diff --git a/dll/shellext/stobject/resources/battery/charging4.ico b/dll/shellext/stobject/resources/battery/charging4.ico new file mode 100644 index 0000000000..bd1f495c9a Binary files /dev/null and b/dll/shellext/stobject/resources/battery/charging4.ico differ diff --git a/dll/shellext/stobject/resources/battery/error.ico b/dll/shellext/stobject/resources/battery/error.ico new file mode 100644 index 0000000000..6afba7759d Binary files /dev/null and b/dll/shellext/stobject/resources/battery/error.ico differ diff --git a/dll/shellext/stobject/resources/hotplug/0.ico b/dll/shellext/stobject/resources/hotplug/0.ico new file mode 100644 index 0000000000..83025a942d Binary files /dev/null and b/dll/shellext/stobject/resources/hotplug/0.ico differ diff --git a/dll/shellext/stobject/resources/hotplug/1.ico b/dll/shellext/stobject/resources/hotplug/1.ico new file mode 100644 index 0000000000..f615f0ebd3 Binary files /dev/null and b/dll/shellext/stobject/resources/hotplug/1.ico differ diff --git a/dll/shellext/stobject/stobject.rc b/dll/shellext/stobject/stobject.rc index f7844dead4..4d7e6da69f 100644 --- a/dll/shellext/stobject/stobject.rc +++ b/dll/shellext/stobject/stobject.rc @@ -11,6 +11,25 @@ IDI_EXTRACT ICON "resources/2.ico" IDI_VOLUME ICON "resources/3.ico" IDI_VOLMUTE ICON "resources/4.ico" +IDI_BATTCAP0 ICON "resources/battery/0.ico" +IDI_BATTCAP1 ICON "resources/battery/1.ico" +IDI_BATTCAP2 ICON "resources/battery/2.ico" +IDI_BATTCAP3 ICON "resources/battery/3.ico" +IDI_BATTCAP4 ICON "resources/battery/4.ico" +IDI_BATTCAP5 ICON "resources/battery/5.ico" + +IDI_BATTCHA0 ICON "resources/battery/charging0.ico" +IDI_BATTCHA1 ICON "resources/battery/charging1.ico" +IDI_BATTCHA2 ICON "resources/battery/charging2.ico" +IDI_BATTCHA3 ICON "resources/battery/charging3.ico" +IDI_BATTCHA4 ICON "resources/battery/charging4.ico" + +IDI_BATTCAP_ERR ICON "resources/battery/error.ico" + +IDI_HOTPLUG_ERR ICON "resources/hotplug/0.ico" +IDI_HOTPLUG_OK ICON "resources/hotplug/1.ico" + + IDR_SYSTRAY REGISTRY "resources/rgs/systray.rgs" #include <reactos/manifest_dll.rc> diff --git a/dll/shellext/stobject/volume.cpp b/dll/shellext/stobject/volume.cpp index f82e6e0eee..b7cb3ff049 100644 --- a/dll/shellext/stobject/volume.cpp +++ b/dll/shellext/stobject/volume.cpp @@ -113,7 +113,7 @@ static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray) return S_OK; } -HRESULT Volume_IsMute(VOID) +HRESULT Volume_IsMute() { #if 0 MIXERCONTROLDETAILS mixerControlDetails; @@ -217,10 +217,10 @@ HRESULT Volume_OnDeviceChange(_In_ CSysTray * pSysTray, WPARAM wParam, LPARAM lP return Volume_FindMixerControl(pSysTray); } -static void _RunVolume(BOOL bSmall) +static void _RunVolume() { // FIXME: ensure we are loading the right one - ShellExecuteW(NULL, NULL, L"sndvol32.exe", bSmall ? L"/t" : NULL, NULL, SW_SHOWNORMAL); + ShellExecuteW(NULL, NULL, L"sndvol32.exe", NULL, NULL, SW_SHOWNORMAL); } static void _RunMMCpl() @@ -238,14 +238,14 @@ static void _ShowContextMenu(CSysTray * pSysTray) HMENU hPopup = CreatePopupMenu(); AppendMenuW(hPopup, MF_STRING, IDS_VOL_OPEN, strOpen); AppendMenuW(hPopup, MF_STRING, IDS_VOL_ADJUST, strAdjust); - SetMenuDefaultItem(hPopup, IDS_VOL_OPEN, FALSE); DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN; - DWORD msgPos = GetMessagePos(); - + POINT pt; SetForegroundWindow(pSysTray->GetHWnd()); + GetCursorPos(&pt); + DWORD id = TrackPopupMenuEx(hPopup, flags, - GET_X_LPARAM(msgPos), GET_Y_LPARAM(msgPos), + pt.x, pt.y, pSysTray->GetHWnd(), NULL); DestroyMenu(hPopup); @@ -253,7 +253,7 @@ static void _ShowContextMenu(CSysTray * pSysTray) switch (id) { case IDS_VOL_OPEN: - _RunVolume(FALSE); + _RunVolume(); break; case IDS_VOL_ADJUST: _RunMMCpl(); @@ -296,15 +296,14 @@ HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WP switch (lParam) { case WM_LBUTTONDOWN: - SetTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID, 500, NULL); break; case WM_LBUTTONUP: + TRACE("TODO: display volume slider\n"); break; case WM_LBUTTONDBLCLK: - KillTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID); - _RunVolume(FALSE); + _RunVolume(); break; case WM_RBUTTONDOWN: @@ -329,11 +328,3 @@ HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WP return S_FALSE; } - -VOID -Volume_OnTimer(HWND hWnd) -{ - TRACE("Volume_OnTimer\n!"); - KillTimer(hWnd, VOLUME_TIMER_ID); - _RunVolume(TRUE); -}