📄 nlistctrl.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 + -