mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 12:54:51 +00:00
![David Quintana](/assets/img/avatar_default.png)
[STOBJECT] * Some nitpicking. [SHELL32] * Fix missing null-termination by using proper string literals. svn path=/branches/shell-experiments/; revision=65194
213 lines
4.8 KiB
C++
213 lines
4.8 KiB
C++
/*
|
|
* PROJECT: ReactOS system libraries
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: dll\win32\stobject\csystray.cpp
|
|
* PURPOSE: Systray shell service object implementation
|
|
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(stobject);
|
|
|
|
SysTrayIconHandlers_t g_IconHandlers [] = {
|
|
{ Volume_Init, Volume_Shutdown, Volume_Update, Volume_Message }
|
|
};
|
|
const int g_NumIcons = _countof(g_IconHandlers);
|
|
|
|
const GUID CLSID_SysTray = { 0x35CEC8A3, 0x2BE6, 0x11D2, { 0x87, 0x73, 0x92, 0xE2, 0x20, 0x52, 0x41, 0x53 } };
|
|
|
|
CSysTray::CSysTray() {}
|
|
CSysTray::~CSysTray() {}
|
|
|
|
HRESULT CSysTray::InitIcons()
|
|
{
|
|
TRACE("Initializing Notification icons...\n");
|
|
for (int i = 0; i < g_NumIcons; i++)
|
|
{
|
|
HRESULT hr = g_IconHandlers[i].pfnInit(this);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSysTray::ShutdownIcons()
|
|
{
|
|
TRACE("Shutting down Notification icons...\n");
|
|
for (int i = 0; i < g_NumIcons; i++)
|
|
{
|
|
HRESULT hr = g_IconHandlers[i].pfnShutdown(this);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSysTray::UpdateIcons()
|
|
{
|
|
TRACE("Updating Notification icons...\n");
|
|
for (int i = 0; i < g_NumIcons; i++)
|
|
{
|
|
HRESULT hr = g_IconHandlers[i].pfnUpdate(this);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
for (int i = 0; i < g_NumIcons; i++)
|
|
{
|
|
HRESULT hr = g_IconHandlers[i].pfnMessage(this, uMsg, wParam, lParam);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (hr != S_FALSE)
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip)
|
|
{
|
|
NOTIFYICONDATA nim = { 0 };
|
|
|
|
TRACE("NotifyIcon code=%d, uId=%d, hIcon=%p, szTip=%S\n", code, uId, hIcon, szTip);
|
|
|
|
nim.cbSize = sizeof(NOTIFYICONDATA);
|
|
nim.uFlags = NIF_MESSAGE | NIF_ICON | NIF_STATE | NIF_TIP;
|
|
nim.hIcon = hIcon;
|
|
nim.uID = uId;
|
|
nim.uCallbackMessage = uId;
|
|
nim.dwState = 0;
|
|
nim.dwStateMask = 0;
|
|
nim.hWnd = m_hWnd;
|
|
nim.uVersion = NOTIFYICON_VERSION;
|
|
if (szTip)
|
|
StringCchCopy(nim.szTip, _countof(nim.szTip), szTip);
|
|
else
|
|
nim.szTip[0] = 0;
|
|
BOOL ret = Shell_NotifyIcon(code, &nim);
|
|
return ret ? S_OK : E_FAIL;
|
|
}
|
|
|
|
DWORD WINAPI CSysTray::s_SysTrayThreadProc(PVOID param)
|
|
{
|
|
CSysTray * st = (CSysTray*) param;
|
|
return st->SysTrayThreadProc();
|
|
}
|
|
|
|
HRESULT CSysTray::SysTrayMessageLoop()
|
|
{
|
|
BOOL ret;
|
|
MSG msg;
|
|
|
|
while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0)
|
|
{
|
|
if (ret < 0)
|
|
break;
|
|
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSysTray::SysTrayThreadProc()
|
|
{
|
|
WCHAR strFileName[MAX_PATH];
|
|
GetModuleFileNameW(g_hInstance, strFileName, MAX_PATH);
|
|
HMODULE hLib = LoadLibraryW(strFileName);
|
|
|
|
CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
|
|
|
|
Create(NULL);
|
|
|
|
HRESULT ret = SysTrayMessageLoop();
|
|
|
|
CoUninitialize();
|
|
|
|
FreeLibraryAndExitThread(hLib, ret);
|
|
}
|
|
|
|
HRESULT CSysTray::CreateSysTrayThread()
|
|
{
|
|
TRACE("CSysTray Init TODO: Initialize tray icon handlers.\n");
|
|
|
|
HANDLE hThread = CreateThread(NULL, 0, s_SysTrayThreadProc, this, 0, NULL);
|
|
|
|
CloseHandle(hThread);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSysTray::DestroySysTrayWindow()
|
|
{
|
|
DestroyWindow();
|
|
hwndSysTray = NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
// *** IOleCommandTarget methods ***
|
|
HRESULT STDMETHODCALLTYPE CSysTray::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CSysTray::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
|
|
{
|
|
if (!IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
|
|
return E_FAIL;
|
|
|
|
switch (nCmdID)
|
|
{
|
|
case OLECMDID_NEW: // init
|
|
return CreateSysTrayThread();
|
|
case OLECMDID_SAVE: // shutdown
|
|
return DestroySysTrayWindow();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (hWnd != m_hWnd)
|
|
return FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
InitIcons();
|
|
SetTimer(1, 2000, NULL);
|
|
return TRUE;
|
|
case WM_TIMER:
|
|
UpdateIcons();
|
|
return TRUE;
|
|
case WM_DESTROY:
|
|
KillTimer(1);
|
|
ShutdownIcons();
|
|
return TRUE;
|
|
}
|
|
|
|
TRACE("SysTray message received %u (%08p %08p)\n", uMsg, wParam, lParam);
|
|
|
|
hr = ProcessIconMessage(uMsg, wParam, lParam);
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
|
|
if (hr == S_FALSE)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|