📄 listctrlex.cpp
字号:
// ListCtrlEx.cpp : implementation file
//
#include "stdafx.h"
#include "ListCtrlEx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx
//=============================================================================
// 构造函数, 初始化变量
CListCtrlEx::CListCtrlEx()
{
m_pEdit= NULL;
m_pCombo = NULL;
m_pLastCtrl = NULL;
m_nUsedCtrl = 0;
m_bShowCtrl =FALSE;
}
//=============================================================================
// 析构函数, 释放程序创建的对象
CListCtrlEx::~CListCtrlEx()
{
if(m_pEdit) delete m_pEdit;
if(m_pCombo) delete m_pCombo;
}
//=============================================================================
// 控件消息映射
BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
//{{AFX_MSG_MAP(CListCtrlEx)
ON_WM_LBUTTONDOWN()
ON_WM_KILLFOCUS()
ON_WM_NCLBUTTONDBLCLK()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
ON_EN_KILLFOCUS(IDC_INPLACE_EDIT, OnKillfocusEditBox)
ON_EN_CHANGE(IDC_INPLACE_EDIT, OnChangeEditBox)
ON_CBN_KILLFOCUS(IDC_INPLACE_COMBO, OnKillfocusCmbBox)
ON_CBN_SELCHANGE(IDC_INPLACE_COMBO, OnSelchangeCmbBox)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx message handlers
//#############################################################################
// 所有的贴上的控件消息处理
//=============================================================================
// 编辑框失去焦点, 如果内容发生改变, 更新显示并通知父窗口
void CListCtrlEx::OnKillfocusEditBox()
{
CString newStr;
m_pEdit->GetWindowText(newStr);
if(newStr != GetItemText(m_nRow, m_nCol))
{
SetItemText(m_nRow,m_nCol,newStr);
GetParent()->SendMessage(UM_EDITCHANGED, WPARAM(GetDlgCtrlID()), LPARAM(m_nCol));
}
m_pEdit->ShowWindow(SW_HIDE);
Invalidate();
}
//=============================================================================
// 编辑框内容改变
void CListCtrlEx::OnChangeEditBox()
{
}
//=============================================================================
// 组合框失去焦点
void CListCtrlEx::OnKillfocusCmbBox()
{
m_pCombo->ShowWindow(SW_HIDE);
Invalidate();
}
//=============================================================================
// 组合框项选择改变
void CListCtrlEx::OnSelchangeCmbBox()
{
CString newStr;
if (m_pCombo)
{
m_pCombo->GetLBText(m_pCombo->GetCurSel(),newStr);
m_strComboOld = GetItemText(m_nRow, m_nCol);
if(newStr != m_strComboOld)
{
SetItemText(m_nRow,m_nCol,newStr);
GetParent()->SendMessage(UM_SELECTCHANGE, WPARAM(GetDlgCtrlID()), LPARAM(m_nCol));
}
}
}
//#############################################################################
// 列表框控件函数
//=============================================================================
// 鼠标左键按下, 即某个单元格被双击(选择)
void CListCtrlEx::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CListCtrl::OnLButtonDblClk(nFlags, point);
// 针对禁止用户选择复选框
MSG message;
while( PeekMessage( &message, NULL, 0, 0 ,PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
SelectCell(point);
}
//=============================================================================
// 鼠标左键按下, 即某个单元格被单击(选择)
void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
{
CListCtrl::OnLButtonDown(nFlags, point);
MSG message;
while( PeekMessage( &message, NULL, 0, 0 ,PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
SelectCell(point);
}
//=============================================================================
// 根据点位置,选中对应的单元格
void CListCtrlEx::SelectCell(CPoint point)
{
SetFocus(); // 设置列表框获得焦点
MSG message; // 分发消息, 让编辑框等附属控件先失去焦点
while( PeekMessage( &message, NULL, 0, 0 ,PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
if( HitTestEx(point) != -1 )
{
if(m_pLastCtrl)
m_pLastCtrl->ShowWindow(SW_HIDE);
UINT flag = LVIS_FOCUSED;
if( (GetItemState( m_nRow, flag ) & flag) == flag && m_nCol > 0)
{
// ???
}
else
SetItemState( m_nRow, LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED);
GetParent()->SendMessage(UM_CHECKSTATECHANGE, WPARAM(GetDlgCtrlID()), LPARAM(m_nCol)) ;
ShowCtrl();
}
}
//=============================================================================
// 外部函数,用来显示某个控件
void CListCtrlEx::ShowCtrl(int nRow, int nCol, CWnd* pCtrl)
{
if(m_pLastCtrl)
m_pLastCtrl->ShowWindow(SW_HIDE);
m_nRow = nRow;
m_nCol = nCol;
// SetFocus();
SetItemState( m_nRow, LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED);
m_pLastCtrl = pCtrl;
m_bShowCtrl = TRUE;
ShowCtrl();
}
//=============================================================================
// 内部函数, 显示当前控件
void CListCtrlEx::ShowCtrl()
{
//-----------------------------------------------------------
// 计算单元格位置
if( !EnsureVisible( m_nRow, TRUE ) )
return; // 确认该行可见
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
if( m_nCol >= nColumnCount ||GetColumnWidth(m_nCol) < 5 ) // 确认该列有效
return;
// 获取列的偏移量
int offset = 0;
for( int i = 0; i < m_nCol; i++ )
offset += GetColumnWidth( i );
CRect rect;
GetItemRect(m_nRow,&rect,LVIR_BOUNDS);
// Now scroll if we need to expose the column
CRect rcClient;
GetClientRect( &rcClient );
if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
{
CSize size;
size.cx = offset + rect.left;
size.cy = 0;
Scroll( size );
rect.left -= size.cx;
}
rect.left += offset;
rect.right = rect.left + GetColumnWidth( m_nCol ) ;
int n=0;
rect.top -= n;
rect.bottom -= n;
if( rect.right > rcClient.right) rect.right = rcClient.right;
if(m_bShowCtrl)
{
if(m_pEdit)
{
m_pEdit->SetMargins(4,4);
}
if( m_pLastCtrl == m_pCombo)
{
rect.left += 2;
//rect.right -= 4;
n=1;
rect.top -= n-1;
rect.bottom -= n;
}
m_pLastCtrl->MoveWindow(rect);
m_pLastCtrl->ShowWindow(SW_SHOW);
if( m_pLastCtrl == m_pEdit)
{
m_pEdit->SetSel(0,-1);
m_pEdit->SetFocus();
}
if( m_pLastCtrl == m_pCombo)
{
m_pCombo->SetItemHeight(-1,rect.Height()-3);
m_pCombo->SetItemHeight(0,rect.Height()+2);
}
}
}
//=============================================================================
//根据point值,判断point所在行和列:
int CListCtrlEx::HitTestEx(CPoint point)
{
// m_nRow = 0; // 获取所在的行
// m_nCol =0;
// return 0;
m_nRow = HitTest( point,NULL ); // 获取所在的行
m_nCol =0;
// 只有在风格为LVS_REPORT时才处理
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
return m_nRow;
// 获取当前可见的顶行和末行
m_nRow = GetTopIndex();
int bottom = m_nRow + GetCountPerPage();
if( bottom > GetItemCount() )
bottom = GetItemCount();
// 获取列数
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
// 循环处理所有可见的行
for( ;m_nRow <=bottom;m_nRow++)
{
// 获取每行绑定的单元格,并判断鼠标点是否落在某行上
CRect rect;
GetItemRect( m_nRow, &rect, LVIR_BOUNDS );
if( rect.PtInRect(point) )
{ // 如果鼠标点落在本行内
// 循环所有列,判断鼠标点落在哪列内
for(int column = 0; column < nColumnCount; column++ )
{
int colwidth = GetColumnWidth(column);
if( point.x >= rect.left && point.x <= (rect.left + colwidth ) )
{
m_nCol =column;
CString tp;
return m_nRow;
}
rect.left += colwidth;
}
}
}
m_nCol = -1;
return -1;
}
//=============================================================================
// 设置使用的控件种类
void CListCtrlEx::SetUsedCtrl(int nUsedCtrl)
{
m_nUsedCtrl = nUsedCtrl;
CRect rect(0,0,10,200);
//---------------------------------------------------------------
// 如果使用编辑控件
if(nUsedCtrl&USED_CTRL_EDIT == USED_CTRL_EDIT)
{
m_pEdit = new CEdit();
m_pEdit->Create(WS_CHILD|WS_BORDER|ES_AUTOHSCROLL,rect,this,IDC_INPLACE_EDIT );
m_pEdit->SetFont(GetFont());
}
//---------------------------------------------------------------
// 如果使用组合框控件
if((nUsedCtrl&USED_CTRL_COMBO) == USED_CTRL_COMBO)
{
m_pCombo = new CComboBox();
m_pCombo->Create(WS_CHILD|WS_VSCROLL|CBS_DROPDOWNLIST|CBS_AUTOHSCROLL,\
rect,this,IDC_INPLACE_COMBO );
int n=GetItemRect(0,&rect,LVIR_BOUNDS );
m_pCombo->SetFont(GetFont());
}
}
//=============================================================================
// 列表控件失去焦点时
void CListCtrlEx::OnKillFocus(CWnd* pNewWnd)
{
CListCtrl::OnKillFocus(pNewWnd);
//---------------------------------------------------------------
// 列表框控件真正失去焦点时,隐藏上次使用的贴上的控件(如果有的话)
if(m_pLastCtrl)
{
if(m_pLastCtrl->GetFocus() != m_pLastCtrl)
{ //列表框控件失去的焦点不是由贴上的控件获取焦点引起
m_pLastCtrl->ShowWindow(SW_HIDE);
}
}
}
void CListCtrlEx::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// MessageBox("ffdsafdsjkda;");
CListCtrl::OnNcLButtonDblClk(nHitTest, point);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -