在MFC程序中,其实根据系统提供,只能将每行的高度设置成相同的。但是在实际工程中,有时需要设置不同的行高,但是又保证该控
件的使用和系统提供的相似。我觉得很难。
我也曾在网上找过相关的资料,但是都是只有提问者,回答者几乎没有。
但是我的工程中需要有这样的功能时,我便自己重写继承了下CListCtrl类,在外部使用的时候与CListCtrl控件的功能相同,只是在内
部重绘的时候修改了下绘制思路就可以了。但是现在有个问题,并且知道是哪错了,但是没有时间修改,不过行高不同的功能已经实现
了。大家可以帮我修改下。
其实,代码不重要,重要的是如何绘制的思路。
控件功能:
我的控件只要实现的是,只要在插入的数据中有'\n'等换行标识时,就让该行的高度增加。
绘图的思路:
在外部插入的时候与原来使用相同,但是在InsertItemText和SetItemText,解析插入的数据中有多少个'\n',将一个拆分成多个保存
起来。把这些拆分的字符串又当成一个一个的数据,继续使用InsertItemText和SetItemText插入。
例如:一个字符串为:m_list.InsertItemText(0,_T("这只是\n一个简单的例子\n举例说明\n是如何使用的"));
其中有3个换行符,我可以将这个字符串拆分成4段。再分别使用InsertItemText插入这4个字符串。
CListCtrl::InserItem(0,_T("这只是"));
CListCtrl::InserItem(1,_T("一个简单的例子"));
CListCtrl::InserItem(2,_T("举例说明"));
CListCtrl::InserItem(3,_T("是如何使用的"));
此时,0、1、2、3是外部0的子集。SetItemText也是如此。
代码操作使用:
1:首先需要使用vector容器保存要修改的变量。
此时,定义一个结构体,保存需要修改的内容
struct Insert_Text
{
int nItem; //哪一行
int Duan_num; //insert的段数
int begin_Datas; //初始段数的开始
int end_Datas; //到第几行结束
CString insert_Text; //InsertItem 未分解的字符串
int nStats; //是否被选择的状态
DWORD_PTR dwData; //使用在SetItemData中,相当于定义的别名
};
vector<Insert_Text> m_VectorInsert;
2:重写InsertItem、SetItemText这两个函数
int UIChangeListCtrl::InsertItem(_In_ int nItem, _In_z_ LPCTSTR lpszItem)
{
CString str = lpszItem;
int size = Decompostion_CStrings(str);
Insert_Text it;
//保存显示的取值范围
if (nItem == 0)
{
it.nItem = nItem;
it.Duan_num = size;
it.insert_Text = str;
it.begin_Datas = 0;
it.end_Datas = size-1;
it.nStats = 0;
}
else
{
it.nStats = 0;
it.nItem = nItem;
it.Duan_num = size;
it.insert_Text = str;
int m = m_VectorInsert[nItem-1].end_Datas;
it.begin_Datas = m+1;
it.end_Datas = it.begin_Datas+size-1;
}
m_VectorInsert.push_back(it);
InPutDatas();
return TRUE;
}
int UIChangeListCtrl::SetItemText(int nItem,int nSubItem, LPCTSTR lpszText)
{
CString str = lpszText;
int size = Decompostion_CStrings(str);
//判断vector中是否有相同的nItem
int vec_size = m_VectorInsert.size();
for (int i = 0; i < vec_size;i++)
{
if (m_VectorInsert[i].nItem == nItem)
{
//此时判断,无论nSubItem,获取最高的size
int max_Duan = m_VectorInsert[i].Duan_num;
max_Duan = max(max_Duan,size);
m_VectorInsert[i].Duan_num = max_Duan;
}
}
SetItem_text sit;
sit.nItem = nItem;
sit.nSubItem = nSubItem;
sit.set_Text = lpszText;
m_vectorSet.push_back(sit);
InPutDatas();
return TRUE;
}
3:定义InPutDatas重新规划CListCtrl内部插入数据,其实,改变行高这是最关键的部分。表示的可能有些繁琐,凑合着看
//重新规划CListCtrl
void UIChangeListCtrl::InPutDatas()
{
if (m_VectorInsert.size() ==0)
{
return;
}
//1、将所有的InsertItem、SetItemText的内容都存入map,并且当nItem相等时再画出这一行内容
int insert_size = m_VectorInsert.size();
//2、绘制InsertItem,把不足的begin,end补齐
for (int i = 0; i < insert_size;i++)
{
if (m_VectorInsert[i].nItem == 0)
{
m_VectorInsert[i].begin_Datas = 0;
m_VectorInsert[i].end_Datas = m_VectorInsert[i].begin_Datas+m_VectorInsert[i].Duan_num-1;
continue;
}
else
{
//此时的Text_begin 应该是上一个的nItem的Text_end
int nItem = m_VectorInsert[i].nItem-1;
int LastEnd = m_VectorInsert[nItem].end_Datas;
m_VectorInsert[i].begin_Datas = LastEnd+1;
m_VectorInsert[i].end_Datas = m_VectorInsert[i].begin_Datas+m_VectorInsert[i].Duan_num-1;
}
}
//循环解析字符串
for (int si = 0;si < m_VectorInsert.size();si++)
{
//把SetItemData的别名存入里面
for(int st = 0; st < m_vectorSave_datas.size();st++)
{
if (m_vectorSave_datas[st].nItem == m_VectorInsert[si].nItem)
{
m_VectorInsert[si].dwData = m_vectorSave_datas[st].save_dwData;
continue;
}
}
//对于InsetItemText的输入
InsetDrawText(si);
//SetItemText的解析
int set_sizes = m_vectorSet.size();
int nItem = m_VectorInsert[si].nItem;
CUIntArray SaveSetArray;
for (int set = 0; set < m_vectorSet.size();set++)
{
if (nItem == m_vectorSet[set].nItem)
{
SaveSetArray.Add(m_vectorSet[set].nSubItem);
}
}
int set_num = SaveSetArray.GetSize();
for (int m = 0; m < m_vectorSet.size();m++)
{
if (m_VectorInsert[si].nItem == m_vectorSet[m].nItem)
{
for (int snum = 0;snum < set_num;snum++)
{
//再判断nSbuItem相等时,取出字符串
if (m_vectorSet[m].nSubItem == (snum+1))
{
CString strSet = m_vectorSet[m].set_Text;
//解析字符串
CStringArray SetItemArray;
int m = 0;
for (CString sItem = strSet.Tokenize(_T("\n"),m);m>= 0;sItem = strSet.Tokenize(_T("\n"),m))
{
SetItemArray.Add(sItem);
}
if (SetItemArray.GetSize() < m_VectorInsert[si].Duan_num)
{
for (int m = SetItemArray.GetSize();m < m_VectorInsert[si].Duan_num;m++)
{
SetItemArray.InsertAt(m,_T(""));
}
}
int begin = m_VectorInsert[si].begin_Datas;
int itext = 0;
ZuoBiao zb;
while(itext< m_VectorInsert[si].Duan_num)
{
if (m_VectorInsert[si].end_Datas)
{
if (m_manySetDraw.size() == 0)
{
CListCtrl::SetItemText(begin,snum+1,SetItemArray[itext]);
zb.beginm = begin;
zb.colum = snum+1;
m_manySetDraw.push_back(zb);
CString str = SetItemArray[itext];
begin++;
itext++;
}
else if (m_manySetDraw.size() != 0)
{
for (int j = 0;j < m_manySetDraw.size();j++)
{
//如果再次进入循环的begin值和mm_manyDraw中有一个是相同的
if (m_manySetDraw[j].beginm == begin && m_manySetDraw[j].colum == snum+1)
{
begin++;
itext++;
continue;
}
}
if (begin <= m_VectorInsert[si].end_Datas)
{
CListCtrl::SetItemText(begin,snum+1,SetItemArray[itext]);
zb.beginm = begin;
zb.colum = snum+1;
m_manySetDraw.push_back(zb);
CString str = SetItemArray[itext];
begin++;
itext++;
}
}
}
}
}
}
}
}
}
}
此时使用这三个函数,再加上自绘的DrawItem已经可以实现界面上的行号不同了。
显示代码很多,我就不依次列举了。如有需要可以下载上传文件,我将.h和.cpp放在一起了。拆分后可以运行。
功能包括:表头的自绘、表本身实现系统的操作