自动调整CListCtrl 列宽
void CPrintsysDlg::AdjustColumnWidth()
{
//SetRedraw(FALSE);
int nColumnCount = GetColumnCount();
for (int i = 0; i < nColumnCount; i++)
{
m_list.SetColumnWidth(i, LVSCW_AUTOSIZE);
int nColumnWidth =m_list. GetColumnWidth(i);
m_list.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
int nHeaderWidth = m_list.GetColumnWidth(i);
m_list.SetColumnWidth(i, max(nColumnWidth, nHeaderWidth));
}
// SetRedraw(TRUE);
}
int CPrintsysDlg::GetColumnCount()
{
CHeaderCtrl* pHeaderCtrl =m_list. GetHeaderCtrl();
return (pHeaderCtrl->GetItemCount());
}
自动调整列宽2
void CListCtrlEx::AutoSizeColumns(int col /*=-1*/,BOOL bFitWidth/*=FALSE*/)
{
// Call this after your list control is filled
CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
int ColumnCount = pHeaderCtrl->GetItemCount();
if(!GetHeaderCtrl())return;
ShowWindow(SW_HIDE);//避免闪烁
SetRedraw(FALSE);
if(!bFitWidth)//如果不自动调整最后一列宽度,使得总列宽等于控件宽度,
InsertColumn(ColumnCount,"");
int mincol = col < 0 ? 0 : col;
int maxcol = col < 0 ? ColumnCount-1 : col;
for (col = mincol; col <= maxcol; col++) {
SetColumnWidth(col,LVSCW_AUTOSIZE);
int wc1 = GetColumnWidth(col);
SetColumnWidth(col,LVSCW_AUTOSIZE_USEHEADER);
int wc2 = GetColumnWidth(col);
int iFrom=GetTopIndex();
int nCountPerpage=GetCountPerPage();
if(nCountPerpage<=0)
nCountPerpage=GetItemCount();
int iTo=iFrom+nCountPerpage;
int nImgWidth=0;
int iIndent=0;
LVITEM li;
li.mask=LVIF_IMAGE|LVIF_INDENT;
IMAGEINFO ImageInfo;
for(int iItem=iFrom;iItem<iTo;iItem++){
li.iItem=iItem;
GetItem(&li);
iIndent=max(li.iIndent,iIndent);
if(li.iImage!=-1){
CImageList* pImageList=GetImageList(LVSIL_SMALL);
if(pImageList->GetSafeHandle()){
pImageList->GetImageInfo(li.iImage,&ImageInfo);
nImgWidth=max(nImgWidth,ImageInfo.rcImage.right-ImageInfo.rcImage.left);
}
}
}
int wc = max(20,max(wc1,wc2));
if(col==0)
wc+=nImgWidth*(iIndent+1);
else
wc+=nImgWidth;
SetColumnWidth(col,wc);
}
if(!bFitWidth)
DeleteColumn(ColumnCount-1);
SetRedraw(TRUE);
ShowWindow(SW_SHOW);
}
禁止列宽拖动
通过重写虚函数OnNotify实现。
类视图加入OnNotify:
//头文件中
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//函数定义
//禁止List控件列与列之间的拖拉
BOOL CListCtrlEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam;
switch(((NMHDR*)lParam)->code)
{
case HDN_BEGINTRACKW://拖动
case HDN_BEGINTRACKA:
case HDN_DIVIDERDBLCLICK://双击
if (pHDN->iItem == Col) // Col—设定为自己不想改变的列值,比如Col=0,就是第1列
{
*pResult = TRUE;
return TRUE;
}
break;
}
return CListCtrl::OnNotify(wParam, lParam, pResult);
}
固定标题列宽,禁止拖动(Ini ListCtril中调用):
CHeaderCtrl* pHeaderCtrl = (CHeaderCtrl*)m_ListCtrl.GetHeaderCtrl();
pHeaderCtrl->EnableWindow( FALSE ) ;
禁止点击列(Ini ListCtril中调用):
BOOL CListCtrlEx::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message==WM_LBUTTONDOWN || pMsg->message==WM_LBUTTONUP)
{
CHeaderCtrl* pHead;
pHead=GetHeaderCtrl();
if(pMsg->hwnd==pHead->m_hWnd){
//return TRUE; //无法点击列
}
}
return CListCtrl::PreTranslateMessage(pMsg);
}
把ListCtrl最后一列自动调整大小;并随对话框改变而改变
建立工程AutoListCtrl
给 CAutolistCtlDlg添加如下几个函数,在OnInitDialog()中调用SetList();
private:
void SetList();
void SetListColumn();
void SetListText();
void ReSizeList();
void CAutolistCtlDlg::SetList()
{
SetListColumn();
SetListText();
ReSizeList();
}
void CAutolistCtlDlg::SetListColumn()//列表头
{
CString strColumn;
for (int i = 0; i < 3; i++)
{
strColumn.Format(_T("Column(%d)"), i);
m_xList.InsertColumn(i, strColumn,LVCFMT_LEFT, 100);
}
}
void CAutolistCtlDlg::SetListText()
{
CString strListText;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 10; j++)
{
strListText.Format(_T("Item[%d][%d]"), j, i);
if (0 == i)
m_xList.InsertItem(j, strListText);//第一列
else
m_xList.SetItemText(j, i, strListText);//后面几列
}
}
void CAutolistCtlDlg::ReSizeList()
{
CRect rect;
GetClientRect(&rect);//wnd的
m_xList.MoveWindow(5, 5, rect.Width() - 10, rect.Height() - 10);
}
void CAutolistCtlDlg::OnSize(UINT nType, int cx, int cy)//对话框对应消息ON_WM_SIZE的函数
{
CDialog::OnSize(nType, cx, cy);
if (IsWindow(m_xList.m_hWnd))//会在InitDialog之前执行一次,这个时候listctrl还没被创建
{
m_xList.MoveWindow(5, 5, cx - 1, cy -10);
//m_xList.AutoColumn();
}
}
/*Onsize中的代码使ListCtrl随对话框的缩放而缩放,要使对话框有缩放功能,必须在对话框的Border属性中选择Resizing*/
接下来要让listcrl的最后一列自动对齐(填满)
新建一个MFC类继承于CListCtrl
class CAutoColumnList : public CListCtrl
添加成员函数
public:
void AutoColumn();
private:
void OnSize(UINT nType, int cx, int cy);//List的ON_WM_SIZE()对应的消息函数
//.cpp
BEGIN_MESSAGE_MAP(CAutoColumnList, CListCtrl)
ON_WM_SIZE()
END_MESSAGE_MAP()
/*1.ON_WM_SIZE()是MFC自带消息,其消息函数一定对应void OnSize(UINT nType, int cx, int cy)形式。
但我们仍然要自己把OnSize声明一下
2.如果是自定义消息,则要这么写:
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
ON_WM_SIZE()
ON_MESSAGE(WM_RESIZEME,OnResizeMe)
END_MESSAGE_MAP()*/
void CAutoColumnList::OnSize(UINT nType, int cx, int cy)
{
CListCtrl::OnSize(nType, cx, cy);
AutoColumn();
}
// CAutoColumnList message handlers
void CAutoColumnList::AutoColumn()//自动调节最后一列
{
CRect xRect;
int nLastColumnWidth = 0;
int nColumnNum = 0;
GetClientRect(&xRect);//OleControl的
nLastColumnWidth = xRect.Width();
nColumnNum = GetHeaderCtrl()->GetItemCount();
for (int i = 0; i < nColumnNum - 1; i++)
nLastColumnWidth = nLastColumnWidth - GetColumnWidth(i);
SetColumnWidth(nColumnNum - 1, nLastColumnWidth);
}
最后,要记得把ListCtrl的变量m_xList类型改为CAutoColumnList
到此为止,程序可以运行了,但我们会问,为什么要为ListCtl设置一个消息函数OnSize,而不直接在Dlg的OnSize里面调用m_xList.AutoColumn()呢?
下面来看一下CAutolistCtlDlg::OnSize, CAutolistCtlDlg::OnInitDialog(),
CAutoColumnList::OnSize这三个函数在程序刚启动时的调用顺序:
1.首先调用CAutolistCtlDlg::OnSize
知道为什么要:
if (IsWindow(m_xList.m_hWnd))//会在InitDialog之前执行一次,这个时候listctrl还没被创建
{
m_xList.MoveWindow(5, 5, cx - 1, cy -10);
//m_xList.AutoColumn();
}
判断一下了吧?这个时候listctrl还没生成,使用它当然会出错。当然,有了此条件语句,在其内部的
m_xList.AutoColumn()想执行也执行不了了。
2.再调用CAutolistCtlDlg::OnInitDialog(),这个时候SetList()被调用了。
3.最后调用CAutoColumnList::OnSize,因为listCtrl已经建立,调用AutoColumn()自然可以成功调整列。
所以如果把AutoColumn()放在CAutolistCtlDlg::OnSize中而不是CAutoColumnList::OnSize中,刚启动程
序时是不会对齐的,直到resize一下dlg,再次执行CAutolistCtlDlg::OnSize,则条件语句中的东西才能被执行。