Skip to content

Commit

Permalink
[STOBJECT]
Browse files Browse the repository at this point in the history
Implement code to show and hide the power and volume icons in the notification area aka systray.
Control panel applications send WM_USR+220 messages to the systray window in order to show or hide an icon in the systray. The wParam parameter identifies the icon: 1=power, 4=volume. The lParam parameter indicates the new icon status: 0:show, 1:hide.
Control panel applications also send WM_USER+221 messages to the systray window in order to retrieve the current status of a systray icon. The wParam parameter identifies the icon, just like in the WM_SUER+220 messages. The lParam parameter is ignored. The return value indicates the status of the icon: 1:visible, 0:hidden.

svn path=/trunk/; revision=74225
  • Loading branch information
EricKohl committed Mar 23, 2017
1 parent b8b7eed commit a926541
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 41 deletions.
1 change: 1 addition & 0 deletions reactos/dll/shellext/stobject/CMakeLists.txt
Expand Up @@ -21,6 +21,7 @@ add_library(stobject SHARED
csystray.cpp
stobject.cpp
stobject.rc
power.cpp
volume.cpp
${CMAKE_CURRENT_BINARY_DIR}/stobject.def)

Expand Down
11 changes: 6 additions & 5 deletions reactos/dll/shellext/stobject/csystray.cpp
Expand Up @@ -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() {}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions reactos/dll/shellext/stobject/csystray.h
Expand Up @@ -4,7 +4,7 @@
* FILE: dll/shellext/stobject/csystray.h
* PURPOSE: Systray shell service object
* PROGRAMMERS: Robert Naumann
David Quintana <gigaherz@gmail.com>
* David Quintana <gigaherz@gmail.com>
*/
#pragma once

Expand Down Expand Up @@ -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();
Expand Down
185 changes: 185 additions & 0 deletions 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 <eric.kohl@reactos.org>
* David Quintana <gigaherz@gmail.com>
*/

#include "precomp.h"

#include <mmsystem.h>
#include <mmddk.h>

#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;
}
10 changes: 8 additions & 2 deletions reactos/dll/shellext/stobject/precomp.h
Expand Up @@ -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
{
Expand All @@ -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);

0 comments on commit a926541

Please sign in to comment.