Files
reactos/reactos/subsys/system/explorer/taskbar/traynotify.cpp
T
Martin Fuchs cd813d619c set work area size
svn path=/trunk/; revision=5749
2003-08-22 13:27:58 +00:00

287 lines
5.9 KiB
C++

/*
* Copyright 2003 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//
// Explorer clone
//
// traynotify.cpp
//
// Martin Fuchs, 22.08.2003
//
#include "../utility/utility.h"
#include "../explorer.h"
//#include "taskbar.h" // for _desktop_bar
#include "traynotify.h"
NotifyIconIndex::NotifyIconIndex(NOTIFYICONDATA* pnid)
{
_hWnd = pnid->hWnd;
_uID = pnid->uID;
// special handling for windows task manager
if ((int)_uID < 0)
_uID = 0;
}
NotifyIconIndex::NotifyIconIndex()
{
_hWnd = 0;
_uID = 0;
}
NotifyInfo::NotifyInfo()
{
_idx = -1;
_hIcon = 0;
_dwState = 0;
_uCallbackMessage = 0;
}
NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid)
{
_hWnd = pnid->hWnd;
_uID = pnid->uID;
if (pnid->uFlags & NIF_MESSAGE)
_uCallbackMessage = pnid->uCallbackMessage;
if (pnid->uFlags & NIF_ICON)
_hIcon = pnid->hIcon;
#ifdef NIF_STATE // currently (as of 21.08.2003) missing in MinGW headers
if (pnid->uFlags & NIF_STATE)
_dwState = (_dwState&~pnid->dwStateMask) | (pnid->dwState&pnid->dwStateMask);
#endif
return *this;
}
NotifyArea::NotifyArea(HWND hwnd)
: super(hwnd)
{
// _desktop_bar = NULL;
_next_idx = 0;
}
LRESULT NotifyArea::Init(LPCREATESTRUCT pcs)
{
if (super::Init(pcs))
return 1;
ClientRect clnt(_hwnd);
// create clock window
_hwndClock = Window::Create(WINDOW_CREATOR(ClockWindow), 0,
BtnWindowClass(CLASSNAME_CLOCKWINDOW,CS_DBLCLKS), NULL, WS_CHILD|WS_VISIBLE,
clnt.right-(CLOCKWINDOW_WIDTH+1), 1, CLOCKWINDOW_WIDTH, clnt.bottom-2, _hwnd);
return 0;
}
LRESULT NotifyArea::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{
switch(nmsg) {
case WM_PAINT:
Paint();
break;
default:
if (nmsg>=WM_MOUSEFIRST && nmsg<=WM_MOUSELAST) {
NotifyIconSet::iterator found = IconHitTest(Point(lparam));
if (found != _sorted_icons.end()) {
NotifyInfo& entry = const_cast<NotifyInfo&>(*found); // Why does GCC 3.3 need this additional const_cast ?!
// Notify the message the the owner if it's still alive
if (IsWindow(entry._hWnd)) //TODO: We could check this regularly for all icons by using WM_TIMER to prevent for hanging icons
PostMessage(entry._hWnd, entry._uCallbackMessage, entry._uID, nmsg);
else {
// delete icons without owner window
if (_icon_map.erase(entry))
Refresh();
}
}
}
return super::WndProc(nmsg, wparam, lparam);
}
return 0;
}
LRESULT NotifyArea::ProcessTrayNotification(int notify_code, NOTIFYICONDATA* pnid)
{
switch(notify_code) {
case NIM_ADD:
case NIM_MODIFY:
if ((int)pnid->uID >= 0) { //TODO: fix for windows task manager
NotifyInfo& entry = _icon_map[pnid] = pnid;
// a new entry?
if (entry._idx == -1)
entry._idx = ++_next_idx;
Refresh();
}
break;
case NIM_DELETE:
if (_icon_map.erase(pnid))
Refresh();
break;
#if NOTIFYICON_VERSION>=3 // currently (as of 21.08.2003) missing in MinGW headers
case NIM_SETFOCUS:
break;
case NIM_SETVERSION:
break;
#endif
}
return 0;
}
void NotifyArea::Refresh()
{
_sorted_icons.clear();
// sort icon infos by display index
for(NotifyIconMap::const_iterator it=_icon_map.begin(); it!=_icon_map.end(); ++it)
_sorted_icons.insert(it->second);
InvalidateRect(_hwnd, NULL, TRUE); // refresh icon display
UpdateWindow(_hwnd);
}
void NotifyArea::Paint()
{
PaintCanvas canvas(_hwnd);
// draw icons
int x = 2;
int y = 2;
for(NotifyIconSet::const_iterator it=_sorted_icons.begin(); it!=_sorted_icons.end(); ++it)
{
const NotifyInfo& entry = *it;
#ifdef NIF_STATE // currently (as of 21.08.2003) missing in MinGW headers
if (!(entry._dwState & NIS_HIDDEN))
#endif
{
DrawIconEx(canvas, x, y, entry._hIcon, 16, 16, 0, 0, DI_NORMAL);
x += 20;
}
}
}
/// search for a icon at a given client coordinate position
NotifyIconSet::iterator NotifyArea::IconHitTest(const POINT& pos)
{
if (pos.y<2 || pos.y>=2+16)
return _sorted_icons.end();
NotifyIconSet::iterator it = _sorted_icons.begin();
int x = 2;
for(; it!=_sorted_icons.end(); ++it)
{
NotifyInfo& entry = const_cast<NotifyInfo&>(*it); // Why does GCC 3.3 need this additional const_cast ?!
#ifdef NIF_STATE // currently (as of 21.08.2003) missing in MinGW headers
if (!(entry._dwState & NIS_HIDDEN))
#endif
{
if (pos.x>=x && pos.x<x+16)
break;
x += 20;
}
}
return it;
}
ClockWindow::ClockWindow(HWND hwnd)
: super(hwnd)
{
*_time = _T('\0');
FormatTime();
SetTimer(hwnd, 0, 1000, NULL);
}
LRESULT ClockWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{
switch(nmsg) {
case WM_PAINT:
Paint();
break;
case WM_TIMER: {
if (FormatTime())
InvalidateRect(_hwnd, NULL, TRUE);
break;}
default:
return super::WndProc(nmsg, wparam, lparam);
}
return 0;
}
bool ClockWindow::FormatTime()
{
SYSTEMTIME systime;
TCHAR buffer[16];
GetLocalTime(&systime);
//_stprintf(buffer, TEXT("%02d:%02d:%02d"), systime.wHour, systime.wMinute, systime.wSecond);
_stprintf(buffer, TEXT("%02d:%02d"), systime.wHour, systime.wMinute);
if (_tcscmp(buffer, _time)) {
_tcscpy(_time, buffer);
return true;
}
return false; // no change
}
void ClockWindow::Paint()
{
PaintCanvas canvas(_hwnd);
BkMode bkmode(canvas, TRANSPARENT);
SelectedFont font(canvas, GetStockFont(ANSI_VAR_FONT));
DrawText(canvas, _time, -1, ClientRect(_hwnd), DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX);
}