[STOBJECT] Implement the hotplug and the power icons in the system tray
|
@ -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
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* FILE: dll/shellext/stobject/csystray.cpp
|
||||
* PURPOSE: Systray shell service object implementation
|
||||
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
|
||||
* Shriraj Sawant a.k.a SR13 <sr.official@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();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* PURPOSE: Systray shell service object
|
||||
* PROGRAMMERS: Robert Naumann
|
||||
* David Quintana <gigaherz@gmail.com>
|
||||
* Shriraj Sawant a.k.a SR13 <sr.official@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; }
|
||||
|
||||
|
|
|
@ -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.kohl@reactos.org>
|
||||
* David Quintana <gigaherz@gmail.com>
|
||||
* PURPOSE: Removable devices notification icon handler
|
||||
* PROGRAMMERS: Shriraj Sawant a.k.a SR13 <sr.official@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;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (NO_ERROR != GetLastError() && ERROR_NO_MORE_ITEMS != GetLastError())
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @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)
|
||||
{
|
||||
WCHAR strTooltip[128];
|
||||
|
||||
{
|
||||
TRACE("Hotplug_Init\n");
|
||||
|
||||
g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_EXTRACT));
|
||||
|
||||
LoadStringW(g_hInstance, IDS_HOTPLUG_REMOVE_1, strTooltip, _countof(strTooltip));
|
||||
|
||||
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;
|
||||
HMENU hPopup = CreatePopupMenu();
|
||||
ULONG ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
|
||||
|
||||
LoadStringW(g_hInstance, IDS_HOTPLUG_REMOVE_2, szBuffer, _countof(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");
|
||||
|
||||
hPopup = CreatePopupMenu();
|
||||
AppendMenuW(hPopup, MF_STRING, 1, szBuffer);
|
||||
|
||||
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 == 1)
|
||||
RunHotplug();
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
ShowHotplugPopupMenu(
|
||||
HWND hWnd)
|
||||
{
|
||||
#if 0
|
||||
DWORD id, msgPos;
|
||||
|
||||
HMENU hPopup = CreatePopupMenu();
|
||||
|
||||
// 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);
|
||||
|
||||
DestroyMenu(hPopup);
|
||||
|
||||
if (id != 0)
|
||||
if (id > 0)
|
||||
{
|
||||
// FIXME
|
||||
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.
|
||||
*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DestroyMenu(hPopup);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult)
|
||||
static void _ShowContextMenuR(CSysTray * pSysTray)
|
||||
{
|
||||
CString strMenu((LPWSTR)IDS_HOTPLUG_REMOVE_2);
|
||||
HMENU hPopup = CreatePopupMenu();
|
||||
AppendMenuW(hPopup, MF_STRING, IDS_HOTPLUG_REMOVE_2, strMenu);
|
||||
|
||||
SetForegroundWindow(pSysTray->GetHWnd());
|
||||
DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
|
||||
POINT pt;
|
||||
GetCursorPos(&pt);
|
||||
|
||||
DWORD id = TrackPopupMenuEx(hPopup, flags,
|
||||
pt.x, pt.y,
|
||||
pSysTray->GetHWnd(), NULL);
|
||||
|
||||
if (id == IDS_HOTPLUG_REMOVE_2)
|
||||
{
|
||||
_RunHotplug(pSysTray);
|
||||
}
|
||||
|
||||
DestroyMenu(hPopup);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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!%%)"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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!%%)"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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!%%)"
|
||||
|
|
|
@ -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!%%)"
|
||||
|
|
|
@ -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!%%) осталось"
|
||||
|
|
|
@ -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!%%) "
|
||||
|
|
|
@ -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!%%) "
|
||||
|
|
|
@ -4,14 +4,30 @@
|
|||
* FILE: dll/shellext/stobject/power.cpp
|
||||
* PURPOSE: Power notification icon handler
|
||||
* PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
|
||||
Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
|
||||
* David Quintana <gigaherz@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;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
*/
|
||||
}
|
||||
|
||||
/*++
|
||||
* @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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return hBatIcon;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray)
|
||||
{
|
||||
WCHAR strTooltip[128];
|
||||
|
||||
{
|
||||
TRACE("Power_Init\n");
|
||||
|
||||
g_hIconBattery = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BATTERY));
|
||||
|
||||
LoadStringW(g_hInstance, IDS_PWR_AC, strTooltip, _countof(strTooltip));
|
||||
|
||||
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);
|
||||
|
||||
DWORD id = TrackPopupMenuEx(hPopup, flags,
|
||||
pt.x, pt.y,
|
||||
pSysTray->GetHWnd(), NULL);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case IDS_PWR_PROPERTIES:
|
||||
_RunPower();
|
||||
break;
|
||||
}
|
||||
DestroyMenu(hPopup);
|
||||
|
||||
if (id == IDS_PWR_PROPERTIES)
|
||||
RunPower();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
BIN
dll/shellext/stobject/resources/battery/0.ico
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
dll/shellext/stobject/resources/battery/1.ico
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
dll/shellext/stobject/resources/battery/2.ico
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
dll/shellext/stobject/resources/battery/3.ico
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
dll/shellext/stobject/resources/battery/4.ico
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
dll/shellext/stobject/resources/battery/5.ico
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
dll/shellext/stobject/resources/battery/charging0.ico
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
dll/shellext/stobject/resources/battery/charging1.ico
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
dll/shellext/stobject/resources/battery/charging2.ico
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
dll/shellext/stobject/resources/battery/charging3.ico
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
dll/shellext/stobject/resources/battery/charging4.ico
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
dll/shellext/stobject/resources/battery/error.ico
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
dll/shellext/stobject/resources/hotplug/0.ico
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
dll/shellext/stobject/resources/hotplug/1.ico
Normal file
After Width: | Height: | Size: 2.5 KiB |
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|