奇怪的 自绘listctrl

zrdongjiao 2013-06-17 01:30:07
需求:listctrl中插入一个进度条,每一行都有进度条

csdn上看到一个帖子,和我的需求相关,于是 运行了一下代码,发现可行,只是不知道运作原理。

代码为:


listctrl中嵌入一个processctrl

代码来自csdn




对话框调用代码:
CMyListCtrl m_listCtrl;
m_listCtrl.InsertUserData();
m_listCtrl.InsertUserData();






listctrl的风格为view: report, owner draw fixed:true


封装的ListCtrl代码

//ListCtrl.h

#pragma once
#include<vector>
using std::vector;


//{"软件名字" ,"软件大小", "软件类别", "安装", "安装进度"};

typedef struct tagListCtrlData
{
TCHAR szSoftName[100];
TCHAR szSoftSize[20]; //用户使用的时候格式化字符串即可
TCHAR szSoftType[20];
TCHAR szSoftAction[20]; //软件行为:安装否,这里仅仅是一个演示
CProgressCtrl m_pProgressCtrl; //进度条
}ListCtrlData,* PListCtrlData;





class CMyListCtrl : public CListCtrl
{
DECLARE_DYNAMIC(CMyListCtrl)
private:
vector<PListCtrlData> m_progressPtrVec; //保存指针

public:
CMyListCtrl();
virtual ~CMyListCtrl();

public:
BOOL InsertUserData(); //暂时只演示进度条

protected:
DECLARE_MESSAGE_MAP()
public:
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
protected:
virtual void PreSubclassWindow();
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
};



//ListCtrl.cpp


#include "stdafx.h"

#include "MyListCtrl.h"

#define PROCESS_CTRL_ID 2000

IMPLEMENT_DYNAMIC(CMyListCtrl, CListCtrl)

CMyListCtrl::CMyListCtrl()
{

}

CMyListCtrl::~CMyListCtrl()
{
}


BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
END_MESSAGE_MAP()



void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
PListCtrlData pListCtrlData=m_progressPtrVec[lpDrawItemStruct->itemID];
if(pListCtrlData)
{
CRect subRC;
GetSubItemRect(lpDrawItemStruct->itemID,4,LVIR_BOUNDS ,subRC);
pListCtrlData->m_pProgressCtrl.MoveWindow(&subRC);
pListCtrlData->m_pProgressCtrl.ShowWindow(SW_SHOW);
}
}


void CMyListCtrl::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类

//增加ListCtrl列头
LVCOLUMN lvc = {LVCF_FMT | LVCF_TEXT | LVCF_WIDTH};
TCHAR* pszText[] = {_T("软件名字") ,_T("软件大小"), _T("软件类别"), _T("安装"), _T("安装进度")};
int cx[] = {150, 100, 150, 45, 500};
int i=0;
for (i = 0; i < sizeof(cx) / sizeof(int); i ++)
{
lvc.pszText = pszText[i];
lvc.cx = cx[i];
lvc.fmt = LVCFMT_CENTER;
InsertColumn(i, &lvc);
}

CListCtrl::PreSubclassWindow();
}



BOOL CMyListCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此添加专用代码和/或调用基类

return CListCtrl::PreCreateWindow(cs);
}


BOOL CMyListCtrl::InsertUserData()
{
PListCtrlData pListCtrl=new ListCtrlData();
ASSERT(pListCtrl);
m_progressPtrVec.push_back(pListCtrl);
static int nStep=0;
InsertItem(nStep,NULL); //问题在这里,为什么会有这么奇怪的代码??? 插入空行! 我去掉后, 则不会出现进度条
nStep++;
RECT rect={0,0,0,0};
pListCtrl->m_pProgressCtrl.Create(WS_CHILD,rect,this,PROCESS_CTRL_ID+nStep);
pListCtrl->m_pProgressCtrl.SetRange(0,99);
pListCtrl->m_pProgressCtrl.SetStep(10);
pListCtrl->m_pProgressCtrl.SetPos(10);
return TRUE;
}






...全文
147 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
sumos 2013-06-17
  • 打赏
  • 举报
回复
DT_SINGLELINE|DT_VCENTER | DT_LEFT
sumos 2013-06-17
  • 打赏
  • 举报
回复
引用 6 楼 zrdongjiao 的回复:
[quote=引用 5 楼 dahaiI0 的回复:] 数据应该没错,看了下MSDN iSubItem The one-based index of the subitem. 参数是基于1的索引,估计如果0的话是获取整个ITEM的rect
额额, 多谢,那么如何取第0列的矩形区域呢 我也看了msdn,没有找到啊 [/quote] CRect GetSubItemRect(int row,int col) { CRect rc; CListCtrl::GetSubItemRect(row,col,LVIR_BOUNDS,&rc); if(col == 0) { int w = CListCtrl::GetColumnWidth(0); rc.right = rc.left + w; } return rc; }
zrdongjiao 2013-06-17
  • 打赏
  • 举报
回复
引用 5 楼 dahaiI0 的回复:
数据应该没错,看了下MSDN iSubItem The one-based index of the subitem. 参数是基于1的索引,估计如果0的话是获取整个ITEM的rect
额额, 多谢,那么如何取第0列的矩形区域呢 我也看了msdn,没有找到啊
dahaiI0 2013-06-17
  • 打赏
  • 举报
回复
数据应该没错,看了下MSDN iSubItem The one-based index of the subitem. 参数是基于1的索引,估计如果0的话是获取整个ITEM的rect
zrdongjiao 2013-06-17
  • 打赏
  • 举报
回复
引用 3 楼 dahaiI0 的回复:
DrawText画的是pListCtrlData->szSoftName,又不是str,DT_CENTER改成DT_LEFT看下。 另外第0列的值不应该会这么宽
多谢搞定 换了个参数成功了。 不过,我关观察了一下, 第0列的值依然 为: rc = {top=18 bottom=36 left=0 right=945} 区域确实很大 在代码里修改为第1列,就发现,没有这个问题。 GetSubItemRect(lpDrawItemStruct->itemID,1,LVIR_BOUNDS ,rc); 难道 是第0列非常特殊?
dahaiI0 2013-06-17
  • 打赏
  • 举报
回复
DrawText画的是pListCtrlData->szSoftName,又不是str,DT_CENTER改成DT_LEFT看下。 另外第0列的值不应该会这么宽
zrdongjiao 2013-06-17
  • 打赏
  • 举报
回复
引用 1 楼 dahaiI0 的回复:
InsertItem是插入一行数据,注释掉肯定什么都没有,第二个参数是第一列的数据,插入一行后可以用 SetITemText设置其他列的数据
在这个基础上修改了一下: if(pListCtrlData) { CRect rc; GetSubItemRect(lpDrawItemStruct->itemID,4,LVIR_BOUNDS ,rc); pListCtrlData->m_pProgressCtrl.MoveWindow(&rc); pListCtrlData->m_pProgressCtrl.ShowWindow(SW_SHOW); GetSubItemRect(lpDrawItemStruct->itemID,0,LVIR_BOUNDS ,rc); CString str; str=_T("xxxx"); //GetItemText(lpDrawItemStruct->itemID,0); DrawText(lpDrawItemStruct->hDC,pListCtrlData->szSoftName,lstrlen(pListCtrlData->szSoftName),rc,DT_CENTER|DT_SINGLELINE); } 好奇怪,进度条出现了,但是 第0行没有显示字符串:xxxx DrawText(lpDrawItemStruct->hDC,pListCtrlData->szSoftName,lstrlen(pListCtrlData->szSoftName),rc,DT_CENTER|DT_SINGLELINE); 你看我的参数,是对的啊 难道是 是rc的值导致的吗? 观察: 第4列的值: rc = {top=18 bottom=36 left=445 right=945} 第0列的值: rc = {top=18 bottom=36 left=0 right=945}
dahaiI0 2013-06-17
  • 打赏
  • 举报
回复
InsertItem是插入一行数据,注释掉肯定什么都没有,第二个参数是第一列的数据,插入一行后可以用 SetITemText设置其他列的数据

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧