⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 supergridctrl.cpp

📁 磁盘容量扫描、但界面和程序结构非常不错
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// SuperGridCtrl.cpp : implementation file
//

#include "stdafx.h"
//#include "SuperGrid.h"
#include "SuperGridCtrl.h"
//#include "ListEditCtrl.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/*

    SuperGrid, YALC (yet another listview control) 

	Written by me(Allan Nielsen), that is .. if the code works :)
		mailto:winallan@post10.tele.dk

    Modified by David Yuheng Zhao 

	Copyright (c) 1998.

	If you find bugs, please notify me and I'll contact the author who wrote the darn thing :)
	
    You may use it, abuse it, redistribute it, in any way you desire, but
	if you choose to use this control in any commercial or non commercial application then please 
	send me an email letting me know, makes me :) . 
	

	HISTORY (that's new allright)

	what's new since last update: 4 dec. 1998.
	
				- MeasureItem now uses current font	
				- Combobox support in CItemInfo				
				  see the ShowList in MySuperGrid.h/cpp, PreTranslateMessage functions
				  and the file ComboInListView.cpp/h
                - function to indicate the precens of a combobox it draws a down arrow ..see DrawComboBox
				  the idea came from Robert Bouwens. :)
				- in file TestTreeDlg.cpp:  due to the MeasureItem message-reflection	
				  the listctrl is now created in the CDialog::OnCreate function and later on resized
				- LVIS_DROPHILITED support when dragging items
				- Support for LVS_EX_CHECKBOXES	  
				- Added some examples on how to print preview selected item(or at least to get some information from of the grid)
				  the sample is in the CMySuperGrid.h/cpp which is derived from CSuperGridCtrl it shows you
				  how to initalize the grid, sort items, search for items and subitems, select and delete thems
				- added virtual GetIcon function to set your default icon handler for a listview index.
				- added virtual GetCellRGB() to set the color for current selected cell
				- renamed CTreeNode to CTreeItem, sorry ;-(
				- the nested class CTreeItem has been stripped down to nothing but simple (struct)data members
				  only servering as a linked list of lists now :-)
				- well.. moved all the importent stuff from CTreeItem to CSuperGridCtrl e.g
				  all operations on a CTreeItem now resides in the CSuperGridCtrl, much more OO-like ;-)
				- added Quicksort function
				- got rid of TheOpenCloseThing function.
				- added virtual function OnUpdateListViewItem..called when ever an Item is about to be updated
				- added virtual function OnControlLButtonDown...called when ever LButtondown in a cell
				- added virtual function CreateDragImageEx...

	 WHAT'S UP :
				- Clipboard support
				- Better documentation :)
				- Ole drag/drop...instead of the current one.
				- Peace on earth.
				- service pack 2 for VC++ 6.0 :=|
				- move/resize the edit or the combobox when resizing in CView
				- no more support for VC++ 5.0 :)

*/

CString CItemInfo::GetSubItem(int iSubItem)
{
	if (m_pFolder == NULL)
		return CString("");

	return m_pFolder -> GetItemText(iSubItem+1);
}

CString CItemInfo::GetItemText(void)
{
	if (m_pFolder == NULL)
		return CString("");

	return m_pFolder -> GetItemText(0);
}
/////////////////////////////////////////////////////////////////////////////
// CSuperGridCtrl
CSuperGridCtrl::CSuperGridCtrl()
{
	m_cxImage = m_cyImage = m_bIsDragging = m_CurSubItem = 0;
	m_pRoot=NULL;
    m_nDragTarget=m_nDragItem = -1;
}


CSuperGridCtrl::~CSuperGridCtrl()
{
	if(m_pRoot!=NULL)
	{
		if(GetData(m_pRoot)!=NULL)
			delete GetData(m_pRoot);
		delete m_pRoot;
		m_pRoot = NULL;
	}
}


BEGIN_MESSAGE_MAP(CSuperGridCtrl, CListCtrl)
	//{{AFX_MSG_MAP(CSuperGridCtrl)
	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
	ON_WM_CREATE()
	ON_WM_HSCROLL()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_TIMER()
	ON_WM_VSCROLL()
	ON_WM_LBUTTONUP()
	ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnListKeydown)
	ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBegindrag)
	ON_WM_MEASUREITEM_REFLECT()
	ON_WM_DRAWITEM_REFLECT()
	ON_WM_RBUTTONDOWN()
	ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemchanged)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSuperGridCtrl message handlers


//WHEN USING VC++5.0 
void CSuperGridCtrl::IE4StyleEx(DWORD dwNewStyle)
{
	DWORD dwStyle = ::SendMessage(m_hWnd,LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
	dwStyle |= dwNewStyle;
	::SendMessage(m_hWnd,LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
}


BOOL CSuperGridCtrl::PreCreateWindow(CREATESTRUCT& cs) 
{
	cs.style |= LVS_REPORT | LVS_SINGLESEL | LVS_SHAREIMAGELISTS | LVS_OWNERDRAWFIXED | LVS_SHOWSELALWAYS;	
	return CListCtrl::PreCreateWindow(cs);
}



int CSuperGridCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CListCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;

	return 0;
}



#define OFFSET_FIRST	2 
#define OFFSET_OTHER	6
void CSuperGridCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	if (lpDrawItemStruct->CtlType != ODT_LISTVIEW)
        return;

	if(lpDrawItemStruct->itemAction == ODA_DRAWENTIRE)
	{
		HIMAGELIST himl = (HIMAGELIST)::SendMessage(m_hWnd, LVM_GETIMAGELIST, (WPARAM)(int)(LVSIL_SMALL), 0L);
		if(himl==NULL)
		{
			ASSERT(FALSE);
			return;
		}

		LV_ITEM lvi;
		static _TCHAR szBuff[MAX_PATH];
		LPCTSTR pszText;
	
		int nItem = lpDrawItemStruct->itemID;
		CRect rcItem(lpDrawItemStruct->rcItem);

		lvi.mask= LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_INDENT | LVIF_PARAM; 
		lvi.iItem = nItem;
		lvi.iSubItem=0;
		lvi.pszText=szBuff;
		lvi.cchTextMax=sizeof(szBuff);
		lvi.stateMask=0xFFFF;		
		GetItem(&lvi);

		CTreeItem *pSelItem = (CTreeItem*)lpDrawItemStruct->itemData;
		

		CRect rcLabel;
		GetItemRect(nItem, rcLabel, LVIR_LABEL);
		
		CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
		ASSERT(pDC);
		

		CRect rcClipBox;
		pDC->GetClipBox(rcClipBox);

		COLORREF crBackground, crText;
		
		if (lpDrawItemStruct->itemState & ODS_SELECTED)
		{
			// Set the text background and foreground colors
			crBackground = GetSysColor (COLOR_HIGHLIGHT);
			crText = GetSysColor (COLOR_HIGHLIGHTTEXT);
		}
		else
		{
			// Set the text background and foreground colors to the standard window
			// colors
			crBackground = GetSysColor (COLOR_WINDOW);
			crText = GetSysColor (COLOR_WINDOWTEXT);
		}

		//Get current Icon, you have overridden this I hope :-)
		int iImage = GetIcon(pSelItem);
		if(iImage!=-1)
		{
			LV_ITEM lvItem;				
			lvItem.mask =  LVIF_IMAGE;
			lvItem.iImage = iImage;
			lvItem.iItem = nItem;
			lvItem.iSubItem = 0;
			SetItem(&lvItem);
			lvi.iImage = iImage; 
		}

		CRect rc;
		GetItemRect(nItem, rc, LVIR_BOUNDS);

		CRect rcIcon;
		GetItemRect(nItem, rcIcon, LVIR_ICON);
		//Draw Current image
		int nOffset = (rcItem.Height() - m_cyImage)/2;
		int nY = rcItem.bottom - m_cyImage - nOffset;
		int nWidth = m_cxImage;//def icon size
		//do not draw icon out side 1.st column.
		if(rc.left + GetIndent(pSelItem) * m_cxImage + m_cxImage  > GetColumnWidth(0)-2/*looks better -2*/)
			nWidth = (rc.left +  GetIndent(pSelItem) * m_cxImage + m_cxImage ) - GetColumnWidth(0);

		UINT uiFlags = ILD_TRANSPARENT;

		if( GetItemState(nItem, LVIF_STATE) & LVIS_DROPHILITED)//if dragging show a SelectDropTarget alike effect :)
			uiFlags |= ILD_BLEND50;
		
		if((nWidth=m_cxImage-nWidth) >-1)//calc width of icon
		ImageList_DrawEx(himl, lvi.iImage, pDC->m_hDC,  
						 rc.left + (GetIndent(pSelItem) * m_cxImage), 
						 nY, 
						 nWidth,	
						 m_cyImage,
						 CLR_DEFAULT, 
						 CLR_DEFAULT, 
						 uiFlags);

		DrawTreeItem(pDC, pSelItem, nItem, rc);

		//Draw selection bar (erase old selection too)
		pDC->SetBkColor(crBackground);
		CRect rcClip = lpDrawItemStruct->rcItem;
		rcClip.left += GetIndent(pSelItem) * m_cxImage + m_cxImage + 2;
		if(rcClip.left > GetColumnWidth(0))
			rcClip.left = GetColumnWidth(0);
		//fill background color
		ExtTextOut(pDC->GetSafeHdc(), 0, 0, ETO_OPAQUE, rcClip, NULL, 0, NULL);

		if (lpDrawItemStruct->itemState & ODS_SELECTED)
		{
			CRect rect;
			GetItemRect(nItem, rect, LVIR_LABEL);
			rect.DeflateRect(2,2);
			pDC->DrawFocusRect(rect);
		}

		//if checkbox style
		UINT nStateImageMask = lvi.state & LVIS_STATEIMAGEMASK;
		if (nStateImageMask)
		{
			int nImage = (nStateImageMask>>12) - 1;
			CImageList *pImageList = GetImageList(LVSIL_STATE);
			if (pImageList)
			{
				int cxIcon,cyIcon=0;
				ImageList_GetIconSize(pImageList->m_hImageList, &cxIcon, &cyIcon);
				if(rc.left + (GetIndent(pSelItem) * m_cxImage) + m_cxImage + cxIcon < GetColumnWidth(0))
					pImageList->Draw(pDC, nImage,CPoint(rc.left + (GetIndent(pSelItem) * m_cxImage) + cxIcon, nY), ILD_TRANSPARENT);
			}
		}

	
		//draw 1. item	
		GetItemRect(nItem, rcItem, LVIR_LABEL);
		pszText = MakeShortString(pDC, szBuff, rcItem.right - rcItem.left, 2*OFFSET_FIRST);
		rcLabel = rcItem;
		rcLabel.left+=OFFSET_FIRST;
		rcLabel.right-=OFFSET_FIRST;
		
		pDC->SetBkColor (crBackground);
		pDC->SetTextColor (crText);
		pDC->DrawText(pszText,-1, rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_EXTERNALLEADING);

		//draw subitems..I guess this is standard code.
		LV_COLUMN lvc;
		lvc.mask = LVCF_FMT | LVCF_WIDTH;
		for(int nColumn=1; GetColumn(nColumn, &lvc); nColumn++)
		{
			rcItem.left=rcItem.right;
			rcItem.right+=lvc.cx;
			if (rcItem.left < rcClipBox.right && rcItem.right > rcClipBox.left && rcItem.right > rcItem.left)
			{
				pDC->SetBkColor(crBackground);
				pDC->SetTextColor(crText);
				int nRetLen = GetItemText(nItem, nColumn, szBuff, sizeof(szBuff));
				if(nRetLen==0)
					pszText=NULL;
				else
					pszText=MakeShortString(pDC,szBuff,rcItem.right-rcItem.left,2*OFFSET_OTHER);

				UINT nJustify=DT_LEFT;

				if(pszText==szBuff)
				{
					switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
					{
					case LVCFMT_RIGHT:
						nJustify=DT_RIGHT;
						break;
					case LVCFMT_CENTER:
						nJustify=DT_CENTER;
						break;
					default:
						break;
					}
				}
				rcLabel=rcItem;
				rcLabel.left+=OFFSET_OTHER;
				rcLabel.right-=OFFSET_OTHER;
				if(pszText!=NULL)
					pDC->DrawText(pszText,-1,rcLabel, nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_EXTERNALLEADING);
			}//if
			//draw down arrow if combobox regardless of rcClipBox rgn
			if (lpDrawItemStruct->itemState & ODS_SELECTED)
				DrawComboBox(pDC, pSelItem, nItem, nColumn);
		}//for
	}//ODA_DRAWENTIRE
}



void CSuperGridCtrl::DrawComboBox(CDC* pDC, CTreeItem *pSelItem, int nItem, int nColumn)
{
	CItemInfo* pInfo = GetData(pSelItem);
	/*CItemInfo::CONTROLTYPE ctrlType;
	if(pInfo->GetControlType(nColumn-1, ctrlType))
	{
		if(ctrlType==pInfo->CONTROLTYPE::combobox) 
		{
			CRect rect;
			#if _MSC_VER >= 1200
				GetSubItemRect(nItem, nColumn, LVIR_BOUNDS, rect);
			#else
				// Get the column offset	
				int offset = 0;	
				for( int i = 0; i < nColumn; i++)
				   offset += GetColumnWidth(i);	
				GetItemRect(nItem, &rect, LVIR_BOUNDS);
				// Get Column alignment	
				LV_COLUMN lvcol;
				lvcol.mask = LVCF_FMT;
				GetColumn(nColumn, &lvcol);
				rect.left += offset;
				rect.right = rect.left + GetColumnWidth(nColumn);
			#endif
			rect.left=rect.right - GetSystemMetrics(SM_CYVSCROLL);
			pDC->DrawFrameControl(rect, DFC_SCROLL, DFCS_SCROLLDOWN);
		}
	}*/
}


//this piece of code is borrowed from the wndproc.c file in the odlistvw.exe example from MSDN and was converted to mfc-style
void CSuperGridCtrl::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
    if (lpMeasureItemStruct->CtlType != ODT_LISTVIEW)
        return;
	TEXTMETRIC tm;
	CClientDC dc(this);	
	CFont* pFont = GetFont();
	CFont* pOldFont = dc.SelectObject(pFont);	
	dc.GetTextMetrics(&tm);
	int nItemHeight = tm.tmHeight + tm.tmExternalLeading;
	lpMeasureItemStruct->itemHeight = nItemHeight + 4;//or should I go for max(nItemheight+4, m_cxImage+2);
}



//the basic rutine making the ... thing snatched it from some tedious code example some where in MSDN call odlistvw.exe
LPCTSTR CSuperGridCtrl::MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset)
{
	static const _TCHAR szThreeDots[]=_T("...");

	int nStringLen=lstrlen(lpszLong);

	if(nStringLen==0 || pDC->GetTextExtent(lpszLong,nStringLen).cx + nOffset < nColumnLen)
		return(lpszLong);

	static _TCHAR szShort[MAX_PATH];

	lstrcpy(szShort,lpszLong);
	int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;

	for(int i=nStringLen-1; i > 0; i--)
	{
		szShort[i]=0;
		if(pDC->GetTextExtent(szShort,i).cx + nOffset + nAddLen < nColumnLen)
			break;
	}
	lstrcat(szShort,szThreeDots);
	return(szShort);
}



void CSuperGridCtrl::OnListKeydown(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
	switch(pLVKeyDow->wVKey)
	{
		case VK_SPACE: 
			break;

		case VK_DELETE: 
			break;
		case VK_MULTIPLY:
			{  
				int nIndex = GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); 
				int nScrollIndex=0;
				if(nIndex!=-1)
				{
					CWaitCursor wait;
					SetRedraw(0);
					CTreeItem *pParent = reinterpret_cast<CTreeItem*>(GetItemData(nIndex));
					int nScroll=0;
					ExpandAll(pParent, nScroll);
					SetRedraw(1);
					RedrawItems(nIndex, nScroll);
					EnsureVisible(nIndex, TRUE);
					
				 }
			 }break;

		case VK_ADD:
		case VK_RIGHT:
			{
					int nIndex = GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); 
					if(nIndex!=-1)
					{
						CWaitCursor wait;
						CTreeItem *pSelItem = reinterpret_cast<CTreeItem*>(GetItemData(nIndex));
						int nScrollIndex = Expand(pSelItem, nIndex);
						CRect rc;
						GetItemRect(nIndex,rc,LVIR_BOUNDS);
						InvalidateRect(rc);
						UpdateWindow();
						EnsureVisible(nIndex,1);
					}

			}break;


		case VK_SUBTRACT:
		case VK_LEFT:
			{
				int nIndex = GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); 
				if(nIndex!=-1)
				{
					CWaitCursor wait;
					CTreeItem *pSelItem = reinterpret_cast<CTreeItem*>(GetItemData(nIndex));
					Collapse(pSelItem);
					CRect rc;
					GetItemRect(nIndex, rc, LVIR_BOUNDS);
					InvalidateRect(rc);
					UpdateWindow();
				}
			}break;
		default :break;
	}

	//Update owner
	//GetOwner()->SendMessage(WM_FOLDER_SELECTED, 0,0);

	*pResult = 0;
}

/*BOOL CSuperGridCtrl::HitTestOnSign(CPoint point, LVHITTESTINFO& ht)
{
	ht.pt = point;
	// Test for which subitem was clicked.
	ListView_SubItemHitTest(m_hWnd, &ht);
	int nItem = HitTest(point);
	//if(ht.iItem!=-1)
	{
		//first hittest on checkbox
		//"we need additional checking in owner-draw mode
		// because we only get LVHT_ONITEM" End quote Microsoft(c) :{
		//BOOL bHit = FALSE;
		

		CTreeItem* pItem = reinterpret_cast<CTreeItem*>(GetItemData(nItem));
		if(pItem!=NULL)
		{/*
			if(bHit)//if checkbox
			{
				//yes I know..have to maintain to sets of checkstates here...
				//one for listview statemask and one for CTreeItem..but its located here so no harm done
				GetCheck(ht.iItem) ? SetCheck(ht.iItem, FALSE) : SetCheck(ht.iItem);
				CItemInfo *pInfo = GetData(pItem);
				pInfo->GetCheck()?pInfo->SetCheck(0):pInfo->SetCheck(1);
			}*/
			//if haschildren and clicked on + or - then expand/collapse
		/*	if(ItemHasChildren(pItem))
			{
				//hittest on the plus/sign "button" 
				//see the DrawTreeItem for setting up the plus/sign "button" 
				CRect rcBounds;
				GetItemRect(nItem, rcBounds, LVIR_BOUNDS);

				int nHalfImage = (m_cxImage>>1);
				SIZE right_bottom = {(m_cxImage>>1)+2+1, (m_cyImage>>1)+2+1};//once again ANDY: the '+ 1' is to center the [+] or [-] 
				int left = rcBounds.left + GetIndent(pItem) * m_cxImage - (m_cxImage>>1);
				int top = (rcBounds.top + nHalfImage) - (right_bottom.cy >> 1);
				POINT left_top = {left -  (right_bottom.cx >> 1), top};
				CRect rc(left_top, right_bottom);

				if(rc.PtInRect(point))
				{
					SetRedraw(0);
					int nScrollIndex=0;
					if(IsCollapsed(pItem))
						nScrollIndex = Expand(pItem, nItem);
					else
					   Collapse(pItem);
					SetRedraw(1);
					CRect rc;
					GetItemRect(nItem, rc, LVIR_BOUNDS);
					InvalidateRect(rc);
					UpdateWindow();
					EnsureVisible(nScrollIndex,1);
					return 0;
				}
			}//has kids
		}//pItem!=NULL
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -