[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}/sdk/lib/atl
|
||||||
${REACTOS_SOURCE_DIR})
|
${REACTOS_SOURCE_DIR})
|
||||||
|
|
||||||
|
add_definitions(
|
||||||
|
-D_ATL_NO_EXCEPTIONS)
|
||||||
|
|
||||||
spec2def(stobject.dll stobject.spec)
|
spec2def(stobject.dll stobject.spec)
|
||||||
|
|
||||||
file(GLOB_RECURSE stobject_rc_deps resources/*.*)
|
file(GLOB_RECURSE stobject_rc_deps resources/*.*)
|
||||||
|
@ -30,6 +33,7 @@ set_module_type(stobject win32dll UNICODE)
|
||||||
target_link_libraries(stobject uuid wine atlnew)
|
target_link_libraries(stobject uuid wine atlnew)
|
||||||
|
|
||||||
add_importlibs(stobject
|
add_importlibs(stobject
|
||||||
|
setupapi
|
||||||
advapi32
|
advapi32
|
||||||
winmm
|
winmm
|
||||||
ole32
|
ole32
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* FILE: dll/shellext/stobject/csystray.cpp
|
* FILE: dll/shellext/stobject/csystray.cpp
|
||||||
* PURPOSE: Systray shell service object implementation
|
* PURPOSE: Systray shell service object implementation
|
||||||
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
|
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
|
||||||
|
* Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -97,7 +98,27 @@ HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, LR
|
||||||
return S_FALSE;
|
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 };
|
NOTIFYICONDATA nim = { 0 };
|
||||||
|
|
||||||
|
@ -108,8 +129,8 @@ HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip)
|
||||||
nim.hIcon = hIcon;
|
nim.hIcon = hIcon;
|
||||||
nim.uID = uId;
|
nim.uID = uId;
|
||||||
nim.uCallbackMessage = uId;
|
nim.uCallbackMessage = uId;
|
||||||
nim.dwState = 0;
|
nim.dwState = dwstate;
|
||||||
nim.dwStateMask = 0;
|
nim.dwStateMask = NIS_HIDDEN;
|
||||||
nim.hWnd = m_hWnd;
|
nim.hWnd = m_hWnd;
|
||||||
nim.uVersion = NOTIFYICON_VERSION;
|
nim.uVersion = NOTIFYICON_VERSION;
|
||||||
if (szTip)
|
if (szTip)
|
||||||
|
@ -219,30 +240,8 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
switch (wParam)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
UpdateIcons();
|
UpdateIcons();
|
||||||
return TRUE;
|
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;
|
|
||||||
|
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
KillTimer(1);
|
KillTimer(1);
|
||||||
ShutdownIcons();
|
ShutdownIcons();
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* PURPOSE: Systray shell service object
|
* PURPOSE: Systray shell service object
|
||||||
* PROGRAMMERS: Robert Naumann
|
* PROGRAMMERS: Robert Naumann
|
||||||
* David Quintana <gigaherz@gmail.com>
|
* David Quintana <gigaherz@gmail.com>
|
||||||
|
* Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ class CSysTray :
|
||||||
HRESULT ShutdownNetShell();
|
HRESULT ShutdownNetShell();
|
||||||
|
|
||||||
public:
|
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; }
|
HWND GetHWnd() { return m_hWnd; }
|
||||||
|
|
||||||
|
|
|
@ -2,38 +2,152 @@
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: dll/shellext/stobject/hotplug.cpp
|
* FILE: dll/shellext/stobject/hotplug.cpp
|
||||||
* PURPOSE: Hotplug notification icon handler
|
* PURPOSE: Removable devices notification icon handler
|
||||||
* PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
|
* PROGRAMMERS: Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
|
||||||
* David Quintana <gigaherz@gmail.com>
|
|
||||||
*/
|
*/
|
||||||
|
#include <windows.h>
|
||||||
#include "precomp.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);
|
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 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_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)
|
HRESULT STDMETHODCALLTYPE Hotplug_Init(_In_ CSysTray * pSysTray)
|
||||||
{
|
{
|
||||||
WCHAR strTooltip[128];
|
|
||||||
|
|
||||||
TRACE("Hotplug_Init\n");
|
TRACE("Hotplug_Init\n");
|
||||||
|
g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_HOTPLUG_OK));
|
||||||
g_hIconHotplug = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_EXTRACT));
|
|
||||||
|
|
||||||
LoadStringW(g_hInstance, IDS_HOTPLUG_REMOVE_1, strTooltip, _countof(strTooltip));
|
|
||||||
|
|
||||||
g_IsRunning = TRUE;
|
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)
|
HRESULT STDMETHODCALLTYPE Hotplug_Update(_In_ CSysTray * pSysTray)
|
||||||
{
|
{
|
||||||
TRACE("Hotplug_Update\n");
|
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)
|
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);
|
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];
|
HMENU hPopup = CreatePopupMenu();
|
||||||
DWORD id, msgPos;
|
ULONG ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
|
||||||
HMENU hPopup;
|
|
||||||
|
|
||||||
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();
|
swprintf(menuName, L"Eject %wS", dispName);
|
||||||
AppendMenuW(hPopup, MF_STRING, 1, szBuffer);
|
AppendMenuW(hPopup, MF_STRING, index+1, menuName);
|
||||||
|
}
|
||||||
msgPos = GetMessagePos();
|
|
||||||
|
|
||||||
SetForegroundWindow(pSysTray->GetHWnd());
|
SetForegroundWindow(pSysTray->GetHWnd());
|
||||||
id = TrackPopupMenuEx(hPopup,
|
DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
|
||||||
TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN,
|
POINT pt;
|
||||||
GET_X_LPARAM(msgPos),
|
GetCursorPos(&pt);
|
||||||
GET_Y_LPARAM(msgPos),
|
|
||||||
pSysTray->GetHWnd(),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
DestroyMenu(hPopup);
|
DWORD id = TrackPopupMenuEx(hPopup, flags,
|
||||||
|
pt.x, pt.y,
|
||||||
|
pSysTray->GetHWnd(), NULL);
|
||||||
|
|
||||||
if (id == 1)
|
if (id > 0)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
#endif
|
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.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
TRACE("Hotplug_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg, wParam, lParam);
|
||||||
|
|
||||||
switch (uMsg)
|
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:
|
case WM_USER + 220:
|
||||||
TRACE("Hotplug_Message: WM_USER+220\n");
|
TRACE("Hotplug_Message: WM_USER+220\n");
|
||||||
if (wParam == 2)
|
if (wParam == 1)
|
||||||
{
|
{
|
||||||
if (lParam == FALSE)
|
if (lParam == FALSE)
|
||||||
return Hotplug_Init(pSysTray);
|
return Hotplug_Init(pSysTray);
|
||||||
|
@ -128,7 +275,7 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WP
|
||||||
|
|
||||||
case WM_USER + 221:
|
case WM_USER + 221:
|
||||||
TRACE("Hotplug_Message: WM_USER+221\n");
|
TRACE("Hotplug_Message: WM_USER+221\n");
|
||||||
if (wParam == 2)
|
if (wParam == 1)
|
||||||
{
|
{
|
||||||
lResult = (LRESULT)g_IsRunning;
|
lResult = (LRESULT)g_IsRunning;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -141,22 +288,21 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WP
|
||||||
switch (lParam)
|
switch (lParam)
|
||||||
{
|
{
|
||||||
case WM_LBUTTONDOWN:
|
case WM_LBUTTONDOWN:
|
||||||
SetTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID, 500, NULL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
|
_ShowContextMenu(pSysTray);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDBLCLK:
|
case WM_LBUTTONDBLCLK:
|
||||||
KillTimer(pSysTray->GetHWnd(), HOTPLUG_TIMER_ID);
|
_RunHotplug(pSysTray);
|
||||||
RunHotplug();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDOWN:
|
case WM_RBUTTONDOWN:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONUP:
|
case WM_RBUTTONUP:
|
||||||
ShowContextMenu(pSysTray);
|
_ShowContextMenuR(pSysTray);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDBLCLK:
|
case WM_RBUTTONDBLCLK:
|
||||||
|
@ -167,6 +313,41 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WP
|
||||||
}
|
}
|
||||||
return S_OK;
|
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:
|
default:
|
||||||
TRACE("Hotplug_Message received for unknown ID %d, ignoring.\n");
|
TRACE("Hotplug_Message received for unknown ID %d, ignoring.\n");
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
@ -174,11 +355,3 @@ HRESULT STDMETHODCALLTYPE Hotplug_Message(_In_ CSysTray *pSysTray, UINT uMsg, WP
|
||||||
|
|
||||||
return S_FALSE;
|
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_PROPERTIES "&Upravit možnosti napájení"
|
||||||
IDS_PWR_METER "&Otevřít ukazatel spotřeby"
|
IDS_PWR_METER "&Otevřít ukazatel spotřeby"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "zbývá %1!u!%%"
|
IDS_PWR_PERCENT_REMAINING "zbývá %.2f%%"
|
||||||
IDS_PWR_CHARGING " (nabíjení)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Zbývá neznámo"
|
IDS_PWR_UNKNOWN_REMAINING "Zbývá neznámo"
|
||||||
IDS_PWR_AC "On AC power"
|
IDS_PWR_AC "On AC power"
|
||||||
IDS_PWR_HOURS_REMAINING "zbývá %1!u!:%2!02u! hodin (%3!u!%%)"
|
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_PROPERTIES "&Energieverwaltungseigenschaften einstellen"
|
||||||
IDS_PWR_METER "Batterieanzeige ö&ffnen"
|
IDS_PWR_METER "Batterieanzeige ö&ffnen"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "%1!u!%% verbleibend"
|
IDS_PWR_PERCENT_REMAINING "%.2f%% verbleibend"
|
||||||
IDS_PWR_CHARGING " (wird aufgeladen)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Unbekannt verbleibend"
|
IDS_PWR_UNKNOWN_REMAINING "Unbekannt verbleibend"
|
||||||
IDS_PWR_AC "Mit Wechselstrom"
|
IDS_PWR_AC "Mit Wechselstrom"
|
||||||
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! Stunden (%3!u!%%) verbleibend"
|
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_PROPERTIES "&Adjust Power Properties"
|
||||||
IDS_PWR_METER "&Open Power Meter"
|
IDS_PWR_METER "&Open Power Meter"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "%1!u!%% remaining"
|
IDS_PWR_PERCENT_REMAINING "%.2f%% remaining"
|
||||||
IDS_PWR_CHARGING " (charging)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Unknown remaining"
|
IDS_PWR_UNKNOWN_REMAINING "Unknown remaining"
|
||||||
IDS_PWR_AC "On AC power"
|
IDS_PWR_AC "On AC power"
|
||||||
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! hours (%3!u!%%) remaining"
|
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_PROPERTIES "&Ajustar propiedades de energía"
|
||||||
IDS_PWR_METER "Abrir &medidor de energía"
|
IDS_PWR_METER "Abrir &medidor de energía"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "Queda un %1!u!%%"
|
IDS_PWR_PERCENT_REMAINING "Queda un %.2f%%"
|
||||||
IDS_PWR_CHARGING " (cargando)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Estado de batería desconocido"
|
IDS_PWR_UNKNOWN_REMAINING "Estado de batería desconocido"
|
||||||
IDS_PWR_AC "En corriente alterna"
|
IDS_PWR_AC "En corriente alterna"
|
||||||
IDS_PWR_HOURS_REMAINING "Quedan %1!u!:%2!02u! horas (%3!u!%%)"
|
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_PROPERTIES "&Adjust Power Properties"
|
||||||
IDS_PWR_METER "&Open Power Meter"
|
IDS_PWR_METER "&Open Power Meter"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "%1!u!%% remaining"
|
IDS_PWR_PERCENT_REMAINING "%.2f%% remaining"
|
||||||
IDS_PWR_CHARGING " (charging)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Unknown remaining"
|
IDS_PWR_UNKNOWN_REMAINING "Unknown remaining"
|
||||||
IDS_PWR_AC "On AC power"
|
IDS_PWR_AC "On AC power"
|
||||||
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! hours (%3!u!%%) remaining"
|
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_PROPERTIES "&Modifica proprietà alimentazione"
|
||||||
IDS_PWR_METER "&Apri misuratore alimentazione"
|
IDS_PWR_METER "&Apri misuratore alimentazione"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "%1!u!%% rimanenti"
|
IDS_PWR_PERCENT_REMAINING "%.2f%% rimanenti"
|
||||||
IDS_PWR_CHARGING " (in carica)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Autonomia sconosciuta"
|
IDS_PWR_UNKNOWN_REMAINING "Autonomia sconosciuta"
|
||||||
IDS_PWR_AC "Alimentazione da rete AC"
|
IDS_PWR_AC "Alimentazione da rete AC"
|
||||||
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! ore (%3!u!%%) rimanenti"
|
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! ore (%3!u!%%) rimanenti"
|
||||||
|
|
|
@ -18,8 +18,8 @@ BEGIN
|
||||||
IDS_PWR_PROPERTIES "&Opcje zasilania"
|
IDS_PWR_PROPERTIES "&Opcje zasilania"
|
||||||
IDS_PWR_METER "&Otwórz miernik baterii"
|
IDS_PWR_METER "&Otwórz miernik baterii"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "Pozostało %1!u!%%"
|
IDS_PWR_PERCENT_REMAINING "Pozostało %.2f%%"
|
||||||
IDS_PWR_CHARGING " (ładowanie)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Stan naładowania nieznany"
|
IDS_PWR_UNKNOWN_REMAINING "Stan naładowania nieznany"
|
||||||
IDS_PWR_AC "Podłączony do zasilacza"
|
IDS_PWR_AC "Podłączony do zasilacza"
|
||||||
IDS_PWR_HOURS_REMAINING "Pozostało %1!u!:%2!02u! godzin (%3!u!%%)"
|
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_PROPERTIES "&Ajustare proprietăți de consum energie"
|
||||||
IDS_PWR_METER "&Deschide Contor de energie"
|
IDS_PWR_METER "&Deschide Contor de energie"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "Au mai rămas %1!u!%%"
|
IDS_PWR_PERCENT_REMAINING "Au mai rămas %.2f%%"
|
||||||
IDS_PWR_CHARGING " (în încărcare)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Nu este disponibil cât a mai rămas"
|
IDS_PWR_UNKNOWN_REMAINING "Nu este disponibil cât a mai rămas"
|
||||||
IDS_PWR_AC "În rețea de CA"
|
IDS_PWR_AC "În rețea de CA"
|
||||||
IDS_PWR_HOURS_REMAINING "Au mai rămas %1!u!:%2!02u! ore (%3!u!%%)"
|
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_PROPERTIES "&Настройка параметров электропитания"
|
||||||
IDS_PWR_METER "&Открыть показатели питания"
|
IDS_PWR_METER "&Открыть показатели питания"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "%1!u!%% осталось"
|
IDS_PWR_PERCENT_REMAINING "%.2f%% осталось"
|
||||||
IDS_PWR_CHARGING " (зарядка)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "Неизвестно"
|
IDS_PWR_UNKNOWN_REMAINING "Неизвестно"
|
||||||
IDS_PWR_AC "От сети переменного тока"
|
IDS_PWR_AC "От сети переменного тока"
|
||||||
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! часов (%3!u!%%) осталось"
|
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! часов (%3!u!%%) осталось"
|
||||||
|
|
|
@ -20,8 +20,8 @@ BEGIN
|
||||||
IDS_PWR_PROPERTIES "调整电源属性(&A)"
|
IDS_PWR_PROPERTIES "调整电源属性(&A)"
|
||||||
IDS_PWR_METER "开放式电源表(&O)"
|
IDS_PWR_METER "开放式电源表(&O)"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "剩余 %1!u!%%"
|
IDS_PWR_PERCENT_REMAINING "剩余 %.2f%%"
|
||||||
IDS_PWR_CHARGING " (充电中)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "未知剩余"
|
IDS_PWR_UNKNOWN_REMAINING "未知剩余"
|
||||||
IDS_PWR_AC "交流电源"
|
IDS_PWR_AC "交流电源"
|
||||||
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! 小时 剩余 (%3!u!%%) "
|
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! 小时 剩余 (%3!u!%%) "
|
||||||
|
|
|
@ -20,8 +20,8 @@ BEGIN
|
||||||
IDS_PWR_PROPERTIES "調整電源屬性(&A)"
|
IDS_PWR_PROPERTIES "調整電源屬性(&A)"
|
||||||
IDS_PWR_METER "開放式電源表(&O)"
|
IDS_PWR_METER "開放式電源表(&O)"
|
||||||
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
|
||||||
IDS_PWR_PERCENT_REMAINING "剩餘 %1!u!%%"
|
IDS_PWR_PERCENT_REMAINING "剩餘 %.2f%%"
|
||||||
IDS_PWR_CHARGING " (充電中)"
|
IDS_PWR_CHARGING "%.2f%% and charging"
|
||||||
IDS_PWR_UNKNOWN_REMAINING "未知剩餘"
|
IDS_PWR_UNKNOWN_REMAINING "未知剩餘"
|
||||||
IDS_PWR_AC "交流電源"
|
IDS_PWR_AC "交流電源"
|
||||||
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! 小時 剩餘 (%3!u!%%) "
|
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! 小時 剩餘 (%3!u!%%) "
|
||||||
|
|
|
@ -4,14 +4,30 @@
|
||||||
* FILE: dll/shellext/stobject/power.cpp
|
* FILE: dll/shellext/stobject/power.cpp
|
||||||
* PURPOSE: Power notification icon handler
|
* PURPOSE: Power notification icon handler
|
||||||
* PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
|
* PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
|
||||||
|
Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com>
|
||||||
* David Quintana <gigaherz@gmail.com>
|
* David Quintana <gigaherz@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <SetupAPI.h>
|
||||||
|
#include <devguid.h>
|
||||||
|
#include <BatClass.h>
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
#include "powrprof.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);
|
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
|
typedef struct _PWRSCHEMECONTEXT
|
||||||
{
|
{
|
||||||
HMENU hPopup;
|
HMENU hPopup;
|
||||||
|
@ -19,71 +35,261 @@ typedef struct _PWRSCHEMECONTEXT
|
||||||
UINT uiLast;
|
UINT uiLast;
|
||||||
} PWRSCHEMECONTEXT, *PPWRSCHEMECONTEXT;
|
} PWRSCHEMECONTEXT, *PPWRSCHEMECONTEXT;
|
||||||
|
|
||||||
|
CString g_strTooltip;
|
||||||
|
static float g_batCap = 0;
|
||||||
static HICON g_hIconBattery = NULL;
|
static HICON g_hIconBattery = NULL;
|
||||||
static BOOL g_IsRunning = FALSE;
|
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)
|
HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray)
|
||||||
{
|
{
|
||||||
WCHAR strTooltip[128];
|
|
||||||
|
|
||||||
TRACE("Power_Init\n");
|
TRACE("Power_Init\n");
|
||||||
|
g_hIconBattery = DynamicLoadIcon(g_hInstance);
|
||||||
g_hIconBattery = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BATTERY));
|
|
||||||
|
|
||||||
LoadStringW(g_hInstance, IDS_PWR_AC, strTooltip, _countof(strTooltip));
|
|
||||||
|
|
||||||
g_IsRunning = TRUE;
|
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)
|
HRESULT STDMETHODCALLTYPE Power_Update(_In_ CSysTray * pSysTray)
|
||||||
{
|
{
|
||||||
TRACE("Power_Update\n");
|
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)
|
HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray)
|
||||||
{
|
{
|
||||||
TRACE("Power_Shutdown\n");
|
TRACE("Power_Shutdown\n");
|
||||||
|
|
||||||
g_IsRunning = FALSE;
|
g_IsRunning = FALSE;
|
||||||
|
|
||||||
return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_POWER, NULL, NULL);
|
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];
|
CString strOpen((LPCSTR)IDS_PWR_PROPERTIES);
|
||||||
DWORD id, msgPos;
|
HMENU hPopup = CreatePopupMenu();
|
||||||
HMENU hPopup;
|
AppendMenuW(hPopup, MF_STRING, IDS_PWR_PROPERTIES, strOpen);
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
SetForegroundWindow(pSysTray->GetHWnd());
|
SetForegroundWindow(pSysTray->GetHWnd());
|
||||||
id = TrackPopupMenuEx(hPopup,
|
DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
|
||||||
TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN,
|
POINT pt;
|
||||||
GET_X_LPARAM(msgPos),
|
GetCursorPos(&pt);
|
||||||
GET_Y_LPARAM(msgPos),
|
|
||||||
pSysTray->GetHWnd(),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
|
DWORD id = TrackPopupMenuEx(hPopup, flags,
|
||||||
|
pt.x, pt.y,
|
||||||
|
pSysTray->GetHWnd(), NULL);
|
||||||
|
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case IDS_PWR_PROPERTIES:
|
||||||
|
_RunPower();
|
||||||
|
break;
|
||||||
|
}
|
||||||
DestroyMenu(hPopup);
|
DestroyMenu(hPopup);
|
||||||
|
|
||||||
if (id == IDS_PWR_PROPERTIES)
|
|
||||||
RunPower();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -114,12 +320,12 @@ PowerSchemesEnumProc(
|
||||||
static
|
static
|
||||||
VOID
|
VOID
|
||||||
ShowPowerSchemesPopupMenu(
|
ShowPowerSchemesPopupMenu(
|
||||||
HWND hWnd)
|
CSysTray *pSysTray)
|
||||||
{
|
{
|
||||||
PWRSCHEMECONTEXT PowerSchemeContext = {NULL, 0, 0};
|
PWRSCHEMECONTEXT PowerSchemeContext = {NULL, 0, 0};
|
||||||
UINT uiActiveScheme;
|
UINT uiActiveScheme;
|
||||||
DWORD id, msgPos;
|
DWORD id;
|
||||||
|
POINT pt;
|
||||||
PowerSchemeContext.hPopup = CreatePopupMenu();
|
PowerSchemeContext.hPopup = CreatePopupMenu();
|
||||||
EnumPwrSchemes(PowerSchemesEnumProc, (LPARAM)&PowerSchemeContext);
|
EnumPwrSchemes(PowerSchemesEnumProc, (LPARAM)&PowerSchemeContext);
|
||||||
|
|
||||||
|
@ -132,14 +338,14 @@ ShowPowerSchemesPopupMenu(
|
||||||
MF_BYCOMMAND);
|
MF_BYCOMMAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
msgPos = GetMessagePos();
|
SetForegroundWindow(pSysTray->GetHWnd());
|
||||||
|
GetCursorPos(&pt);
|
||||||
|
|
||||||
SetForegroundWindow(hWnd);
|
|
||||||
id = TrackPopupMenuEx(PowerSchemeContext.hPopup,
|
id = TrackPopupMenuEx(PowerSchemeContext.hPopup,
|
||||||
TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN,
|
TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN,
|
||||||
GET_X_LPARAM(msgPos),
|
pt.x,
|
||||||
GET_Y_LPARAM(msgPos),
|
pt.y,
|
||||||
hWnd,
|
pSysTray->GetHWnd(),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
DestroyMenu(PowerSchemeContext.hPopup);
|
DestroyMenu(PowerSchemeContext.hPopup);
|
||||||
|
@ -180,22 +386,21 @@ HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPA
|
||||||
switch (lParam)
|
switch (lParam)
|
||||||
{
|
{
|
||||||
case WM_LBUTTONDOWN:
|
case WM_LBUTTONDOWN:
|
||||||
SetTimer(pSysTray->GetHWnd(), POWER_TIMER_ID, 500, NULL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
|
ShowPowerSchemesPopupMenu(pSysTray);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDBLCLK:
|
case WM_LBUTTONDBLCLK:
|
||||||
KillTimer(pSysTray->GetHWnd(), POWER_TIMER_ID);
|
_RunPower();
|
||||||
RunPower();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDOWN:
|
case WM_RBUTTONDOWN:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONUP:
|
case WM_RBUTTONUP:
|
||||||
ShowContextMenu(pSysTray);
|
_ShowContextMenu(pSysTray);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDBLCLK:
|
case WM_RBUTTONDBLCLK:
|
||||||
|
@ -213,11 +418,3 @@ HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPA
|
||||||
|
|
||||||
return S_FALSE;
|
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_Shutdown(_In_ CSysTray * pSysTray);
|
||||||
extern HRESULT STDMETHODCALLTYPE Volume_Update(_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 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_Init(_In_ CSysTray * pSysTray);
|
||||||
extern HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray);
|
extern HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray);
|
||||||
extern HRESULT STDMETHODCALLTYPE Hotplug_Update(_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 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_Init(_In_ CSysTray * pSysTray);
|
||||||
extern HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray);
|
extern HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray);
|
||||||
extern HRESULT STDMETHODCALLTYPE Power_Update(_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 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 POWER_TIMER_ID 2
|
||||||
#define VOLUME_TIMER_ID 3
|
#define VOLUME_TIMER_ID 3
|
||||||
|
|
|
@ -39,4 +39,20 @@
|
||||||
#define IDS_KEYS_MOUSE 331
|
#define IDS_KEYS_MOUSE 331
|
||||||
#define IDS_KEYS_FILTER 332
|
#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
|
#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_VOLUME ICON "resources/3.ico"
|
||||||
IDI_VOLMUTE ICON "resources/4.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"
|
IDR_SYSTRAY REGISTRY "resources/rgs/systray.rgs"
|
||||||
|
|
||||||
#include <reactos/manifest_dll.rc>
|
#include <reactos/manifest_dll.rc>
|
||||||
|
|
|
@ -113,7 +113,7 @@ static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Volume_IsMute(VOID)
|
HRESULT Volume_IsMute()
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
MIXERCONTROLDETAILS mixerControlDetails;
|
MIXERCONTROLDETAILS mixerControlDetails;
|
||||||
|
@ -217,10 +217,10 @@ HRESULT Volume_OnDeviceChange(_In_ CSysTray * pSysTray, WPARAM wParam, LPARAM lP
|
||||||
return Volume_FindMixerControl(pSysTray);
|
return Volume_FindMixerControl(pSysTray);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _RunVolume(BOOL bSmall)
|
static void _RunVolume()
|
||||||
{
|
{
|
||||||
// FIXME: ensure we are loading the right one
|
// 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()
|
static void _RunMMCpl()
|
||||||
|
@ -238,14 +238,14 @@ static void _ShowContextMenu(CSysTray * pSysTray)
|
||||||
HMENU hPopup = CreatePopupMenu();
|
HMENU hPopup = CreatePopupMenu();
|
||||||
AppendMenuW(hPopup, MF_STRING, IDS_VOL_OPEN, strOpen);
|
AppendMenuW(hPopup, MF_STRING, IDS_VOL_OPEN, strOpen);
|
||||||
AppendMenuW(hPopup, MF_STRING, IDS_VOL_ADJUST, strAdjust);
|
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 flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN;
|
||||||
DWORD msgPos = GetMessagePos();
|
POINT pt;
|
||||||
|
|
||||||
SetForegroundWindow(pSysTray->GetHWnd());
|
SetForegroundWindow(pSysTray->GetHWnd());
|
||||||
|
GetCursorPos(&pt);
|
||||||
|
|
||||||
DWORD id = TrackPopupMenuEx(hPopup, flags,
|
DWORD id = TrackPopupMenuEx(hPopup, flags,
|
||||||
GET_X_LPARAM(msgPos), GET_Y_LPARAM(msgPos),
|
pt.x, pt.y,
|
||||||
pSysTray->GetHWnd(), NULL);
|
pSysTray->GetHWnd(), NULL);
|
||||||
|
|
||||||
DestroyMenu(hPopup);
|
DestroyMenu(hPopup);
|
||||||
|
@ -253,7 +253,7 @@ static void _ShowContextMenu(CSysTray * pSysTray)
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case IDS_VOL_OPEN:
|
case IDS_VOL_OPEN:
|
||||||
_RunVolume(FALSE);
|
_RunVolume();
|
||||||
break;
|
break;
|
||||||
case IDS_VOL_ADJUST:
|
case IDS_VOL_ADJUST:
|
||||||
_RunMMCpl();
|
_RunMMCpl();
|
||||||
|
@ -296,15 +296,14 @@ HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WP
|
||||||
switch (lParam)
|
switch (lParam)
|
||||||
{
|
{
|
||||||
case WM_LBUTTONDOWN:
|
case WM_LBUTTONDOWN:
|
||||||
SetTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID, 500, NULL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
|
TRACE("TODO: display volume slider\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDBLCLK:
|
case WM_LBUTTONDBLCLK:
|
||||||
KillTimer(pSysTray->GetHWnd(), VOLUME_TIMER_ID);
|
_RunVolume();
|
||||||
_RunVolume(FALSE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_RBUTTONDOWN:
|
case WM_RBUTTONDOWN:
|
||||||
|
@ -329,11 +328,3 @@ HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WP
|
||||||
|
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
Volume_OnTimer(HWND hWnd)
|
|
||||||
{
|
|
||||||
TRACE("Volume_OnTimer\n!");
|
|
||||||
KillTimer(hWnd, VOLUME_TIMER_ID);
|
|
||||||
_RunVolume(TRUE);
|
|
||||||
}
|
|
||||||
|
|