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

📄 listctrlx.cpp

📁 eMule0.44b的原代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "emule.h"
#include "ListCtrlX.h"
#include "ListViewSearchDlg.h"
#include "OtherFunctions.h"
#include "MenuCmds.h"

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


/////////////////////////////////////////////////////////////////////////////
// CListCtrlX

BEGIN_MESSAGE_MAP(CListCtrlX, CListCtrl)
	ON_WM_SYSCOLORCHANGE()
	ON_WM_SETFOCUS()
	ON_WM_DESTROY()
	ON_WM_CREATE()
	ON_WM_INITMENUPOPUP()
	ON_WM_MENUSELECT()
	ON_WM_CONTEXTMENU()
	ON_NOTIFY_EX(HDN_BEGINDRAG, 0, OnHdrBeginDrag)
	ON_NOTIFY_EX(HDN_ENDDRAG, 0, OnHdrEndDrag)
	ON_WM_KEYDOWN()
	ON_MESSAGE(WM_COPY, OnCopy)
END_MESSAGE_MAP()

CListCtrlX::CListCtrlX()
{
	m_pParent = NULL;
	m_pMenu = NULL;
	m_uIDMenu = (UINT)-1;
	m_bRouteMenuCmdsToMainFrame = FALSE;
	m_uIDAccel = (UINT)-1;
	m_hAccel = NULL;
	m_iSortColumn = -1;
	m_uIDHdrImgList = (UINT)-1;
	m_sizeHdrImgListIcon.cx = 0;
	m_sizeHdrImgListIcon.cy = 0;
	m_iHdrImgListImages = 0;
	m_bUseHdrCtrlSortBitmaps = FALSE;
	m_strFindText;
	m_bFindMatchCase = FALSE;
	m_iFindDirection = 1;
	m_iFindColumn = 0;
}

CListCtrlX::~CListCtrlX()
{
}

void CListCtrlX::ReadColumnStats(int iColumns, LCX_COLUMN_INIT* pColumns)
{
	ASSERT( !m_strRegKey.IsEmpty() );
	ReadColumnStats(iColumns, pColumns, m_strRegKey);
}

void CListCtrlX::ReadColumnStats(int iColumns, LCX_COLUMN_INIT* pColumns, LPCTSTR pszSection)
{
	::ReadColumnStats(iColumns, pColumns, pszSection, m_strRegPrefix);

	DWORD dwVal = theApp.GetProfileInt(pszSection, m_strRegPrefix + _T("_SortColumn"), -1);
	m_iSortColumn = (short)LOWORD(dwVal);
	if (m_iSortColumn >= 0 && m_iSortColumn < iColumns)
	{
		LCX_SORT_ORDER eSortOrder = (LCX_SORT_ORDER)(short)HIWORD(dwVal);
		if (eSortOrder == ASCENDING || eSortOrder == DESCENDING)
			pColumns[m_iSortColumn].eSortOrder = eSortOrder;

		if (pColumns[m_iSortColumn].eSortOrder == NONE)
			pColumns[m_iSortColumn].eSortOrder = pColumns[m_iSortColumn].eDfltSortOrder != NONE ? pColumns[m_iSortColumn].eDfltSortOrder : ASCENDING;
	}
	else
		m_iSortColumn = -1;
}

void ReadColumnStats(int iColumns, LCX_COLUMN_INIT* pColumns, LPCTSTR pszSection, LPCTSTR pszPrefix)
{
	for (int iCol = 0; iCol < iColumns; iCol++)
	{
		DWORD dwVal = theApp.GetProfileInt(pszSection, CString(pszPrefix) + pColumns[iCol].pszHeading, -1);
		if (dwVal != (DWORD)-1)
		{
			pColumns[iCol].iWidth = (short)LOWORD(dwVal);
			if ((pColumns[iCol].iOrder = (short)HIWORD(dwVal)) < 0)
				pColumns[iCol].iOrder = 0; // COMCTL chrashes on negative 'iOrder' values!
		}
	}
}

void CListCtrlX::WriteColumnStats(int iColumns, const LCX_COLUMN_INIT* pColumns)
{
	ASSERT( !m_strRegKey.IsEmpty() );
	WriteColumnStats(iColumns, pColumns, m_strRegKey);
}

void CListCtrlX::WriteColumnStats(int iColumns, const LCX_COLUMN_INIT* pColumns, LPCTSTR pszSection)
{
	::WriteColumnStats(*this, iColumns, pColumns, pszSection, m_strRegPrefix);

	DWORD dwVal = MAKELONG(m_iSortColumn, pColumns[m_iSortColumn].eSortOrder);
	theApp.WriteProfileInt(pszSection, m_strRegPrefix + _T("_SortColumn"), dwVal);
}

void WriteColumnStats(CListCtrl& lv, int iColumns, const LCX_COLUMN_INIT* pColumns, LPCTSTR pszSection, LPCTSTR pszPrefix)
{
	for (int iCol = 0; iCol < iColumns; iCol++)
	{
		LVCOLUMN lvc;
		lvc.mask = LVCF_WIDTH | LVCF_ORDER;
		if (lv.GetColumn(iCol, &lvc) && (lvc.cx != pColumns[iCol].iWidth || lvc.iOrder != pColumns[iCol].iOrder))
		{
			DWORD dwVal = MAKELONG(lvc.cx, lvc.iOrder);
			theApp.WriteProfileInt(pszSection, CString(pszPrefix) + pColumns[iCol].pszHeading, dwVal);
		}
	}
}

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

	// If we want to handle the VK_RETURN key, we have to do that via accelerators!
	if (m_uIDAccel != (UINT)-1) {
		m_hAccel = ::LoadAccelerators(AfxGetResourceHandle(), MAKEINTRESOURCE(m_uIDAccel));
		ASSERT(m_hAccel);
	}

	return 0;
}

void CListCtrlX::PreSubclassWindow()
{
	CListCtrl::PreSubclassWindow();

	// If we want to handle the VK_RETURN key, we have to do that via accelerators!
	if (m_uIDAccel != (UINT)-1) {
		m_hAccel = ::LoadAccelerators(AfxGetResourceHandle(), MAKEINTRESOURCE(m_uIDAccel));
		ASSERT(m_hAccel);
	}
}

BOOL CListCtrlX::PreTranslateMessage(MSG *pMsg)
{
	if (m_hAccel != NULL)
	{
		if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
		{
			// If we want to handle the VK_RETURN key, we have to do that via accelerators!
			if (TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
				return TRUE;
		}
	}

	return CListCtrl::PreTranslateMessage(pMsg);
}

void CListCtrlX::CreateColumns(int iColumns, LCX_COLUMN_INIT* pColumns)
{
	InsertColumn(0, _T("Dummy"), LVCFMT_LEFT, 0);
	for (int iCol = 0; iCol < iColumns; iCol++)
	{
		CString strHeading;
		if (pColumns[iCol].uHeadResID)
			strHeading = GetResString(pColumns[iCol].uHeadResID);
		if (strHeading.IsEmpty())
			strHeading = pColumns[iCol].pszHeading;

		int iColWidth;
		if (pColumns[iCol].iWidth >= 0)
		{
			iColWidth = pColumns[iCol].iWidth;
		}
		else
		{
			// Get the 'Optimal Column Width'
			if (pColumns[iCol].pszSample)
			{
				int iWidthSample = GetStringWidth(pColumns[iCol].pszSample);
				int iWidthHeader = GetStringWidth(strHeading);
				iWidthHeader += 30; // if using the COMCTL 6.0 header bitmaps (up/down arrows), we need more space

				iColWidth = 6 + __max(iWidthSample, iWidthHeader) + 6;	// left+right margin
				if (pColumns[iCol].uFormat & LVCFMT_RIGHT) // right-justified text(!)
					iColWidth += 4;
			}
			else
				iColWidth = 0;
		}

		LVCOLUMN lvc;
		lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_FMT | LVCF_SUBITEM;
		lvc.pszText = const_cast<LPTSTR>((LPCTSTR)strHeading);
		lvc.cx = iColWidth;
		lvc.fmt = pColumns[iCol].uFormat;
		lvc.iSubItem = pColumns[iCol].iColID;
		InsertColumn(pColumns[iCol].iColID + 1/*skip dummy column*/, &lvc);
	}
	DeleteColumn(0);
}

void CListCtrlX::EnableHdrCtrlSortBitmaps(BOOL bUseHdrCtrlSortBitmaps)
{
	if (bUseHdrCtrlSortBitmaps && theApp.m_ullComCtrlVer >= MAKEDLLVERULL(6,0,0,0))
		m_bUseHdrCtrlSortBitmaps = TRUE;
	else
#ifdef IDB_SORT_STATES
		SetHdrImgList(IDB_SORT_STATES, LCX_SORT_STATE_IMAGE_WIDTH, LCX_SORT_STATE_IMAGE_HEIGHT, LCX_SORT_STATE_IMAGES);
#else
		ASSERT(0);
#endif
}

void CListCtrlX::SetHdrImgList(UINT uResID, int cx, int cy, int iImages)
{
	m_uIDHdrImgList = uResID;
	m_sizeHdrImgListIcon.cx = cx;
	m_sizeHdrImgListIcon.cy = cy;
	m_iHdrImgListImages = iImages;
}

void CListCtrlX::SetSortColumn(int iColumns, LCX_COLUMN_INIT* pColumns, int iSortColumn)
{
	ASSERT( iSortColumn < iColumns );
	(void)iColumns;

	m_iSortColumn = iSortColumn;
	pColumns[m_iSortColumn].eSortOrder = pColumns[m_iSortColumn].eDfltSortOrder;

	UpdateSortColumn(iColumns, pColumns);
}

void CListCtrlX::UpdateSortColumn(int iColumns, LCX_COLUMN_INIT* pColumns)
{
	UpdateHdrCtrlSortBitmap(m_iSortColumn, pColumns[m_iSortColumn].eSortOrder);
}

void CListCtrlX::UpdateSortOrder(LPNMLISTVIEW pnmlv, int iColumns, LCX_COLUMN_INIT* pColumns)
{
	ASSERT( pnmlv->iItem == -1 );
	ASSERT( pnmlv->iSubItem >= 0 && pnmlv->iSubItem < iColumns );
	(void)iColumns;

	// Get sorting order for column
	if (pnmlv->iSubItem == m_iSortColumn)
	{
		// The sorting order is toggled, only if the user has clicked on the
		// same column which was used for the prev. sorting (like Windows
		// Explorer)
		if (pColumns[m_iSortColumn].eSortOrder == ASCENDING)
			pColumns[m_iSortColumn].eSortOrder = DESCENDING;
		else
			pColumns[m_iSortColumn].eSortOrder = ASCENDING;
	}
	else
	{
		// Everytime the user has clicked a column which was *not* used for
		// the prev. sorting, use the 'default' sorting order (like Windows
		// Explorer resp. MS Outlook)
		m_iSortColumn = pnmlv->iSubItem;
		pColumns[m_iSortColumn].eSortOrder = pColumns[m_iSortColumn].eDfltSortOrder;
	}

	UpdateHdrCtrlSortBitmap(m_iSortColumn, pColumns[m_iSortColumn].eSortOrder);
}

void CListCtrlX::UpdateHdrCtrlSortBitmap(int iSortedColumn, LCX_SORT_ORDER eSortOrder)
{
	//////////////////////////////////////////////////////////////////////////
	// Update the listview column headers to show the current sorting order
	//
	CHeaderCtrl* pHdrCtrl = GetHeaderCtrl();
	if (pHdrCtrl != NULL)
	{
		int iColumns = pHdrCtrl->GetItemCount();
		for (int i = 0; i < iColumns; i++)
		{
			HDITEM hdi;
			hdi.mask = HDI_FORMAT;
			pHdrCtrl->GetItem(i, &hdi);

		#ifndef HDF_SORTUP
		#define HDF_SORTUP		0x0400
		#define HDF_SORTDOWN	0x0200
		#endif

			if (i == iSortedColumn)
			{
				if (m_bUseHdrCtrlSortBitmaps) {
					hdi.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
					hdi.fmt |= (eSortOrder == ASCENDING) ? HDF_SORTUP : HDF_SORTDOWN;
				}
				else if (m_uIDHdrImgList != (UINT)-1) {
					hdi.mask |= HDI_FORMAT | HDI_IMAGE;
					hdi.fmt |= HDF_IMAGE | HDF_BITMAP_ON_RIGHT;
					hdi.iImage = (eSortOrder == ASCENDING) ? LCX_IDX_SORT_IMG_ASCENDING : LCX_IDX_SORT_IMG_DESCENDING;
				}
				pHdrCtrl->SetItem(i, &hdi);
			}
			else
			{
				if (m_bUseHdrCtrlSortBitmaps)
					hdi.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
				else
					hdi.fmt &= ~(HDF_IMAGE | HDF_BITMAP_ON_RIGHT);
				pHdrCtrl->SetItem(i, &hdi);
			}
		}
	}
}

void CListCtrlX::UpdateHdrImageList()
{
	if (   m_uIDHdrImgList != (UINT)-1
		&& m_sizeHdrImgListIcon.cx > 0 && m_sizeHdrImgListIcon.cy > 0
		&& m_iHdrImgListImages > 0)
	{
		::UpdateHdrImageList(*this, m_imlHdr, m_uIDHdrImgList, m_sizeHdrImgListIcon, m_iHdrImgListImages);
	}
}

void UpdateHdrImageList(CListCtrl& lv, CImageList& imlHdr, UINT uIDHdrImgList,
						CSize sizeHdrImgListIcon, int iHdrImgListImages)
{
	CHeaderCtrl* pHdrCtrl = lv.GetHeaderCtrl();
	if (pHdrCtrl != NULL)
	{
		HINSTANCE hInstRes = AfxFindResourceHandle(MAKEINTRESOURCE(uIDHdrImgList), RT_BITMAP);
		if (hInstRes != NULL)
		{
			// Explicitly map the bitmap (which comes in default 3D colors) to the current system colors
			HBITMAP hbmHdr = (HBITMAP)::LoadImage(hInstRes, MAKEINTRESOURCE(uIDHdrImgList), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS);
			if (hbmHdr != NULL)
			{
				CBitmap bmSortStates;
				bmSortStates.Attach(hbmHdr);

				// Create image list with mask (NOTE: The mask is needed for WinXP!)
				HIMAGELIST himlHeaderOld = imlHdr.Detach();
				if (imlHdr.Create(sizeHdrImgListIcon.cx, sizeHdrImgListIcon.cy, ILC_COLOR | ILC_MASK, iHdrImgListImages, 0))
				{
					// Fill images and masks into image list
					VERIFY( imlHdr.Add(&bmSortStates, RGB(255, 0, 255)) != -1 );

					// To avoid drawing problems (which occure only with an image list *with* a mask) while
					// resizing list view columns which have the header control bitmap right aligned, set
					// the background color of the image list.
					if (theApp.m_ullComCtrlVer < MAKEDLLVERULL(6,0,0,0))
						imlHdr.SetBkColor(GetSysColor(COLOR_BTNFACE));

					// When setting the image list for the header control, this *ALWAYS* returns
					// the image list which was set for the list view control!!!
					pHdrCtrl->SetImageList(&imlHdr);
					if (himlHeaderOld != NULL)
						ImageList_Destroy(himlHeaderOld);

				#if defined(HDM_GETBITMAPMARGIN) && defined(HDM_SETBITMAPMARGIN)
					int iBmpMargin = pHdrCtrl->SendMessage(HDM_GETBITMAPMARGIN); // Win2000: default us '6' (3*GetSystemMetrics(SM_CXEDGE))
					// Use same bitmap margin as Windows (W2K) Explorer -- this saves some pixels which
					// may be required for rather small column titles!
					int iNewBmpMargin = GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXEDGE)/2;
					if (iNewBmpMargin < iBmpMargin)
						pHdrCtrl->SendMessage(HDM_SETBITMAPMARGIN, iNewBmpMargin);
				#endif
				}
			}
		}
	}
}

void CListCtrlX::ApplyImageList(HIMAGELIST himl)
{
	SendMessage(LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
	if (m_imlHdr.m_hImageList != NULL)
	{
		// Must *again* set the image list for the header control, because LVM_SETIMAGELIST
		// always resets any already specified header control image lists!
		GetHeaderCtrl()->SetImageList(&m_imlHdr);
	}
}

BOOL CListCtrlX::OnHdrBeginDrag(UINT, NMHDR*, LRESULT*)
{
	if (theApp.m_ullComCtrlVer < MAKEDLLVERULL(6,0,0,0))
	{
		CImageList* piml = GetHeaderCtrl()->GetImageList();
		if (piml != NULL)
			piml->SetBkColor(GetSysColor(COLOR_3DSHADOW));
	}
	return FALSE; // *Force* default processing of notification!
}

BOOL CListCtrlX::OnHdrEndDrag(UINT, NMHDR*, LRESULT*)
{
	if (theApp.m_ullComCtrlVer < MAKEDLLVERULL(6,0,0,0))
	{
		CImageList* piml = GetHeaderCtrl()->GetImageList();
		if (piml != NULL)
			piml->SetBkColor(GetSysColor(COLOR_BTNFACE));
	}
	return FALSE; // *Force* default processing of notification!
}

void CListCtrlX::SelectAllItems()
{
	SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
}

void CListCtrlX::DeselectAllItems()
{
	SetItemState(-1, 0, LVIS_SELECTED);
}

void CListCtrlX::OnSysColorChange()
{

⌨️ 快捷键说明

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