分享
 
 
 

编辑ListViewSubItem的一种另的方法

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

编辑ListView Ctrl任一SubItem的一种另类的方法,欢迎大家讨论,一起来找出更简单的办法,没用MFC,用VB的朋友也可以来讨论思路。

在ListView控件中,有一个EditLabel选项,如果仅仅只要编辑第一Column(也就是Label)的内容,那是非常容易的,这里就不讨论了。编辑每一个SubItem在MSDN也好像也没有讲(我自己还没有找到资料), 在CodeGuru上面这方面讲的比较多,我找了一下,不过都是用MFC做的,感觉代码很多,我没有非常仔细的看下去。

当然,实现此项功能一般也不会用到,所以高手们也没有顾及到。不过我却曾经应聘碰到过考官出这样的题目,当时一听我就懵了,搞得后面的回答也一塌糊涂,把一张老脸给丢了个精光,这是题外话。

下面来写写我的思路

我个人的考虑是,首先判断在ListCtrl选定的是哪个SubItem,只要获得了这个SubItem的iItem和iSubItem,其他的问题就会很好解决(在VB中,此项应该更加容易)。 既然得知了是哪个SubItem被选择,那么就可以创建一个Edit类型的子窗口,把这个子窗口放在SubItem的位置,子窗口失去焦点后就将这个Edit的内容来修改SubItem的内容就搞定了。

首先是获取SubItem的位置,即它的行和列。如果将这个ListCtrl的风格设置为LVS_EX_FULLROWSELECT的话,点击使用MFC的GetNextItem(-1, LVNI_SELECTED)函数或者使用GetFirstSelectedItem()和GetNextSelectItem()就可以获得,问题是,如果没有将其风格设置为LVS_EX_FULLROWSELECT的时候,使用GetNextItem(-1, LVNI_SELECTED)在没有点击Label(也就是第一个Column)的时候,是不能返回其iItem的。所以么另想办法。

可以这样:在点击ListCtrl时,控件会向其父窗口发送WM_NOTIFY消息,在此消息中,包含了我们需要的信息。

在响应WM_NOTIFY消息的时候,转换其参数lParam为NMHDR结构,其code字段如果为NM_CLICK就可以判断出是点击了ListCtrl控件。再将其转换为NMLISTVIEW结构,就可以获取我们需要iItem, iSubItem等字段。以下是模仿

MSDN的写法:

switch (((LPNMHDR) lParam)->code) {

case NM_CLICK:

#define pnm ((LPNMLISTVIEW)lParam)

POINT pt;

int iSubItem;

pt = pnm->ptAction;

iSubItem = pnm->iSubItem;

#undef pnm

……………………

现在获得了SubItem的位置资料,发送消息::SendMessage(HWND, LVM_GETSUBITEMRECT, WPARAM, LPARAM)就可以获得SubItem处的矩形了。

获得了SubItem处的矩形,然后调用CreateWindow来创建Edit子窗口就非常容易了。具体请看源代码

(Demo Project和其完整源代码在此下载)

BOOL CEditListCtrlDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)

{

// TODO: Add your specialized code here and/or call the base class

switch (((LPNMHDR) lParam)->code) {

case NM_CLICK:

#define pnm ((LPNMLISTVIEW)lParam)

POINT pt;

RECT rect;

int iHeight;

int s_iItem;

int s_iSubItem;

pt = pnm->ptAction;

s_iSubItem = pnm->iSubItem;

ListView_GetSubItemRect(m_List.m_hWnd, 0, s_iSubItem, LVIR_BOUNDS, &rect);

#undef pnm

iHeight = rect.bottom - rect.top;

s_iItem = floor(pt.y / iHeight) - 1;

if (bClick) file://判断是否是第二次点击同一个SubItem

{

if (s_iItem != iItem || s_iSubItem != iSubItem)

{

iItem = s_iItem;

iSubItem = s_iSubItem;

break;

}

}

else

{

bClick = true;

iItem = s_iItem;

iSubItem = s_iSubItem;

break;

}

if (iItem >= ::SendMessage(m_List.m_hWnd, LVM_GETITEMCOUNT, 0, 0))

break; file://如果点击处没有Item,这退出

ListView_GetSubItemRect(m_List.m_hWnd, iItem, iSubItem, LVIR_LABEL, &rect); file://得到SubItem的矩形

bCreateEdit(rect, iItem, iSubItem);

break;

}

return CDialog::OnNotify(wParam, lParam, pResult);

}

/**********************************************************************

bCreateEdit函数在ListView Ctrl的SubItem位置创建一个Edit的子窗口,用这个子窗口来取得对

SubItem文本的改变,如果创建成功则返回true,如果失败,则返回false

rect为一大小和位置都与SubItem对应的矩形,iItem为当前选择的Item,iSubItem为当前选择SubItem

**********************************************************************/

bool CEditListCtrlDlg::bCreateEdit(const RECT & rect, int iItem, int iSubItem)

{

int iLeft;

int iTextWidth;

char * lpszText = new char[100];

ListView_GetItemText(m_List.m_hWnd, iItem, iSubItem, lpszText, 100); file://get subitem text

GetLeft_Width(iLeft, iTextWidth, strlen(lpszText), rect); file://确定创建的窗口的位置和宽度

if (iSubItem == 0)

iLeft = rect.left + 2;

::Sleep(300);

hwndEdit = CreateWindow(_T("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, iLeft, rect.top - 1, iTextWidth + 5, (rect.bottom - rect.top + 3), m_List.m_hWnd, (HMENU)1313, (HINSTANCE)GetWindowLong(this->m_hWnd, GWL_HINSTANCE), NULL); file://创建窗口

if (hwndEdit == NULL)

{

delete [] lpszText;

return false;

}

HFONT listFont = (HFONT)::SendMessage(m_List.m_hWnd, WM_GETFONT, (WPARAM)0, (LPARAM)0);

::SendMessage(hwndEdit, WM_SETFONT, (WPARAM)listFont, MAKELPARAM(FALSE, 0));

::SetWindowText(hwndEdit, lpszText); file://设置创建的窗口的字体和初始的文本为SubItem的文本

delete [] lpszText;

::SetFocus(hwndEdit);

::SendMessage(hwndEdit, EM_SETSEL, (WPARAM)(INT)0, (LPARAM)(INT)-1); file://窗口的文本全部选定,类似于系统的风格

return true;

}

/*****************************************************************************************

函数GetLeft_Width()为将要创建的Edit子窗口所在的位置和宽度,它要根据SubItem的长度来确定

iLeft为子窗口所在的位置的Left的应用,iTextWidth为SubItem的字符串的逻辑长度,rect为对应

SubItem的矩形,iLenStr为SubItem的字符个数

******************************************************************************************/

void CEditListCtrlDlg :: GetLeft_Width(int & iLeft, int & iTextWidth, int iLenStr, const RECT & rect)

{

TEXTMETRIC tm;

int iRectWidth;

iRectWidth = rect.right - rect.left;

HDC hdc = ::GetWindowDC(m_List.m_hWnd);

::GetTextMetrics(hdc, &tm);

::ReleaseDC(m_List.m_hWnd, hdc);

iTextWidth = tm.tmAveCharWidth * iLenStr;

if (iRectWidth > iTextWidth)

iLeft = rect.left + (iRectWidth - iTextWidth) / 2 + 1;

else

iLeft = rect.left + 2;

if (iLenStr == 0)

{

iLeft = rect.left + iRectWidth / 4;

iTextWidth = iRectWidth / 2;

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有