diff --git a/reactos/dll/shellext/stobject/CMakeLists.txt b/reactos/dll/shellext/stobject/CMakeLists.txt index f2b54c6fef6c9..f9a823422b0e2 100644 --- a/reactos/dll/shellext/stobject/CMakeLists.txt +++ b/reactos/dll/shellext/stobject/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(stobject SHARED csystray.cpp stobject.cpp stobject.rc + power.cpp volume.cpp ${CMAKE_CURRENT_BINARY_DIR}/stobject.def) diff --git a/reactos/dll/shellext/stobject/csystray.cpp b/reactos/dll/shellext/stobject/csystray.cpp index 97b3d88f0f2d9..6200254d0fd84 100644 --- a/reactos/dll/shellext/stobject/csystray.cpp +++ b/reactos/dll/shellext/stobject/csystray.cpp @@ -11,9 +11,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(stobject); SysTrayIconHandlers_t g_IconHandlers [] = { - { Volume_Init, Volume_Shutdown, Volume_Update, Volume_Message } + { Volume_Init, Volume_Shutdown, Volume_Update, Volume_Message }, + { Power_Init, Power_Shutdown, Power_Update, Power_Message } }; -const int g_NumIcons = _countof(g_IconHandlers); +const int g_NumIcons = _countof(g_IconHandlers); CSysTray::CSysTray() {} CSysTray::~CSysTray() {} @@ -79,11 +80,11 @@ HRESULT CSysTray::UpdateIcons() return S_OK; } -HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult) { for (int i = 0; i < g_NumIcons; i++) { - HRESULT hr = g_IconHandlers[i].pfnMessage(this, uMsg, wParam, lParam); + HRESULT hr = g_IconHandlers[i].pfnMessage(this, uMsg, wParam, lParam, lResult); if (FAILED(hr)) return hr; @@ -225,7 +226,7 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM TRACE("SysTray message received %u (%08p %08p)\n", uMsg, wParam, lParam); - hr = ProcessIconMessage(uMsg, wParam, lParam); + hr = ProcessIconMessage(uMsg, wParam, lParam, lResult); if (FAILED(hr)) return FALSE; diff --git a/reactos/dll/shellext/stobject/csystray.h b/reactos/dll/shellext/stobject/csystray.h index 4eea6d0d7adde..04f7c1e292015 100644 --- a/reactos/dll/shellext/stobject/csystray.h +++ b/reactos/dll/shellext/stobject/csystray.h @@ -4,7 +4,7 @@ * FILE: dll/shellext/stobject/csystray.h * PURPOSE: Systray shell service object * PROGRAMMERS: Robert Naumann - David Quintana + * David Quintana */ #pragma once @@ -37,7 +37,7 @@ class CSysTray : HRESULT InitIcons(); HRESULT ShutdownIcons(); HRESULT UpdateIcons(); - HRESULT ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + HRESULT ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult); HRESULT InitNetShell(); HRESULT ShutdownNetShell(); diff --git a/reactos/dll/shellext/stobject/power.cpp b/reactos/dll/shellext/stobject/power.cpp new file mode 100644 index 0000000000000..612810571c585 --- /dev/null +++ b/reactos/dll/shellext/stobject/power.cpp @@ -0,0 +1,185 @@ +/* + * PROJECT: ReactOS system libraries + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/shellext/stobject/power.cpp + * PURPOSE: Power notification icon handler + * PROGRAMMERS: Eric Kohl + * David Quintana + */ + +#include "precomp.h" + +#include +#include + +#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) +#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) + +WINE_DEFAULT_DEBUG_CHANNEL(stobject); + +//static HICON g_hIconBattery = NULL; +static HICON g_hIconAC = NULL; + +static BOOL g_IsRunning = FALSE; + + +HRESULT STDMETHODCALLTYPE Power_Init(_In_ CSysTray * pSysTray) +{ + WCHAR strTooltip[128]; + + TRACE("Power_Init\n"); + +// g_hIconBattery = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BATTERY)); + g_hIconAC = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BATTERY)); + + + HICON icon; +// if (g_IsMute) +// icon = g_hIconBattery; +// else + icon = g_hIconAC; + + LoadStringW(g_hInstance, IDS_PWR_AC, strTooltip, _countof(strTooltip)); + + g_IsRunning = TRUE; + + return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_POWER, icon, strTooltip); +} + +HRESULT STDMETHODCALLTYPE Power_Update(_In_ CSysTray * pSysTray) +{ +// BOOL PrevState; + + TRACE("Power_Update\n"); + +#if 0 + PrevState = g_IsMute; + Volume_IsMute(); + + if (PrevState != g_IsMute) + { + WCHAR strTooltip[128]; + HICON icon; + if (g_IsMute) { + icon = g_hIconMute; + LoadStringW(g_hInstance, IDS_VOL_MUTED, strTooltip, _countof(strTooltip)); + } + else { + icon = g_hIconVolume; + LoadStringW(g_hInstance, IDS_VOL_VOLUME, strTooltip, _countof(strTooltip)); + } + + return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_POWER, icon, strTooltip); + } + else + { + return S_OK; + } +#endif + return S_OK; +} + +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() +{ + ShellExecuteW(NULL, NULL, L"powercfg.cpl", NULL, NULL, SW_SHOWNORMAL); +} + +static void _ShowContextMenu(CSysTray * pSysTray) +{ + WCHAR strOpen[128]; + + LoadStringW(g_hInstance, IDS_PWR_PROPERTIES, strOpen, _countof(strOpen)); + + HMENU hPopup = CreatePopupMenu(); + AppendMenuW(hPopup, MF_STRING, IDS_PWR_PROPERTIES, strOpen); + + DWORD flags = TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_BOTTOMALIGN; + DWORD msgPos = GetMessagePos(); + + SetForegroundWindow(pSysTray->GetHWnd()); + DWORD id = TrackPopupMenuEx(hPopup, flags, + GET_X_LPARAM(msgPos), GET_Y_LPARAM(msgPos), + pSysTray->GetHWnd(), NULL); + + DestroyMenu(hPopup); + + switch (id) + { + case IDS_PWR_PROPERTIES: + _RunPower(); + break; + } +} + +HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult) +{ + TRACE("Power_Message uMsg=%d, wParam=%x, lParam=%x\n", uMsg, wParam, lParam); + + switch (uMsg) + { + case WM_USER + 220: + TRACE("Power_Message: WM_USER+220\n"); + if (wParam == 1) + { + if (lParam == FALSE) + return Power_Init(pSysTray); + else + return Power_Shutdown(pSysTray); + } + return S_FALSE; + + case WM_USER + 221: + TRACE("Power_Message: WM_USER+221\n"); + if (wParam == 1) + { + lResult = (LRESULT)g_IsRunning; + return S_OK; + } + return S_FALSE; + + case ID_ICON_POWER: + Power_Update(pSysTray); + + switch (lParam) + { + case WM_LBUTTONDOWN: + break; + + case WM_LBUTTONUP: + TRACE("TODO: display power options!\n"); + break; + + case WM_LBUTTONDBLCLK: + _RunPower(); + break; + + case WM_RBUTTONDOWN: + break; + + case WM_RBUTTONUP: + _ShowContextMenu(pSysTray); + + case WM_RBUTTONDBLCLK: + break; + + case WM_MOUSEMOVE: + break; + } + return S_OK; + + default: + TRACE("Power_Message received for unknown ID %d, ignoring.\n"); + return S_FALSE; + } + + return S_FALSE; +} diff --git a/reactos/dll/shellext/stobject/precomp.h b/reactos/dll/shellext/stobject/precomp.h index 368fb4914298c..66790be94b465 100644 --- a/reactos/dll/shellext/stobject/precomp.h +++ b/reactos/dll/shellext/stobject/precomp.h @@ -39,13 +39,14 @@ extern HINSTANCE g_hInstance; #define ID_ICON_VOLUME (WM_APP + 0x4CB) +#define ID_ICON_POWER (WM_APP + 0x4CC) #include "csystray.h" typedef HRESULT(STDMETHODCALLTYPE * PFNSTINIT) (_In_ CSysTray * pSysTray); typedef HRESULT(STDMETHODCALLTYPE * PFNSTSHUTDOWN) (_In_ CSysTray * pSysTray); typedef HRESULT(STDMETHODCALLTYPE * PFNSTUPDATE) (_In_ CSysTray * pSysTray); -typedef HRESULT(STDMETHODCALLTYPE * PFNSTMESSAGE) (_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam); +typedef HRESULT(STDMETHODCALLTYPE * PFNSTMESSAGE) (_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult); struct SysTrayIconHandlers_t { @@ -63,4 +64,9 @@ extern const int g_NumIcons; 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); +extern HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult); + +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); diff --git a/reactos/dll/shellext/stobject/volume.cpp b/reactos/dll/shellext/stobject/volume.cpp index 57d9a5d678531..f848468af19bd 100644 --- a/reactos/dll/shellext/stobject/volume.cpp +++ b/reactos/dll/shellext/stobject/volume.cpp @@ -26,7 +26,8 @@ DWORD g_muteControlID; UINT g_mmDeviceChange; -BOOL g_IsMute = FALSE; +static BOOL g_IsMute = FALSE; +static BOOL g_IsRunning = FALSE; static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray) { @@ -161,6 +162,8 @@ HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray * pSysTray) Volume_IsMute(); + g_IsRunning = TRUE; + HICON icon; if (g_IsMute) icon = g_hIconMute; @@ -184,11 +187,13 @@ HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray) { WCHAR strTooltip[128]; HICON icon; - if (g_IsMute) { + if (g_IsMute) + { icon = g_hIconMute; LoadStringW(g_hInstance, IDS_VOL_MUTED, strTooltip, _countof(strTooltip)); } - else { + else + { icon = g_hIconVolume; LoadStringW(g_hInstance, IDS_VOL_VOLUME, strTooltip, _countof(strTooltip)); } @@ -205,6 +210,8 @@ HRESULT STDMETHODCALLTYPE Volume_Shutdown(_In_ CSysTray * pSysTray) { TRACE("Volume_Shutdown\n"); + g_IsRunning = FALSE; + return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_VOLUME, NULL, NULL); } @@ -256,40 +263,70 @@ static void _ShowContextMenu(CSysTray * pSysTray) } } -HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam) +HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult) { if (uMsg == g_mmDeviceChange) return Volume_OnDeviceChange(pSysTray, wParam, lParam); - if (uMsg != ID_ICON_VOLUME) - { - TRACE("Volume_Message received for unknown ID %d, ignoring.\n"); - return S_FALSE; - } - - TRACE("Volume_Message uMsg=%d, w=%x, l=%x\n", uMsg, wParam, lParam); - - Volume_Update(pSysTray); - - switch (lParam) + switch (uMsg) { - case WM_LBUTTONDOWN: - break; - case WM_LBUTTONUP: - TRACE("TODO: display volume slider\n"); - break; - case WM_LBUTTONDBLCLK: - _RunVolume(); - break; - case WM_RBUTTONDOWN: - break; - case WM_RBUTTONUP: - _ShowContextMenu(pSysTray); - case WM_RBUTTONDBLCLK: - break; - case WM_MOUSEMOVE: - break; + case WM_USER + 220: + TRACE("Volume_Message: WM_USER+220\n"); + if (wParam == 4) + { + if (lParam == FALSE) + return Volume_Init(pSysTray); + else + return Volume_Shutdown(pSysTray); + } + return S_FALSE; + + case WM_USER + 221: + TRACE("Volume_Message: WM_USER+221\n"); + if (wParam == 4) + { + lResult = (LRESULT)g_IsRunning; + return S_OK; + } + return S_FALSE; + + case ID_ICON_VOLUME: + TRACE("Volume_Message uMsg=%d, w=%x, l=%x\n", uMsg, wParam, lParam); + + Volume_Update(pSysTray); + + switch (lParam) + { + case WM_LBUTTONDOWN: + break; + + case WM_LBUTTONUP: + TRACE("TODO: display volume slider\n"); + break; + + case WM_LBUTTONDBLCLK: + _RunVolume(); + break; + + case WM_RBUTTONDOWN: + break; + + case WM_RBUTTONUP: + _ShowContextMenu(pSysTray); + break; + + case WM_RBUTTONDBLCLK: + break; + + case WM_MOUSEMOVE: + break; + } + return S_OK; + + default: + TRACE("Volume_Message received for unknown ID %d, ignoring.\n"); + return S_FALSE; } - return S_OK; + return S_FALSE; }