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

📄 nlistctrl.cpp

📁 VisualC++实践与提高-ActiveX篇源码
💻 CPP
字号:
/************************************
  REVISION LOG ENTRY
  Revision By: Mihai Filimon
  Revised on 12/10/98 10:29:22 AM
  Comments: NListCtrl.cpp : implementation file
 ************************************/

#include "stdafx.h"
#include "NCombo.h"
#include "NListCtrl.h"
#include "NWindow.h"
#include "SmartInvalidate.h"
#include "NComboCtl.h"

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

static const int dxSize2 = 2;
#define NULLPOINT CPoint(-1,-1)

/////////////////////////////////////////////////////////////////////////////
// CNListCtrl

// Function name	: CNListCtrl::CNListCtrl
// Description	    : default constuctor
// Return type		: 
CNListCtrl::CNListCtrl()
{
	m_nReleaseMouse = 0;
	m_nSelected = -1;
	m_nLastSelected = -1;
	m_bSizing = TRUE;
	m_ptnCapture = NULLPOINT;
	m_iResizeColumn = -1;
	m_nSaveSelectItem = -1;
	m_nLastNotifyItem = -1;
	m_bLastChanging = FALSE;
}

// Function name	: CNListCtrl::~CNListCtrl
// Description	    : virtual desturctor
// Return type		: 
CNListCtrl::~CNListCtrl()
{
}


BEGIN_MESSAGE_MAP(CNListCtrl, CListCtrl)
	//{{AFX_MSG_MAP(CNListCtrl)
	ON_WM_CREATE()
	ON_WM_WINDOWPOSCHANGING()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_KILLFOCUS()
	ON_WM_HSCROLL()
	ON_WM_KEYDOWN()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNListCtrl message handlers

// Function name	: CNListCtrl::OnCreate
// Description	    : 
// Return type		: int 
// Argument         : LPCREATESTRUCT lpCreateStruct
int CNListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CListCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;

	CreateFontDisp((IDispatch*)m_pParent->m_pControl->GetFont(), m_font);
//	CloneFont(m_pParent->m_pControl->GetFont(), &m_font, _T("-34,0,0,0,400,0,0,0,0,3,2,1,34,Arial"));
	SetFont(&m_font);

	return OnInit();

}

// Function name	: CNListCtrl::OnInit
// Description	    : 
// Return type		: int 
int CNListCtrl::OnInit()
{
	ListView_SetExtendedListViewStyleEx( m_hWnd, 0, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT );

	return 0;
}

// Function name	: CNListCtrl::SetParent
// Description	    : 
// Return type		: void 
// Argument         : CNWindow *pParent
void CNListCtrl::SetParent(CNWindow *pParent)
{
	m_pParent = pParent;
}

// Function name	: CNListCtrl::OnWindowPosChanging
// Description	    : 
// Return type		: void 
// Argument         : WINDOWPOS FAR* lpwndpos
void CNListCtrl::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) 
{
	CListCtrl::OnWindowPosChanging(lpwndpos);
	
	ReleaseCapture();
	if (lpwndpos->flags & SWP_SHOWWINDOW)
	{
		m_pParent->Resize();
		SetWindowPos(&CWnd::wndTopMost, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
		SetCapture();
	}
}

// Function name	: CNListCtrl::GetScroll
// Description	    : 
// Return type		: int 
int CNListCtrl::GetHScroll()
{
	return GetScrollPos(SB_HORZ);
}

// Function name	: CNListCtrl::GetScroll
// Description	    : 
// Return type		: int 
int CNListCtrl::GetVScroll()
{
	return GetScrollPos(SB_VERT);
}

// Function name	: CNListCtrl::GetHScrollMax
// Description	    : 
// Return type		: int 
int CNListCtrl::GetHScrollMax()
{
	CRect rect; GetClientRect(rect);
	return rect.Width();
}

// Function name	: CNListCtrl::WindowProc
// Description	    : 
// Return type		: LRESULT 
// Argument         : UINT message
// Argument         : WPARAM wParam
// Argument         : LPARAM lParam
LRESULT CNListCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	LRESULT lResult = CListCtrl::WindowProc(message, wParam, lParam);
	switch (message)
	{
		case WM_HSCROLL:
		case WM_VSCROLL:
		{
			// Just restore the captured window
			SetCapture();
			break;
		}
	}
	return lResult;
}

// Function name	: CNListCtrl::IsMouseCaptured
// Description	    : 
// Return type		: BOOL 
BOOL CNListCtrl::IsMouseCaptured()
{
	return m_ptnCapture != NULLPOINT;
}

// Function name	: CNListCtrl::OnLButtonDown
// Description	    : 
// Return type		: void 
// Argument         : UINT nFlags
// Argument         : CPoint point
void CNListCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CRect rW, rC;
	GetWindowRect(rW); GetClientRect(rC);
	CPoint p(point);
	ClientToScreen(&p);

	m_iResizeColumn = IsSizingColumn(point);
	if (m_iResizeColumn >= 0)
	{
		SetCapture();
		m_ptnCapture = point;
		return;
	}

	if (rW.PtInRect(p))
		if (rC.PtInRect(point))
			Close(FALSE);
		else
		{
			ReleaseCapture();
			return; // In OnHScroll, OnVScroll this will be again captured
		}
	else
	{
		CWnd* pNEdit = WindowFromPoint(p);
		if (m_pParent->GetHeader()->Lookup(pNEdit) < 0 )
			Close(TRUE);
		else
		{
			pNEdit->SetFocus();
			SetCapture();
			return;
		}
	}

	CListCtrl::OnLButtonDown(nFlags, point);
}

// Function name	: CNListCtrl::OnLButtonUp
// Description	    : 
// Return type		: void 
// Argument         : UINT nFlags
// Argument         : CPoint point
void CNListCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if (IsMouseCaptured())
	{
		m_ptnCapture = NULLPOINT;
		SetCapture();
		return;
	}
	
	CListCtrl::OnLButtonUp(nFlags, point);
}


// Function name	: CNListCtrl::OnMouseMove
// Description	    : 
// Return type		: void 
// Argument         : UINT nFlags
// Argument         : CPoint point
void CNListCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (IsMouseCaptured())
	{
		CRect rect; GetClientRect(rect);
		int rMin = rect.Width() / 6, rMax = rect.Width() - rMin;
		int newWidth = GetColumnWidth( m_iResizeColumn ) + ( point.x - m_ptnCapture.x );
		SetColumnWidth2(m_iResizeColumn, max(newWidth, 0));
		m_ptnCapture = point;
		return;
	}
	SetSelect(HitTest(point));
	SetCursor(AfxGetApp()->LoadStandardCursor(IsSizingColumn(point) < 0? IDC_ARROW : IDC_SIZEWE ));
	CListCtrl::OnMouseMove(nFlags, point);
}

// Function name	: CNListCtrl::OnKillFocus
// Description	    : 
// Return type		: void 
// Argument         : CWnd* pNewWnd
void CNListCtrl::OnKillFocus(CWnd* pNewWnd) 
{
	CListCtrl::OnKillFocus(pNewWnd);
	
	CNHeaderCtrl* pNHeader = m_pParent->GetHeader();
	if (pNHeader->Lookup(pNewWnd) < 0)
		Close(FALSE);
	else
		SetCapture();
}

// Function name	: CNListCtrl::Open
// Description	    : Open the 
// Return type		: void 
void CNListCtrl::Open()
{
	if (IsClose())
		if (m_pParent->GetHeader()->IsWindowVisible())
		{
			ShowWindow(SW_SHOW);
			SetSelect(m_nSaveSelectItem = GetSelect());
			EnsureVisible(GetSelect(), FALSE);
		}
}

// Function name	: CNListCtrl::Close
// Description	    : 
// Return type		: void 
// Argument         : BOOL bCancel
void CNListCtrl::Close(BOOL bCancel)
{
	if (IsOpen())
	{
		ShowWindow(SW_HIDE);
		if (!bCancel)
		{
			*m_pParent->GetHeader() = m_nLastSelected;
			// Set the new one item selected
			SetSelect(m_nLastSelected, TRUE);
		}
	}
}

// Function name	: CNListCtrl::Toggle
// Description	    : 
// Return type		: void 
void CNListCtrl::Toggle()
{
	if (IsOpen()) Close(TRUE);
	else Open();
}

// Function name	: CNListCtrl::OnHScroll
// Description	    : 
// Return type		: void 
// Argument         : UINT nSBCode
// Argument         : UINT nPos
// Argument         : CScrollBar* pScrollBar
void CNListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
#ifdef NOFLICKERING
	CNHeaderCtrl* pNHeader = m_pParent->GetHeader();
	CSmartInvalidate smarter;
	smarter.Add(pNHeader);
	smarter.Add(this);
#endif //NOFLICKERING

	CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
	m_pParent->GetHeader()->ScrollToPos(GetHScroll());

#ifdef NOFLICKERING
	smarter.Update();
	pNHeader->DrawButton(NULL, TRUE);
#endif //NOFLICKERING
}

// Function name	: CNListCtrl::IsOpen
// Description	    : 
// Return type		: BOOL 
BOOL CNListCtrl::IsOpen()
{
	return !IsClose();
}

// Function name	: CNListCtrl::IsClose
// Description	    : 
// Return type		: BOOL 
BOOL CNListCtrl::IsClose()
{
	return !IsWindowVisible();
}


// Function name	: CNListCtrl::IsMouseReleased
// Description	    : 
// Return type		: BOOL 
BOOL CNListCtrl::IsMouseReleased()
{
	return m_nReleaseMouse == 0;
}

// Function name	: CNListCtrl::SetSelect
// Description	    : 
// Return type		: void 
// Argument         : int nItem
// Argument         : BOOL bNotify
void CNListCtrl::SetSelect(int nItem, BOOL bNotify)
{
	if (nItem >= 0)
		if (nItem < GetItemCount())
		{
			SetItemState(nItem, LVNI_SELECTED, LVNI_SELECTED);
			EnsureVisible(nItem, FALSE);
			if (bNotify)
			{
				*m_pParent->GetHeader() = nItem;
				m_nSelected = nItem;
			}
			m_nLastSelected = nItem;
			NotifyControlChange(!bNotify, nItem);
		}
}

// Function name	: CNListCtrl::GetSelect
// Description	    : return m_nSelected if this is in range [0..GetItemCount]. -1 if not
// Return type		: int 
const int CNListCtrl::GetSelect()
{
	return m_nSelected;
}

// Function name	: CNListCtrl::OnKeyDown
// Description	    : Treats separatly each key, because the parent of this do
// not reflect the message. This is a popup window!
// Return type		: void 
// Argument         : UINT nChar
// Argument         : UINT nRepCnt
// Argument         : UINT nFlags
void CNListCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	int nStep = 0;
	switch (nChar)
	{
		case VK_UP:
		{
			nStep = -1;
			break;
		}
		case VK_DOWN:
		{
			nStep = +1;
			break;
		}
		case VK_NEXT:
		{
			nStep = GetCountPerPage();
			break;
		}
		case VK_PRIOR:
		{
			nStep = -GetCountPerPage();
			break;
		}
	}

	if (nStep)
	{
		SetSelect(max(min(m_nLastSelected + nStep,GetItemCount()),0), TRUE);
		return;
	}
	
	CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}

static int _iUp, _iDown, _iCount;
typedef int (_stdcall *NEXTTYPE) (int j = 0);
static NEXTTYPE _nextFunction;

int _stdcall _NextDown(int j = 0);
int _stdcall _NextUp(int j = 0)
{
	int i = NULL;
	if (--_iUp >= 0)
	{
		i = _iUp;
		if (i >= 0 )
			return i;
	}
	_nextFunction = _NextDown; 
	return (*_nextFunction)(j);
}

int _stdcall _NextDown(int j)
{
	int i = NULL;
	if (++_iDown < _iCount)
	{
		i = _iDown;
		if (i < _iCount)
			return i;
	}
	_nextFunction = _NextUp; 
	return (*_nextFunction)(j);
}

int _stdcall _Next(int j)
{
	if (j % 2)
		return _NextUp();
	return _NextDown();
}

int _stdcall _NextForward(int j)
{
	if (++_iDown >= _iCount)
		_iDown = 0;
	return _iDown;
}

int _stdcall _NextBackward(int j)
{
	if (--_iDown < 0)
		_iDown = _iCount - 1;
	return _iDown;
}

// Function name	: CNListCtrl::OnEditChange
// Description	    : The content of edit corresponding to one column from this list, 
// was change. The new contant became lpszColumnText. Here we will search ...
// Return type		: void 
// Argument         : int nColumn
// Argument         : LPCTSTR lpszColumnText
void CNListCtrl::OnEditChange(int nColumn, LPCTSTR lpszColumnText, int nType )
{
	m_pParent->GetHeader()->IncUserReason();
	int n = CString(lpszColumnText).GetLength();
	if (IsOpen() && (n))
	{
		int nCount = _iCount = GetItemCount();
		SetSelect(max(m_nLastSelected,0));
		int i = _iUp = _iDown = m_nLastSelected;
		BOOL bThisItem = TRUE;
		switch (nType)
		{
			case -1:
			{
				_nextFunction = _NextBackward;
				break;
			}
			case 0:
			{
				_nextFunction = _Next;
				nCount--;
				bThisItem = GetItemText(i, nColumn).Left(n).CompareNoCase(lpszColumnText) != 0;
				break;
			}
			case 1:
			{
				_nextFunction = _NextForward;
				break;
			}
		}
		if (bThisItem)
			for (register int j = 0; j < nCount; j++)
				if (GetItemText(i = (*_nextFunction)(j), nColumn).Left(n).CompareNoCase(lpszColumnText) == 0)
				{
					SetSelect(i);
					break;
				}
	}
	NotifyChangeColumnContent(nColumn, lpszColumnText, nType);
	m_pParent->GetHeader()->DecUserReason();
}

// Function name	: CNListCtrl::IsSizingLine
// Description	    : return TRUE if point is over column
// Return type		: BOOL 
// Argument         : CPoint point
int CNListCtrl::IsSizingColumn(CPoint point)
{
	if (m_bSizing)
	{
		CRect rect; GetClientRect(rect);
		if (rect.PtInRect(point))
		{
			int nStart = -GetHScroll() + 1;
			LVCOLUMN lvColumn; lvColumn.mask = LVCF_WIDTH;
			for (int iColumn = 0; GetColumn(iColumn, &lvColumn); iColumn++)
			{
				nStart += lvColumn.cx;
				if ((point.x >= nStart - dxSize2) && (point.x < nStart + dxSize2))
					return iColumn;
			}
		}
	}
	return -1;
}

// Function name	: CNListCtrl::SetColumnWidth2
// Description	    : Redraw the control if column width2 is changed
// Return type		: void 
// Argument         : int iColumn
// Argument         : int nNewValue
void CNListCtrl::SetColumnWidth2(int iColumn, int nNewValue)
{
	CNHeaderCtrl* pNHeader = m_pParent->GetHeader();
#ifdef NOFLICKERING
	CSmartInvalidate smarter;
	smarter.Add(this);
	smarter.Add(pNHeader);
#endif //NOFLICKERING
		SetColumnWidth(iColumn, max(0, nNewValue) );
		pNHeader->ScrollToPos(GetHScroll());
#ifdef NOFLICKERING
	smarter.Update();
	pNHeader->DrawButton(NULL);
#endif //NOFLICKERING
}

// Function name	: CNListCtrl::GetItemHeight
// Description	    : Call to calculate the height of selected font
// Return type		: int 
int CNListCtrl::GetItemHeight()
{
	LOGFONT logFont;
	GetFont()->GetLogFont(&logFont);
	CDC* pDC = GetDC();
	CFont* pFont = pDC->SelectObject(GetFont());
	TEXTMETRIC metrix;
	pDC->GetTextMetrics(&metrix);
	pDC->SelectObject(pFont);
	ReleaseDC(pDC);
	return metrix.tmHeight + 4;
}

// Function name	: CNListCtrl::Restore
// Description	    : Restore the selection. On open drop the select item ws save into m_nSaveSelectItem
// Return type		: void 
void CNListCtrl::Restore()
{
	ASSERT(IsOpen());
	SetSelect(m_nSaveSelectItem, TRUE);
}

// Function name	: CNListCtrl::NotifyControlChange
// Description	    : If you want to remove one event , do here
// Return type		: void 
// Argument         : BOOL bChanging
// Argument         : long nItem
void CNListCtrl::NotifyControlChange(BOOL bChanging, long nItem)
{
	if (!((m_nLastNotifyItem == nItem) && (m_bLastChanging == bChanging)))
		if (CNComboCtrl* pControl = GetControl())
			if (bChanging)
				pControl->FireChangingItem(nItem);
			else
				pControl->FireChangedItem(nItem);
	m_nLastNotifyItem = nItem;
	m_bLastChanging = bChanging;
}

// Function name	: CNListCtrl::GetControl
// Description	    : 
// Return type		: CNComboCtrl* 
CNComboCtrl* CNListCtrl::GetControl()
{
	if (m_pParent)
		return m_pParent->m_pControl;
	return NULL;
}

// Function name	: CNListCtrl::NotifyChangeColumnContent
// Description	    : 
// Return type		: void 
// Argument         : int nColumn
// Argument         : LPCTSTR sColumnContent
// Argument         : int nType
void CNListCtrl::NotifyChangeColumnContent(int nColumn, LPCTSTR sColumnContent, int nType)
{
	if (CNComboCtrl* pControl = GetControl())
		pControl->FireChangeColumnContent(nColumn, sColumnContent, nType);
}

⌨️ 快捷键说明

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