鱼C论坛

 找回密码
 立即注册
查看: 612|回复: 7

[已解决]CListCtrl--NM_CLICK

[复制链接]
发表于 2023-5-2 11:36:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
void CCListCtrlDlg::OnNMClickList4(NMHDR* pNMHDR, LRESULT* pResult)
{
        LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
        //NM_CLICK 这个是鼠标左键点击CListCtrl控件客户区时激发的消息

        int han = pNMItemActivate->iItem; //获取单击的行号
        /*
        【最好设置:LVS_EX_FULLROWSELECT //选择整行;否则只有单击项头才有效】
        */

        str.Format(_T("行号han=%d\r\n"), han);
        OutputDebugString(str);
        
        int lie = pNMItemActivate->iSubItem;  //获取单击的列号


        str.Format(_T("列号lie=%d\r\n"), lie);
        OutputDebugString(str);

        UINT ns=pNMItemActivate->uNewState;
        str.Format(_T("新状态ns=%d\r\n"), ns);
        OutputDebugString(str);

        UINT olds = pNMItemActivate->uOldState;
        str.Format(_T("老状态olds=%d\r\n"), olds);
        OutputDebugString(str);



        *pResult = 0;
}



我的问题:新状态和老状态返回值都是0    ??
               单击后   应该被选中了   起码有个选中状态,我认为新状态的返回值不应该是  0      ??




最佳答案
2023-5-2 12:36:24
您的代码是一个处理CListCtrl控件单击事件的函数。从您的描述中,我了解到您遇到的问题是新状态(new state)和旧状态(old state)的返回值都是0,而您期望当单击后,新状态应该有一个选中状态。

首先,请确保您的CListCtrl控件已经设置了单选模式和整行选择模式。您可以在对话框的OnInitDialog()方法中添加以下代码来设置这些模式:
m_listCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_ONECLICKACTIVATE);
其中,m_listCtrl是CListCtrl控件的对象。这样设置后,当您单击某一行时,整行都将被选中。

然后,在处理单击事件的函数中,您需要使用GetItemState方法来获取新状态(new state)和旧状态(old state)。NMITEMACTIVATE结构体中的uNewState和uOldState成员主要用于响应其他类型的通知消息,如LVN_ITEMCHANGED。在处理NM_CLICK消息时,您可以使用以下代码来获取新状态和旧状态:
UINT ns = m_listCtrl.GetItemState(han, LVIS_SELECTED);
str.Format(_T("新状态ns=%d\r\n"), ns);
OutputDebugString(str);

UINT olds = m_listCtrl.GetItemState(han, LVIS_SELECTED) ? 0 : LVIS_SELECTED;
str.Format(_T("老状态olds=%d\r\n"), olds);
OutputDebugString(str);
这里,m_listCtrl是CListCtrl控件的对象。GetItemState方法需要两个参数:项的索引(index)和状态掩码(state mask)。在这个例子中,我们使用LVIS_SELECTED作为状态掩码,表示我们只关心选中状态。

上面的代码将获取新状态和旧状态,并将它们的值分别输出到调试窗口。请尝试使用这些修改后的代码,看看是否能解决您遇到的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

匿名鱼油
匿名鱼油  发表于 2023-5-2 11:37:12
回答:可能是因为你的列表控件设置了不可选中,导致新状态和老状态都是0。你可以在初始化列表控件的代码中添加以下语句,开启整行选择功能:

m_listCtrl.SetExtendedStyle(m_listCtrl.GetExtendedStyle() | LVS_EX_FULLROWSELECT);

这样就可以正常获取新状态和老状态了。
回复 支持 反对

使用道具 举报

发表于 2023-5-2 11:37:21 | 显示全部楼层
根据您提供的代码,可以看到NM_CLICK消息中的NMITEMACTIVATE结构体中包含了两个状态变量uOldState和uNewState,它们分别表示单击(或右键单击)前和单击(或右键单击)后子项的状态。如果在调试中发现这两个变量都为0,可能是由于CListCtrl控件的样式设置不正确而导致的。

默认情况下,CListCtrl控件只在单击行头时才选择整行。如果要使用户单击列表中任意位置都可以选择整行并激活NM_CLICK消息,您需要设置以下样式:
m_listCtrl.SetExtendedStyle(m_listCtrl.GetExtendedStyle() | LVS_EX_FULLROWSELECT);
此外,还有一种情况会导致uOldState和uNewState都为0,就是当用户试图多选时,即同时按下shift或ctrl键单击两个或多个项目时。

如果问题仍然存在,请尝试在代码中加入一些断点,并检查计算过程中是否有漏掉的细节。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-2 11:37:51 | 显示全部楼层
NMITEMACTIVATE 结构体的 uNewState 和 uOldState 成员表示鼠标点击事件后的新状态和旧状态,它们是可以组合多个位标志来表示多种状态的。

在你的代码中,uNewState 和 uOldState 都具有0的值,这意味着没有状态被设置。这很可能是因为列表控件没有配置以报告项目状态更改。你可以调用 CListCtrl::SetExtendedStyle 方法,并指定 LVS_EX_FULLROWSELECT 标志来启用此功能,就像你代码中的注释所示。

启用此标志后,列表控件将突出显示所选项目,当项目被点击时,NMITEMACTIVATE 结构体的 uNewState 成员应该具有 LVIS_SELECTED(0x0002)的值。同样地,如果项目之前已经被选择,则 uOldState 成员将具有相同的值。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-2 11:43:04 | 显示全部楼层
mylist4.SetExtendedStyle(mylist4.GetExtendedStyle() |LVS_REPORT | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);//指定报表显示格式

但是  新老状态 还是都返回 0
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-2 12:17:00 | 显示全部楼层
根据您提供的代码和问题,我可以看出您正在处理 `CListCtrl` 控件的单击事件,并尝试使用以下代码行来获取有关被点击项的信息:
UINT ns=pNMItemActivate->uNewState;
str.Format(_T("新状态ns=%d\r\n"), ns);
OutputDebugString(str);

UINT olds = pNMItemActivate->uOldState;
str.Format(_T("老状态olds=%d\r\n"), olds);
OutputDebugString(str);

但是,您注意到即使您单击了某个项,这些状态值都为0。这可能是因为没有设置需要选中项的样式属性。

您可以在对话框初始化期间使用以下代码行启用选择项:

m_listControl.SetExtendedStyle(m_listControl.GetExtendedStyle() | LVS_EX_FULLROWSELECT);

这将通过启用 `LVS_EX_FULLROWSELECT` 样式属性,指定每次用户单击Listctrl时选择整行而不是仅选择项目,来激活选择。

此后,您应该能够正确地获取有关选定行的新和旧状态信息。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-2 12:32:10 | 显示全部楼层
根据您的代码,您已经正确地设置了选择模式,应该能够获取到新老状态的值,因此问题可能出在其他地方。以下是一些可能的原因:

1、是否已经正确地配置了CListCtrl控件的通知消息?

        您需要确保您已经为控件分配了ID,并在响应它时注册相应的WM_NOTIFY消息。

2、是否正确地创建了CImageList对象?

        LVS_EX_CHECKBOXES要求将图像列表分配给控件以显示复选框。如果未给控件分配图片列表,则可能导致控件无法显示复选框或返回错误的状态信息。

3、其他原因

        如果您尝试从OnNMCustomDraw()消息处理程序中获取状态,那么您可能必须调用DefWindowProc()来接收默认的类处理,否则您的消息很可能被忽略。

        您也可以使用其他方法(如GetItemState()) 来获取选定项的状态。

请检查这些原因,并尝试修复您的代码以获得正确的状态。
还有,以后要回复请点击下面的“回复”,不然收不到你的消息
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-2 12:36:24 | 显示全部楼层    本楼为最佳答案   
您的代码是一个处理CListCtrl控件单击事件的函数。从您的描述中,我了解到您遇到的问题是新状态(new state)和旧状态(old state)的返回值都是0,而您期望当单击后,新状态应该有一个选中状态。

首先,请确保您的CListCtrl控件已经设置了单选模式和整行选择模式。您可以在对话框的OnInitDialog()方法中添加以下代码来设置这些模式:
m_listCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_ONECLICKACTIVATE);
其中,m_listCtrl是CListCtrl控件的对象。这样设置后,当您单击某一行时,整行都将被选中。

然后,在处理单击事件的函数中,您需要使用GetItemState方法来获取新状态(new state)和旧状态(old state)。NMITEMACTIVATE结构体中的uNewState和uOldState成员主要用于响应其他类型的通知消息,如LVN_ITEMCHANGED。在处理NM_CLICK消息时,您可以使用以下代码来获取新状态和旧状态:
UINT ns = m_listCtrl.GetItemState(han, LVIS_SELECTED);
str.Format(_T("新状态ns=%d\r\n"), ns);
OutputDebugString(str);

UINT olds = m_listCtrl.GetItemState(han, LVIS_SELECTED) ? 0 : LVIS_SELECTED;
str.Format(_T("老状态olds=%d\r\n"), olds);
OutputDebugString(str);
这里,m_listCtrl是CListCtrl控件的对象。GetItemState方法需要两个参数:项的索引(index)和状态掩码(state mask)。在这个例子中,我们使用LVIS_SELECTED作为状态掩码,表示我们只关心选中状态。

上面的代码将获取新状态和旧状态,并将它们的值分别输出到调试窗口。请尝试使用这些修改后的代码,看看是否能解决您遇到的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-21 22:09

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表