/*
Copyright(C) Nishant Sivakumar. All rights reserved.
URLs - http://blog.voidnish.com and http://www.voidnish.com
Contact : nish@voidnish.com
*/
// ShellTrayInfoView.cpp : implementation of the CShellTrayInfoView class
//
#include "stdafx.h"
#include "ShellTrayInfo.h"
#include "ProcessData.h"
#include "ShellTrayInfoView.h"
#include ".\shelltrayinfoview.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CShellTrayInfoView
IMPLEMENT_DYNCREATE(CShellTrayInfoView, CListView)
BEGIN_MESSAGE_MAP(CShellTrayInfoView, CListView)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_DBLCLK_ICON, OnDoubleClick)
ON_COMMAND(ID_LCLK_ICON, OnLeftClick)
ON_COMMAND(ID_RCLK_ICON, OnRightClick)
ON_COMMAND(ID_ICON_UP, OnMoveLeft)
ON_COMMAND(ID_ICON_DOWN, OnMoveRight)
ON_COMMAND(ID_REFRESH_LIST, OnRefresh)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnNMCustomdraw)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnNMDblclk)
END_MESSAGE_MAP()
// CShellTrayInfoView construction/destruction
CShellTrayInfoView::CShellTrayInfoView() :
m_hHiddenFont(NULL),
m_hRegularFont(NULL)
{
// TODO: add construction code here
}
CShellTrayInfoView::~CShellTrayInfoView()
{
DeleteObject(m_hHiddenFont);
DeleteObject(m_hRegularFont);
}
BOOL CShellTrayInfoView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CListView::PreCreateWindow(cs);
}
void CShellTrayInfoView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
LOGFONT lf = {0};
GetFont()->GetLogFont(&lf);
m_hRegularFont = CreateFontIndirect(&lf);
lf.lfItalic = TRUE;
m_hHiddenFont = CreateFontIndirect(&lf);
m_hTrayWnd = FindTrayToolbarWindow();
m_Image16List.Create(16,16,ILC_COLOR24,16,16);
GetListCtrl().SetImageList(&m_Image16List, LVSIL_SMALL);
m_Image16List.Add(LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME)));
GetListCtrl().InsertColumn(0, _T("Icon"), LVCFMT_LEFT, 50);
GetListCtrl().InsertColumn(1, _T("Associated ToolTip"), LVCFMT_LEFT,400);
GetListCtrl().InsertColumn(2, _T("Process Path"), LVCFMT_LEFT, 500);
GetListCtrl().ModifyStyle(0,LVS_REPORT|LVS_SINGLESEL);
GetListCtrl().SetExtendedStyle(LVS_EX_FULLROWSELECT);
ListTrayIcons();
}
// CShellTrayInfoView diagnostics
#ifdef _DEBUG
void CShellTrayInfoView::AssertValid() const
{
CListView::AssertValid();
}
void CShellTrayInfoView::Dump(CDumpContext& dc) const
{
CListView::Dump(dc);
}
#endif //_DEBUG
// CShellTrayInfoView message handlers
void CShellTrayInfoView::ListTrayIcons(int defindex /*= 0*/)
{
m_TifoVec.erase(m_TifoVec.begin(), m_TifoVec.end());
GetListCtrl().DeleteAllItems();
for(int i=1; i<m_Image16List.GetImageCount(); i++)
{
m_Image16List.Remove(i);
}
if(m_hTrayWnd == NULL)
return;
DWORD dwTrayPid;
GetWindowThreadProcessId(m_hTrayWnd, &dwTrayPid);
int count = (int)::SendMessage(m_hTrayWnd, TB_BUTTONCOUNT, 0, 0);
CProcessData<TBBUTTON> data(dwTrayPid);
TBBUTTON tb = {0};
TRAYDATA tray = {0};
TrayItemInfo tifo = {0};
for(int i=0; i<count; i++)
{
::SendMessage(m_hTrayWnd, TB_GETBUTTON, i, (LPARAM)data.GetData());
data.ReadData(&tb);
data.ReadData<TRAYDATA>(&tray,(LPCVOID)tb.dwData);
DWORD dwProcessId = 0;
GetWindowThreadProcessId(tray.hwnd,&dwProcessId);
tifo.sProcessPath = GetFilenameFromPid(dwProcessId);
wchar_t TipChar;
wchar_t sTip[1024] = {0};
wchar_t* pTip = (wchar_t*)tb.iString;
if(!(tb.fsState&TBSTATE_HIDDEN))
{
int x = 0;
do
{
if(x == 1023)
{
wcscpy(sTip,L"[ToolTip was either too long or not set]");
break;
}
data.ReadData<wchar_t>(&TipChar, (LPCVOID)pTip++);
}while(sTip[x++] = TipChar);
}
else
wcscpy(sTip,L"[Hidden Icon]");
USES_CONVERSION;
tifo.sTip = W2T(sTip);
tifo.hwnd = tray.hwnd;
tifo.uCallbackMessage = tray.uCallbackMessage;
tifo.uID = tray.uID;
tifo.bVisible = !(tb.fsState & TBSTATE_HIDDEN);
int iconindex = 0;
ICONINFO iinfo;
if(GetIconInfo(tray.hIcon,&iinfo) != 0)
{
iconindex = m_Image16List.Add(tray.hIcon);
}
LVITEM lv = {0};
lv.iItem = GetListCtrl().GetItemCount();
lv.iSubItem = 0;
lv.mask = LVIF_IMAGE;
lv.iImage = iconindex;
m_TifoVec.push_back(tifo);
int index = GetListCtrl().InsertItem(&lv);
GetListCtrl().SetItemText(index,1,tifo.sTip);
GetListCtrl().SetItemText(index,2,tifo.sProcessPath);
}
if( (count>0) && (defindex>=0) && (defindex<count) )
GetListCtrl().SetItemState(defindex,
LVIS_FOCUSED|LVIS_SELECTED,
LVIS_FOCUSED|LVIS_SELECTED);
}
void CShellTrayInfoView::OnEditCopy()
{
POSITION pos = GetListCtrl().GetFirstSelectedItemPosition();
if(pos)
{
int index = GetListCtrl().GetNextSelectedItem(pos);
OpenClipboard();
EmptyClipboard();
HGLOBAL hText = GlobalAlloc(GMEM_MOVEABLE, sizeof TCHAR * 512);
LPTSTR pStr = (LPTSTR)GlobalLock(hText);
_stprintf(pStr, _T("Tray Tip : %s\r\nOwner : %s"),
m_TifoVec[index].sTip, m_TifoVec[index].sProcessPath);
GlobalUnlock(hText);
SetClipboardData(CF_TEXT, hText);
CloseClipboard();
}
}
void CShellTrayInfoView::OnDoubleClick()
{
PostMessageToTrayIcon(WM_LBUTTONDBLCLK);
}
void CShellTrayInfoView::OnLeftClick()
{
PostMessageToTrayIcon(WM_LBUTTONDOWN);
PostMessageToTrayIcon(WM_LBUTTONUP);
}
void CShellTrayInfoView::OnRightClick()
{
PostMessageToTrayIcon(WM_RBUTTONDOWN);
PostMessageToTrayIcon(WM_RBUTTONUP);
}
void CShellTrayInfoView::PostMessageToTrayIcon(LPARAM lParam)
{
POSITION pos = GetListCtrl().GetFirstSelectedItemPosition();
if(pos)
{
int index = GetListCtrl().GetNextSelectedItem(pos);
::PostMessage(m_TifoVec[index].hwnd,
m_TifoVec[index].uCallbackMessage,
m_TifoVec[index].uID,
lParam);
}
}
void CShellTrayInfoView::OnMoveLeft()
{
POSITION pos = GetListCtrl().GetFirstSelectedItemPosition();
if(pos)
{
int index = GetListCtrl().GetNextSelectedItem(pos);
if(index > 0)
{
::SendMessage(m_hTrayWnd, TB_MOVEBUTTON, index, index-1);
ListTrayIcons(index-1);
}
}
}
void CShellTrayInfoView::OnMoveRight()
{
POSITION pos = GetListCtrl().GetFirstSelectedItemPosition();
if(pos)
{
int index = GetListCtrl().GetNextSelectedItem(pos);
if(index < (GetListCtrl().GetItemCount()-1))
{
::SendMessage(m_hTrayWnd, TB_MOVEBUTTON, index, index+1);
ListTrayIcons(index+1);
}
}
}
void CShellTrayInfoView::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
*pResult = CDRF_DODEFAULT;
if(pNMCD->dwDrawStage == CDDS_PREPAINT)
{
*pResult = CDRF_NOTIFYITEMDRAW;
}
else if(pNMCD->dwDrawStage == CDDS_ITEMPREPAINT)
{
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
if(!m_TifoVec[pNMCD->dwItemSpec].bVisible)
{
pLVCD->clrText = RGB(120,120,120);
SelectObject(pNMCD->hdc,m_hHiddenFont);
}
else
{
pLVCD->clrText = RGB(0,0,130);
SelectObject(pNMCD->hdc,m_hRegularFont);
}
*pResult = CDRF_NEWFONT;
}
}
void CShellTrayInfoView::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItem = (LPNMITEMACTIVATE)pNMHDR;
if(pNMItem->iItem != -1)
PostMessageToTrayIcon(WM_LBUTTONDBLCLK);
*pResult = 0;
}
void CShellTrayInfoView::OnRefresh()
{
ListTrayIcons();
}