WindowsXP-SP1/admin/hmonitor/hmlistview/hmlist.cpp
2020-09-30 16:53:49 +02:00

670 lines
16 KiB
C++

// HMList.cpp : implementation file
//
#include "stdafx.h"
#include "HMListView.h"
#include "HMList.h"
#include "SortClass.h"
#include "HMListViewCtl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
const int _IDM_HEADER_CONTEXTMENU_BASE = 1500;
//-----------------------------------------------------------------------------------
// IA64 : We add SetItemDataPtr and GetItemDataPtr since the old mechanism
// of storing a pointer case to a DWORD or long can not be used
// in Win64 because the high order bits of the pointer are lost on
// conversion.
//*************************************************
// SetItemDataPtr
//*************************************************
BOOL CHMList::SetItemDataPtr(int nItem, void* ptr)
{
if ((nItem < 0) || (nItem > (GetItemCount() - 1)))
return FALSE;
m_mapSortItems[nItem] = ptr;
return TRUE;
}
//*************************************************
// GetItemDataPtr
//*************************************************
void* CHMList::GetItemDataPtr(int nItem) const
{
if ((nItem < 0) || (nItem > (GetItemCount() - 1)))
return NULL;
void* p=NULL;
if( ! m_mapSortItems.Lookup(nItem,(void*&)p) )
return NULL;
return p;
}
//------------------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// CHMList
/////////////////////////////////////////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////////////////////////////////////////
CHMList::CHMList()
{
m_bSorting = false;
m_lColumnSortStates = 0;
m_lColumnClicked = -1;
}
CHMList::~CHMList()
{
}
/////////////////////////////////////////////////////////////////////////////
// Sorting Operations
/////////////////////////////////////////////////////////////////////////////
void CHMList::SortColumn( int iSubItem, bool bSortingMultipleColumns )
{
int iNumCombinedSortedCols = GetNumCombinedSortedColumns();
m_bSorting = true;
if( bSortingMultipleColumns )
{
if( NotInCombinedSortedColumnList( iSubItem ) )
{
m_aCombinedSortedColumns[ iNumCombinedSortedCols++ ] = iSubItem;
}
else
{
MoveItemInCombinedSortedListToEnd( iSubItem );
}
for( int i = iNumCombinedSortedCols - 1; i >= 0 ; i-- )
{
SORT_STATE ssEachItem = GetItemSortState( m_aCombinedSortedColumns[i] );
if( iNumCombinedSortedCols - 1 != i )
{
ssEachItem = (SORT_STATE)!ssEachItem;
}
CSortClass csc(this, m_aCombinedSortedColumns[i] );
csc.Sort( ssEachItem ? true : false );
if( i == iNumCombinedSortedCols - 1 )
{ //Only swap the last column's sort order.
m_headerctrl.SetSortImage( m_aCombinedSortedColumns[i], ssEachItem ? true : false );
SetItemSortState( m_aCombinedSortedColumns[i] , (SORT_STATE)!ssEachItem );
}
}
}
else
{
m_headerctrl.RemoveAllSortImages();
EmptyArray(m_aCombinedSortedColumns);
m_aCombinedSortedColumns[ 0 ] = iSubItem;
SORT_STATE ssEachItem = GetItemSortState( iSubItem );
CSortClass csc(this, iSubItem );
csc.Sort( ssEachItem ? true : false );
m_headerctrl.SetSortImage( iSubItem, ssEachItem ? true : false );
SetItemSortState( iSubItem , (SORT_STATE)!ssEachItem );
}
m_bSorting = false;
}
const int CHMList::GetNumCombinedSortedColumns() const
{
for( int i = 0; i < MAX_COLUMNS; i++ )
{
if( m_aCombinedSortedColumns[i] == -1 )
{
return i;
}
}
return MAX_COLUMNS;
}
bool CHMList::NotInCombinedSortedColumnList(int iItem) const
{
int iNumCombinedSortedColumns = GetNumCombinedSortedColumns();
for( int i = 0; i < iNumCombinedSortedColumns; i++ )
{
if( m_aCombinedSortedColumns[i] == iItem )
{
return false;
}
}
return true;
}
void CHMList::MoveItemInCombinedSortedListToEnd(int iItem)
{
int iNumCombinedSortedColumns = GetNumCombinedSortedColumns();
int aCombinedSortedColumns[MAX_COLUMNS];
memset( aCombinedSortedColumns, -1, MAX_COLUMNS );
int iItemIndex = FindItemInCombedSortedList( iItem );
if( iItemIndex != -1 )
{
if( iItemIndex > 0 )
{
memcpy( aCombinedSortedColumns, m_aCombinedSortedColumns, iItemIndex * sizeof( int ) );
memcpy( &aCombinedSortedColumns[iItemIndex], &m_aCombinedSortedColumns[iItemIndex + 1], (iNumCombinedSortedColumns - iItemIndex - 1) * sizeof(int) );
}
}
aCombinedSortedColumns[ iNumCombinedSortedColumns - 1 ] = iItem;
memcpy( m_aCombinedSortedColumns, aCombinedSortedColumns, MAX_COLUMNS * sizeof(int) );
for( int i = 0; i < MAX_COLUMNS ; i++ )
{
if( aCombinedSortedColumns[i] == -1 )
break;
}
}
const SORT_STATE CHMList::GetItemSortState( int iItem ) const
{
return (SORT_STATE)((m_lColumnSortStates) & ( 1 << iItem ));
}
void CHMList::SetItemSortState(int iItem, SORT_STATE bSortState)
{
if( bSortState != GetItemSortState( iItem ) )
{
m_lColumnSortStates ^= (1 << iItem);
}
}
void CHMList::EmptyArray( int *pArray )
{
memset( pArray, -1, MAX_COLUMNS );
}
const bool CHMList::IsColumnNumeric( int iCol ) const
{
for( int i = 0; i < m_aNumericColumns.GetSize(); i++ )
{
if( m_aNumericColumns.GetAt( i ) == (UINT)iCol )
{
return true;
}
}
return false;
}
int CHMList::FindItemInCombedSortedList( int iItem )
{
int iNumCombinedSortedColumns = GetNumCombinedSortedColumns();
for( int i = 0; i < iNumCombinedSortedColumns; i++ )
{
if(m_aCombinedSortedColumns[i] == iItem )
{
return i;
}
}
return -1;
}
const int CHMList::IsControlPressed() const
{
return (::GetKeyState( VK_SHIFT ) < 0 );
}
void CHMList::SetFilterType(long lType)
{
CHMListViewCtrl* pCtl = (CHMListViewCtrl*)GetParent();
if( pCtl->IsKindOf(RUNTIME_CLASS(CHMListViewCtrl)) )
{
HDITEM hdItem;
HDTEXTFILTER hdTextFilter;
CString sFilter;
hdTextFilter.pszText = sFilter.GetBuffer(_MAX_PATH);
hdTextFilter.cchTextMax = _MAX_PATH;
ZeroMemory(&hdItem,sizeof(HDITEM));
hdItem.mask = HDI_FILTER;
hdItem.type = HDFT_ISSTRING;
hdItem.pvFilter = &hdTextFilter;
m_headerctrl.GetItem(m_lColumnClicked,&hdItem);
sFilter.ReleaseBuffer();
ZeroMemory(&hdItem,sizeof(HDITEM));
hdItem.mask = HDI_LPARAM;
hdItem.lParam = lType;
m_headerctrl.SetItem(m_lColumnClicked,&hdItem);
LRESULT lResult = 0L;
pCtl->FireFilterChange(m_lColumnClicked,sFilter,lType,&lResult);
}
}
BEGIN_MESSAGE_MAP(CHMList, CListCtrl)
//{{AFX_MSG_MAP(CHMList)
ON_WM_CREATE()
ON_WM_CONTEXTMENU()
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
ON_WM_DESTROY()
ON_COMMAND(ID_HEADERCONTEXT_FILTERBAR, OnHeadercontextFilterbar)
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
ON_NOTIFY(HDN_FILTERCHANGE, 0, OnFilterChange)
ON_NOTIFY(HDN_FILTERBTNCLICK, 0, OnFilterButtonClicked)
ON_COMMAND(ID_FILTERMENU_CONTAINS, OnFiltermenuContains)
ON_COMMAND(ID_FILTERMENU_DOESNOTCONTAIN, OnFiltermenuDoesnotcontain)
ON_COMMAND(ID_FILTERMENU_ENDSWITH, OnFiltermenuEndswith)
ON_COMMAND(ID_FILTERMENU_ISEXACTLY, OnFiltermenuIsexactly)
ON_COMMAND(ID_FILTERMENU_ISNOT, OnFiltermenuIsnot)
ON_COMMAND(ID_FILTERMENU_STARTSWITH, OnFiltermenuStartswith)
ON_COMMAND(ID_FILTERMENU_CLEARFILTER, OnFiltermenuClearfilter)
ON_COMMAND(ID_FILTERMENU_CLEARALLFILTERS, OnFiltermenuClearallfilters)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHMList message handlers
BOOL CHMList::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style = cs.style|LVS_EDITLABELS|LVS_REPORT;
cs.lpszClass = _T("SysListView32");
return CListCtrl::PreCreateWindow(cs);
}
int CHMList::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CListCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
m_headerctrl.SubclassWindow( GetHeaderCtrl()->GetSafeHwnd() );
m_headerctrl.SendMessage(HDM_SETFILTERCHANGETIMEOUT, 0, 1000);
return 0;
}
void CHMList::OnContextMenu(CWnd* pWnd, CPoint point)
{
// Handle right click on the header control
if( pWnd->GetSafeHwnd() == GetHeaderCtrl()->GetSafeHwnd() )
{
CMenu menu;
menu.LoadMenu(IDR_MENU_HEADER_CONTEXT);
CMenu& listcontextmenu = *menu.GetSubMenu(1);
CHeaderCtrl* pHdrCtrl = GetHeaderCtrl();
DWORD dwStyle = GetWindowLong(pHdrCtrl->GetSafeHwnd(),GWL_STYLE);
if( dwStyle & HDS_FILTERBAR )
{
listcontextmenu.CheckMenuItem(ID_HEADERCONTEXT_FILTERBAR,MF_BYCOMMAND|MF_CHECKED);
}
int iCol = 0;
TCHAR szName[255];
LVCOLUMN lvc;
ZeroMemory(&lvc,sizeof(LVCOLUMN));
lvc.mask = LVCF_TEXT|LVCF_WIDTH;
lvc.pszText = szName;
lvc.cchTextMax = 255;
while( GetColumn(iCol,&lvc) )
{
if( lvc.cx > 0 )
{
listcontextmenu.AppendMenu(MF_CHECKED|MF_STRING,_IDM_HEADER_CONTEXTMENU_BASE+iCol,lvc.pszText);
}
else
{
listcontextmenu.AppendMenu(MF_UNCHECKED|MF_STRING,_IDM_HEADER_CONTEXTMENU_BASE+iCol,lvc.pszText);
}
iCol++;
}
listcontextmenu.TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);
listcontextmenu.DestroyMenu();
menu.DestroyMenu();
}
}
void CHMList::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if( IsControlPressed() )
{
SortColumn( pNMListView->iSubItem, MULTI_COLUMN_SORT );
}
else
{
SortColumn( pNMListView->iSubItem, SINGLE_COLUMN_SORT );
}
*pResult = 0;
}
void CHMList::OnDestroy()
{
CListCtrl::OnDestroy();
}
void CHMList::OnHeadercontextFilterbar()
{
// set styles for the header control
CHeaderCtrl* pHdrCtrl = GetHeaderCtrl();
DWORD dwStyle = GetWindowLong(pHdrCtrl->GetSafeHwnd(),GWL_STYLE);
if( dwStyle & HDS_FILTERBAR )
{
dwStyle &= ~HDS_FILTERBAR;
}
else
{
dwStyle |= HDS_FILTERBAR;
}
SetWindowLong(pHdrCtrl->GetSafeHwnd(),GWL_STYLE,dwStyle);
}
BOOL CHMList::OnCommand(WPARAM wParam, LPARAM lParam)
{
WORD wID = LOWORD(wParam);
if( wID >= _IDM_HEADER_CONTEXTMENU_BASE )
{
TCHAR szName[255];
int iCol = wID - _IDM_HEADER_CONTEXTMENU_BASE;
LVCOLUMN lvc;
ZeroMemory(&lvc,sizeof(LVCOLUMN));
lvc.mask = LVCF_TEXT|LVCF_WIDTH;
lvc.cx = 0;
lvc.pszText = szName;
lvc.cchTextMax = 255;
GetColumn(iCol,&lvc);
if( lvc.cx == 0 )
{
CDC dc;
dc.Attach(::GetDC(NULL));
// get the width in pixels of the item
CSize size = dc.GetTextExtent(lvc.pszText);
lvc.cx = size.cx + 50;
HDC hDC = dc.Detach();
::ReleaseDC(NULL,hDC);
}
else
{
lvc.cx = 0;
}
SetColumn(iCol,&lvc);
}
return CListCtrl::OnCommand(wParam, lParam);
}
#pragma warning(disable : 4100)
void CHMList::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
CHMListViewCtrl* pCtl = (CHMListViewCtrl*)GetParent();
if( pCtl->IsKindOf(RUNTIME_CLASS(CHMListViewCtrl)) )
{
POSITION pos = GetFirstSelectedItemPosition();
if( pos )
{
int iSelItem = GetNextSelectedItem(pos);
long lParam = (long)GetItemData(iSelItem);
pCtl->FireListClick(lParam);
}
}
*pResult = 0;
}
void CHMList::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
{
CHMListViewCtrl* pCtl = (CHMListViewCtrl*)GetParent();
if( pCtl->IsKindOf(RUNTIME_CLASS(CHMListViewCtrl)) )
{
POSITION pos = GetFirstSelectedItemPosition();
if( pos )
{
int iSelItem = GetNextSelectedItem(pos);
long lParam = (long)GetItemData(iSelItem);
pCtl->FireListDblClick(lParam);
}
}
*pResult = 0;
}
void CHMList::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
{
CHMListViewCtrl* pCtl = (CHMListViewCtrl*)GetParent();
if( pCtl->IsKindOf(RUNTIME_CLASS(CHMListViewCtrl)) )
{
POSITION pos = GetFirstSelectedItemPosition();
if( pos )
{
int iSelItem = GetNextSelectedItem(pos);
long lParam = (long)GetItemData(iSelItem);
pCtl->FireListRClick(lParam);
}
}
*pResult = 0;
}
void CHMList::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
CHMListViewCtrl* pCtl = (CHMListViewCtrl*)GetParent();
if( pCtl->IsKindOf(RUNTIME_CLASS(CHMListViewCtrl)) )
{
if( pDispInfo->item.pszText )
{
pCtl->FireListLabelEdit(pDispInfo->item.pszText,
(LONG_PTR)pDispInfo->item.lParam,
pResult);
return;
}
}
*pResult = 0;
}
void CHMList::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
CHMListViewCtrl* pCtl = (CHMListViewCtrl*)GetParent();
if( pCtl->IsKindOf(RUNTIME_CLASS(CHMListViewCtrl)) )
{
pCtl->FireListKeyDown(pLVKeyDow->wVKey,
pLVKeyDow->flags,
pResult);
return;
}
*pResult = 0;
}
void CHMList::OnFilterChange(NMHDR* pNMHDR, LRESULT* pResult)
{
NMHEADER *pNMHdr = (NMHEADER*)pNMHDR;
CHMListViewCtrl* pCtl = (CHMListViewCtrl*)GetParent();
if( pCtl->IsKindOf(RUNTIME_CLASS(CHMListViewCtrl)) )
{
if( pCtl->m_bColumnInsertionComplete )
{
CString sFilter;
long lType = -1;
if( pNMHdr->iItem != -1 )
{
HDITEM hdItem;
HDTEXTFILTER hdTextFilter;
hdTextFilter.pszText = sFilter.GetBuffer(_MAX_PATH);
hdTextFilter.cchTextMax = _MAX_PATH;
ZeroMemory(&hdItem,sizeof(HDITEM));
hdItem.mask = HDI_FILTER|HDI_LPARAM;
hdItem.type = HDFT_ISSTRING;
hdItem.pvFilter = &hdTextFilter;
m_headerctrl.GetItem(pNMHdr->iItem,&hdItem);
sFilter.ReleaseBuffer();
lType = (long)hdItem.lParam;
}
pCtl->FireFilterChange(pNMHdr->iItem,sFilter,lType,pResult);
return;
}
}
*pResult = 0;
}
void CHMList::OnFilterButtonClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
NMHDFILTERBTNCLICK *pNMFButtonClick = (NMHDFILTERBTNCLICK*)pNMHDR;
NMHEADER *pNMHdr = (NMHEADER*)pNMHDR;
CHMListViewCtrl* pCtl = (CHMListViewCtrl*)GetParent();
if( pCtl->IsKindOf(RUNTIME_CLASS(CHMListViewCtrl)) )
{
CMenu menu;
menu.LoadMenu(IDR_MENU_HEADER_CONTEXT);
CMenu& filtermenu = *menu.GetSubMenu(2);
HDITEM hdItem;
long lType = 0L;
ZeroMemory(&hdItem,sizeof(HDITEM));
hdItem.mask = HDI_LPARAM;
m_lColumnClicked = pNMHdr->iItem;
m_headerctrl.GetItem(pNMHdr->iItem,&hdItem);
lType = (long)hdItem.lParam;
if( lType & HDFS_CONTAINS )
{
filtermenu.CheckMenuItem(ID_FILTERMENU_CONTAINS,MF_CHECKED|MF_BYCOMMAND);
}
if( lType & HDFS_DOES_NOT_CONTAIN )
{
filtermenu.CheckMenuItem(ID_FILTERMENU_DOESNOTCONTAIN,MF_CHECKED|MF_BYCOMMAND);
}
if( lType & HDFS_STARTS_WITH )
{
filtermenu.CheckMenuItem(ID_FILTERMENU_STARTSWITH,MF_CHECKED|MF_BYCOMMAND);
}
if( lType & HDFS_ENDS_WITH )
{
filtermenu.CheckMenuItem(ID_FILTERMENU_ENDSWITH,MF_CHECKED|MF_BYCOMMAND);
}
if( lType & HDFS_IS )
{
filtermenu.CheckMenuItem(ID_FILTERMENU_ISEXACTLY,MF_CHECKED|MF_BYCOMMAND);
}
if( lType & HDFS_IS_NOT )
{
filtermenu.CheckMenuItem(ID_FILTERMENU_ISNOT,MF_CHECKED|MF_BYCOMMAND);
}
CPoint point;
GetCursorPos(&point);
filtermenu.TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);
filtermenu.DestroyMenu();
menu.DestroyMenu();
ZeroMemory(&hdItem,sizeof(HDITEM));
hdItem.mask = HDI_LPARAM;
m_headerctrl.GetItem(pNMHdr->iItem,&hdItem);
lType = (long)hdItem.lParam;
}
*pResult = 0;
}
#pragma warning(default : 4100)
void CHMList::OnFiltermenuContains()
{
SetFilterType(HDFS_CONTAINS);
}
void CHMList::OnFiltermenuDoesnotcontain()
{
SetFilterType(HDFS_DOES_NOT_CONTAIN);
}
void CHMList::OnFiltermenuEndswith()
{
SetFilterType(HDFS_ENDS_WITH);
}
void CHMList::OnFiltermenuIsexactly()
{
SetFilterType(HDFS_IS);
}
void CHMList::OnFiltermenuIsnot()
{
SetFilterType(HDFS_IS_NOT);
}
void CHMList::OnFiltermenuStartswith()
{
SetFilterType(HDFS_STARTS_WITH);
}
void CHMList::OnFiltermenuClearfilter()
{
Header_ClearFilter(m_headerctrl.GetSafeHwnd(),m_lColumnClicked);
}
void CHMList::OnFiltermenuClearallfilters()
{
Header_ClearAllFilters( m_headerctrl.GetSafeHwnd() );
}