Esempio n. 1
0
//------------------------------------------------------------------------
//! Called by the framework when a drop operation is to occur, where the
//! origin is the CGridListCtrlEx itself
//!
//! @param pDataObject Points to the data object containing the data that can be dropped
//! @param dropEffect The effect that the user chose for the drop operation (DROPEFFECT_COPY, DROPEFFECT_MOVE, DROPEFFECT_LINK)
//! @param point Contains the current location of the cursor in client coordinates.
//! @return Nonzero if the drop is successful; otherwise 0
//------------------------------------------------------------------------
BOOL CGridListCtrlGroups::OnDropSelf(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
{
	// Internal drag (Move rows to other group)
	int nRow, nCol;
	CellHitTest(point, nRow, nCol);
	if (!IsGroupViewEnabled())
		return CGridListCtrlEx::MoveSelectedRows(nRow);

	if (GetStyle() & LVS_OWNERDATA)
		return false;

	int nGroupId = nRow!=-1 ? GetRowGroupId(nRow) : GroupHitTest(point);
	if (nGroupId==-1)
		return FALSE;
		
	if (MoveSelectedRows(nGroupId))
	{
		if (nRow!=-1)
		{
			EnsureVisible(nRow, FALSE);
			SetFocusRow(nRow);
		}
	}
	return TRUE;
}
Esempio n. 2
0
//------------------------------------------------------------------------
//! Checks if it is possible to modify the collapse state of a group.
//! This is only possible in Windows Vista.
//!
//! @return Groups can be collapsed (true / false)
//------------------------------------------------------------------------
BOOL CGridListCtrlGroups::IsGroupStateEnabled()
{
	if (!IsGroupViewEnabled())
		return FALSE;

	return CheckOSVersion(0x0600);
}
Esempio n. 3
0
//------------------------------------------------------------------------
//! Changes the row sorting in regard to the specified column
//!
//! @param nCol The index of the column
//! @param bAscending Should the arrow be up or down 
//! @return True / false depending on whether sort is possible
//------------------------------------------------------------------------
bool CGridListCtrlGroups::SortColumn(int nCol, bool bAscending)
{
	CWaitCursor waitCursor;

	if (IsGroupViewEnabled())
	{
		SetRedraw(FALSE);

		GroupByColumn(nCol);

		// Cannot use GetGroupInfo during sort
		PARAMSORT paramsort(m_hWnd, nCol, bAscending, GetColumnTrait(nCol));
		for(int nRow=0 ; nRow < GetItemCount() ; ++nRow)
		{
			int nGroupId = GetRowGroupId(nRow);
			if (nGroupId!=-1 && paramsort.m_GroupNames.FindKey(nGroupId)==-1)
				paramsort.m_GroupNames.Add(nGroupId, GetGroupHeader(nGroupId));
		}

		SetRedraw(TRUE);
		Invalidate(FALSE);

		// Avoid bug in CListCtrl::SortGroups() which differs from ListView_SortGroups
		if (!ListView_SortGroups(m_hWnd, SortFuncGroup, &paramsort))
			return false;
	}
	else
	{
		if (!CGridListCtrlEx::SortColumn(nCol, bAscending))
			return false;
	}

	return true;
}
Esempio n. 4
0
//------------------------------------------------------------------------
//! Create a group for each unique values within a column
//!
//! @param nCol The index of the column
//! @return Succeeded in creating the group
//------------------------------------------------------------------------
BOOL CGridListCtrlGroups::GroupByColumn(int nCol)
{
	CWaitCursor waitCursor;

	SetSortArrow(-1, false);

	SetRedraw(FALSE);

	RemoveAllGroups();

	EnableGroupView( GetItemCount() > 0 );

	if (IsGroupViewEnabled())
	{
		CSimpleMap<CString,CSimpleArray<int> > groups;

		// Loop through all rows and find possible groups
		for(int nRow=0; nRow<GetItemCount(); ++nRow)
		{
			CString cellText = GetItemText(nRow, nCol);

			int nGroupId = groups.FindKey(cellText);
			if (nGroupId==-1)
			{
				CSimpleArray<int> rows;
				groups.Add(cellText, rows);
				nGroupId = groups.FindKey(cellText);
			}
			groups.GetValueAt(nGroupId).Add(nRow);
		}

		// Look through all groups and assign rows to group
		for(int nGroupId = 0; nGroupId < groups.GetSize(); ++nGroupId)
		{
			const CSimpleArray<int>& groupRows = groups.GetValueAt(nGroupId);
			DWORD dwState = LVGS_NORMAL;
#ifdef LVGS_COLLAPSIBLE
			if (IsGroupStateEnabled())
				dwState = LVGS_COLLAPSIBLE;
#endif
			VERIFY( InsertGroupHeader(nGroupId, nGroupId, groups.GetKeyAt(nGroupId), dwState) != -1);

			for(int groupRow = 0; groupRow < groupRows.GetSize(); ++groupRow)
			{
				VERIFY( SetRowGroupId(groupRows[groupRow], nGroupId) );
			}
		}

		SetRedraw(TRUE);
		Invalidate(FALSE);
		return TRUE;
	}

	SetRedraw(TRUE);
	Invalidate(FALSE);
	return FALSE;
}
BOOL CFeedIcoItemListCtrl::IsGroupStateEnabled()
{
	if (!IsGroupViewEnabled())
		return FALSE;

	if (thePrefs.GetWindowsVersion() >= _WINVER_VISTA_ )
		return TRUE;

	return FALSE;
}
Esempio n. 6
0
//------------------------------------------------------------------------
//! WM_CONTEXTMENU message handler to show popup menu when mouse right
//! click is used (or SHIFT+F10 on the keyboard)
//!
//! @param pWnd Handle to the window in which the user right clicked the mouse
//! @param point Position of the cursor, in screen coordinates, at the time of the mouse click.
//------------------------------------------------------------------------
void CGridListCtrlGroups::OnContextMenu(CWnd* pWnd, CPoint point)
{
	if ( IsGroupViewEnabled() )
	{
		if (pWnd!=GetHeaderCtrl())
		{
			if (point.x!=-1 && point.y!=-1)
			{
				CPoint pt = point;
				ScreenToClient(&pt);

				int nGroupId = GroupHitTest(pt);
				if (nGroupId!=-1)
				{
					OnContextMenuGroup(pWnd, point, nGroupId);
					return;
				}
			}
		}
	}
	CGridListCtrlEx::OnContextMenu(pWnd, point);
}
Esempio n. 7
0
//------------------------------------------------------------------------
//! Override this method to change the context menu when activating context
//! menu for the column headers
//!
//! @param pWnd Handle to the window in which the user right clicked the mouse
//! @param point Position of the cursor, in screen coordinates, at the time of the mouse click.
//! @param nCol The index of the column
//------------------------------------------------------------------------
void CGridListCtrlGroups::OnContextMenuHeader(CWnd* pWnd, CPoint point, int nCol)
{
	// Only Windows XP and above supports groups
	if (!IsCommonControlsEnabled())
	{
		CGridListCtrlEx::OnContextMenuHeader(pWnd, point, nCol);
		return;
	}

	// Show context-menu with the option to show hide columns
	CMenu menu;
	VERIFY( menu.CreatePopupMenu() );

	if (nCol!=-1)
	{
		// Retrieve column-title
		const CString& columnTitle = GetColumnHeading(nCol);
		menu.AppendMenu(MF_STRING, 3, CString(_T("Group by: ")) + columnTitle);
	}

	if (IsGroupViewEnabled())
	{
		menu.AppendMenu(MF_STRING, 4, _T("Disable grouping"));
	}

	CString title_editor;
	if (HasColumnEditor(nCol, title_editor))
	{
		menu.AppendMenu(MF_STRING, 1, static_cast<LPCTSTR>(title_editor));
	}

	CString title_picker;
	if (HasColumnPicker(title_picker))
	{
		menu.AppendMenu(MF_STRING, 2, static_cast<LPCTSTR>(title_picker));		
	}
	else
	{
		if (menu.GetMenuItemCount()>0)
			menu.AppendMenu(MF_SEPARATOR, 0, _T(""));

		InternalColumnPicker(menu, 6);
	}

	CSimpleArray<CString> profiles;
	InternalColumnProfileSwitcher(menu, GetColumnCount() + 7, profiles);

	CString title_resetdefault;
	if (HasColumnDefaultState(title_resetdefault))
	{
		if (profiles.GetSize()==0)
			menu.AppendMenu(MF_SEPARATOR, 0, _T(""));
		menu.AppendMenu(MF_STRING, 5, title_resetdefault);
	}

	// Will return zero if no selection was made (TPM_RETURNCMD)
	int nResult = menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD, point.x, point.y, this, 0);
	switch(nResult)
	{
		case 0: break;
		case 1:	OpenColumnEditor(nCol); break;
		case 2: OpenColumnPicker(); break;
		case 3: GroupByColumn(nCol); break;
		case 4:
		{
			// Very strange problem when disabling group mode, then scrollbars are not updated
			// If placed in the bottom and disables group mode, then suddenly there is a strange offset
			//	- Quick fix scroll to top, and then fix scroll bars afterwards
			int pos = GetScrollPos(SB_VERT);
			EnsureVisible(0,FALSE);
			RemoveAllGroups();
			EnableGroupView(FALSE);
			Scroll(CSize(0,pos));
		} break;
		case 5: ResetColumnDefaultState(); break;
		default:
		{
			int nCol = nResult-6;
			if (nCol < GetColumnCount())
			{
				ShowColumn(nCol, !IsColumnVisible(nCol));
			}
			else
			{
				int nProfile = nResult-GetColumnCount()-7;
				SwichColumnProfile(profiles[nProfile]);
			}
		} break;
	}
}
Esempio n. 8
0
//------------------------------------------------------------------------
//! Find the group-id below the given point
//!
//! @param point Mouse position
//! @return ID of the group
//------------------------------------------------------------------------
int CGridListCtrlGroups::GroupHitTest(const CPoint& point)
{
	if (!IsGroupViewEnabled())
		return -1;

	if (HitTest(point)!=-1)
		return -1;

	if (IsGroupStateEnabled())
	{
#if _WIN32_WINNT >= 0x0600
#ifdef ListView_HitTestEx
#ifdef LVHT_EX_GROUP
#ifdef ListView_GetGroupInfoByIndex
		LVHITTESTINFO lvhitinfo = {0};
		lvhitinfo.pt = point;
		ListView_HitTestEx(m_hWnd, &lvhitinfo);
		if ((lvhitinfo.flags & LVHT_EX_GROUP)==0)
			return -1;

		LVGROUP lg = {0};
		lg.cbSize = sizeof(lg);
		lg.mask = LVGF_GROUPID;
		VERIFY( ListView_GetGroupInfoByIndex(m_hWnd, lvhitinfo.iGroup, &lg) );
		return lg.iGroupId;
#endif
#endif
#endif
#endif
	}

	if (IsGroupStateEnabled())
	{
		// Running on Vista or newer, but compiled without _WIN32_WINNT >= 0x0600
#ifndef LVM_GETGROUPINFOBYINDEX
#define LVM_GETGROUPINFOBYINDEX   (LVM_FIRST + 153)
#endif
#ifndef LVM_GETGROUPCOUNT
#define LVM_GETGROUPCOUNT         (LVM_FIRST + 152)
#endif
#ifndef LVM_GETGROUPRECT
#define LVM_GETGROUPRECT          (LVM_FIRST + 98)
#endif
#ifndef LVGGR_HEADER
#define LVGGR_HEADER		      (1)
#endif

		LRESULT groupCount = SNDMSG((m_hWnd), LVM_GETGROUPCOUNT, (WPARAM)0, (LPARAM)0);
		if (groupCount <= 0)
			return -1;
		for(int i = 0 ; i < groupCount; ++i)
		{
			LVGROUP lg = {0};
			lg.cbSize = sizeof(lg);
			lg.mask = LVGF_GROUPID;

			VERIFY( SNDMSG((m_hWnd), LVM_GETGROUPINFOBYINDEX, (WPARAM)(i), (LPARAM)(&lg)) );

			CRect rect(0,LVGGR_HEADER,0,0);
			VERIFY( SNDMSG((m_hWnd), LVM_GETGROUPRECT, (WPARAM)(lg.iGroupId), (LPARAM)(RECT*)(&rect)) );

			if (rect.PtInRect(point))
				return lg.iGroupId;
		}
		// Don't try other ways to find the group
		return -1;
	}

	// We require that each group contains atleast one item
	if (GetItemCount()==0)
		return -1;

	// This logic doesn't support collapsible groups
	int nFirstRow = -1;
	CRect gridRect;
	GetWindowRect(&gridRect);
	for(CPoint pt = point ; pt.y < gridRect.bottom ; pt.y += 2)
	{
		nFirstRow = HitTest(pt);
		if (nFirstRow!=-1)
			break;
	}

	if (nFirstRow==-1)
		return -1;

	int nGroupId = GetRowGroupId(nFirstRow);

	// Extra validation that the above row belongs to a different group
	int nAboveRow = GetNextItem(nFirstRow,LVNI_ABOVE);
	if (nAboveRow!=-1 && nGroupId==GetRowGroupId(nAboveRow))
		return -1;

	return nGroupId;
}
BOOL CFeedIcoItemListCtrl::GroupAllFeedsByType(int nType)
{
	if (!IsCommonControlsEnabled())
		return FALSE;

	SetRedraw(FALSE);

	RemoveAllGroups();
	RemoveAllGroupData();
	EnableGroupView( GetItemCount() > 0 );

	if (IsGroupViewEnabled())
	{
		// Loop through all rows and find possible groups
		for(int nItem = 0; nItem < GetItemCount(); nItem++ )
		{
			CString strCatalogName = GetResString( IDS_UNKNOWN );

			CRssFeed* pFeed = (CRssFeed*)GetItemData(nItem);

			if (pFeed == NULL)
				continue;

			if ( pFeed->m_uCatalogId != FeedCatalog::INVALID_CATALOG_ID )
			{
				FeedCatalog & catalog = CFeedCatalogs::GetInstance()[pFeed->m_uCatalogId];
				ASSERT(catalog.m_uId == pFeed->m_uCatalogId);
				ASSERT(catalog.IsLeaf());

				FeedCatalog * catalogParent;
				if (catalog.m_pParent != NULL)
				{
					catalogParent = catalog.m_pParent;
					strCatalogName = catalogParent->m_strName;
				}
			}

			int nGroupId = m_mapGroups.FindKey(strCatalogName);
			if (nGroupId == -1)
			{
				CSimpleArray<int> nItems;
				m_mapGroups.Add(strCatalogName, nItems);
				nGroupId = m_mapGroups.FindKey(strCatalogName);
			}

			//必须添加不重复数据
			if (m_mapGroups.GetValueAt(nGroupId).Find(nItem) == -1)
			{
				m_mapGroups.GetValueAt(nGroupId).Add(nItem);
			}
			
		}

		// Look through all groups and assign rows to group
		for(int nGroupId = 0; nGroupId < m_mapGroups.GetSize(); nGroupId++)
		{
			const CSimpleArray<int>& groupRows = m_mapGroups.GetValueAt(nGroupId);
			DWORD dwState = LVGS_NORMAL;

#ifdef LVGS_COLLAPSIBLE
			if (IsGroupStateEnabled())
				dwState = LVGS_COLLAPSIBLE;
#endif

			VERIFY( InsertTypeGroup(nGroupId, nGroupId, m_mapGroups.GetKeyAt(nGroupId), dwState) != -1);

			for(int groupRow = 0; groupRow < groupRows.GetSize(); ++groupRow)
			{
				VERIFY( SetItemGroupId(groupRows[groupRow], nGroupId) );
			}
		}

	}

	SetRedraw(TRUE);

	Invalidate(TRUE);
	return FALSE;
}
Esempio n. 10
0
BOOL CFeedIcoItemListCtrl::GroupFeedByType(int nIndex, int nType)
{
	if (!IsCommonControlsEnabled())
		return FALSE;

	SetRedraw(FALSE);

	EnableGroupView(TRUE);
	if (IsGroupViewEnabled())
	{
		CString cellText = GetResString( IDS_UNKNOWN );
		bool	bNew = false;//Is new Group?

		CRssFeed* pFeed = (CRssFeed*)GetItemData(nIndex);
		
		if (pFeed == NULL)
			return FALSE;

		if ( pFeed->m_uCatalogId != FeedCatalog::INVALID_CATALOG_ID )
		{
			FeedCatalog & catalog = CFeedCatalogs::GetInstance()[pFeed->m_uCatalogId];
			ASSERT(catalog.m_uId == pFeed->m_uCatalogId);
			ASSERT(catalog.IsLeaf());

			FeedCatalog * catalogParent;
			if (catalog.m_pParent != NULL)
			{
				catalogParent = catalog.m_pParent;
				cellText = catalogParent->m_strName;
			}
		}

		int nGroupId = m_mapGroups.FindKey(cellText);
		if (nGroupId == -1)
		{
			CSimpleArray<int> nItems;
			m_mapGroups.Add(cellText, nItems);
			nGroupId = m_mapGroups.FindKey(cellText);

			bNew = true;
		}

		//必须添加不重复数据
		if (m_mapGroups.GetValueAt(nGroupId).Find(nIndex) == -1)
		{
			m_mapGroups.GetValueAt(nGroupId).Add(nIndex);
		}

		if (bNew)//new Group
		{
			DWORD dwState = LVGS_NORMAL;

			#ifdef LVGS_COLLAPSIBLE
					if (IsGroupStateEnabled())
						dwState = LVGS_COLLAPSIBLE;
			#endif

			//InsertTypeGroup(nGroupId, nGroupId, cellText, dwState);
			VERIFY(InsertTypeGroup(nGroupId, nGroupId, cellText, dwState) != -1);
		}

		VERIFY( SetItemGroupId(nIndex, nGroupId) );
	}

	SetRedraw(TRUE);
	Invalidate(TRUE);
	

	return FALSE;
}