http://www.eggheadcafe.com/software/aspnet/33811658/detect-changes-in-clistctrl-control-with-checkbox.aspx
Detect changes in ClistCtrl control with checkbox
Ajay Kalra posted on Wednesday, January 14, 2009 3:04 AM
On Jan 13, 11:31=A0am, asoni12 <ason...@>
Take a look at ListView_GetCheckState: http://msdn.microsoft.com/en-us/lib=
rary/bb761250(VS.85).aspx
and LVN_ITEMCHANGING: http://msdn.microsoft.com/en-us/library/bb774847(VS.=
85).aspx
--
Ajay
|
Reply
|
Detect changes in ClistCtrl control with checkbox
asoni1 posted on Tuesday, January 13, 2009 1:38 PM
Hi Ajay,
Thanks for the quick reply.
We get a pointer to an NMLISTVIEW structure in case of both both
LVN_ITEMCHANGING and LVN_ITEMCHANGED event handlers but with this structure
how can we make sure whether items’s checked/unchecked state has been
toggled or something else has changed?
I mean is there any bit in this structure member which is set/unset when the
state gets toggled?
|
Reply
|
In the LVN_ITEMCHANGED handler you can putint ns = pNMListView ->uNewState &
Ian Semmel posted on Tuesday, January 13, 2009 2:29 PM
In the LVN_ITEMCHANGED handler you can put
int ns = pNMListView ->uNewState & LVIS_STATEIMAGEMASK;
if ( ( ns & 0x2000 ) != 0 )
// Checkbox set
else if ( ( ns & 0x1000 ) != 0 )
// Checkbox unset
else
// Something else happened
|
Reply
|
Detect changes in ClistCtrl control with checkbox
Tom Serface posted on Tuesday, January 13, 2009 4:49 PM
ON_NOTIFY(NM_CLICK, IDC_LIST, &CSpanRestoreDlg::OnNMClickList)
// Check or uncheck item. If more than one item is selected then use the
one from the
// hit test to determine how we are setting the others (I.E., if it is off
we turn the other
// selected ones on).
void CMyDlg::OnNMClickList(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
LVHITTESTINFO hitinfo;
*pResult = 0;
bool bChecked = false;
//Copy click point
hitinfo.pt = pNMListView->ptAction;
//Make the hit test...
int nItem = m_cList.HitTest(&hitinfo);
if(hitinfo.flags != LVHT_ONITEMSTATEICON)
return; // Didn't click on an icon
if(m_cList.GetItemState(nItem,LVIS_SELECTED) != LVIS_SELECTED) {
// They clicked on one that is not selected... just change it
// ... do something here
bChecked = m_cList.GetCheck(nItem);
bChecked = !bChecked;
m_cList.SetCheck(nItem,bChecked);
*pResult = 1;
return;
}
// Get the checked state from the one they clicked on, but change all
the ones that are selected
UINT uSelectedCount = m_cList.GetSelectedCount();
// Update all of the selected items.
if (uSelectedCount > 0) {
nItem = -1;
m_cList.SetRedraw(false);
for (UINT i=0;i < uSelectedCount;i++) {
nItem = m_cList.GetNextItem(nItem, LVNI_SELECTED);
m_cList.SetCheck(nItem,bChecked);
}
*pResult = 1;
m_cList.Invalidate();
m_cList.SetRedraw();
}
}
Tom
|
Reply
|
Thanks Ian.
asoni1 posted on Wednesday, January 14, 2009 2:54 AM
Thanks Ian. I did it this way and it works fine for me-
I just wanted to confirm, since I am using constant 0x2000 and 0x1000 here,
can I be sure that these checks will not be bricked in some other environment
like other version of windows OS or Visual Studio?
int oldState = -1;
int newState = -1;
int changedState= -1;
int ns1 = pNMLV->uOldState & LVIS_STATEIMAGEMASK;
int ns2 = pNMLV->uNewState & LVIS_STATEIMAGEMASK;
if ((ns1 & 0x2000) != 0)// find the previous state
{ //Checkbox set
oldState = 1;
}
else if ((ns1 & 0x1000) != 0)
{
//Checkbox unset
oldState = 0;
}
if (-1 != oldState)// If got the previous state then find the new state
{
if ((ns2 & 0x2000) != 0)
{ //Checkbox set
newState = 1;
}
else if ((ns2 & 0x1000) != 0 )
{
//Checkbox unset
newState = 0;
}
if ( (-1 != newState) && (oldState != newState))
{
changedState = newState - oldState;
if (1 == changedState)
{
AfxMessageBox(_T("Item has been checked"));
}
else if (-1 == changedState)
{
AfxMessageBox(_T("Item has been unchecked"));
}
}
}
|
Reply
|
Detect changes in ClistCtrl control with checkbox
Sanoop Das K posted on Saturday, February 28, 2009 4:06 PM
|
通过ClassWizard 属性页或WizardBar,ClassWizard可以创建ON_NOTIFY消息映射实体,并提供处理函数体。要了解更多使用ClassWizard的信息,请参看Visual C++ Programmer's Guide的Mapping Messages to Functions。
ON_NOTIFY消息映射宏格式如下:
ON_NOTIFY(wNotifyCode, id, memberFxn)
wNotifyCode
要处理的提醒消息的代码,如LVN_KEYDOWN。
id
发送提醒消息的控件ID
memberFxn
提醒消息的处理函数
处理函数的原型如下:
afx_msg void memberFxn(NMHDR * pNotifyStruct, LRESULT * result);
pNotifyStruct
上文中描述的参数结构体
result
在函数返回前应设置的返回代码
例子
要使成员函数OnKeydownList1处理ID为IDC_LIST1的CListCtrl发送的LVN_KEYDOWN消息,可以用ClassWizard添加以下代码到消息映射中:
ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeydownList1)
ClassWizard提供的函数体为:
void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
注意,ClassWizard自动提供了参数的指针,可以直接使用pNMHDR或pLVKEYDOW来访问提醒结构体。
ON_NOTIFY_RANGE
若需要为一组控件处理相同的WM_NOTIFY消息,可以使用ON_NOTIFY_RANGE来代替ON_NOTIFY。例如,可以让一组按钮为某一提醒消息执行相同的操作。
当使用ON_NOTIFY_RANGE,需要指定一组连续的控件ID,用于指定控件组的起始ID与结束ID。
ClassWizard并不会处理ON_NOTIFY_RANGE,要使用它,需要手动添加消息映射。
ON_NOTIFY_RANGE的消息映射实体及函数原因如下:
ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn)
wNotifyCode
要处理的提醒消息的代码,如LVN_KEYDOWN。
id
控件组的起始ID
idLast
控件组的结束ID
memberFxn
提醒消息的处理函数
处理函数的原型如下:
afx_msg void memberFxn(NMHDR * pNotifyStruct, LRESULT * result);
pNotifyStruct
上文中描述的参数结构体
result
在函数返回前应设置的返回代码
ON_NOTIFY_EX,ON_NOTIFY_EX_RANGE
若希望由多个对象处理提醒消息,可以使用ON_NOTIFY_EX(或ON_NOTIFY_EX_RANGE)来代替ON_NOTIFY(或ON_NOTIFY_RANGE)。EX版与常规版本的区别在于,EX版的处理函数有BOOL型的返回值,以决定消息的处理是否应该继续。若返回FALSE,则消息可以被多个对象处理。
ClassWizard并不处理ON_NOTIFY_EX或ON_NOTIFY_EX_RANGE;要使用它们,需要手动添加消息映射。
ON_NOTIFY_EX和ON_NOTIFY_EX_RANGE的消息映射实体及函数原型发下,参数的含义与常规版本一致:
ON_NOTIFY_EX(nCode, id, memberFxn)
ON_NOTIFY_EX_RANGE(wNotifyCode, id, idLast, memberFxn)
两者的函数原型均为:
afx_msg BOOL memberFxn(UINT id, NMHDR * pNotifyStruct, LRESULT * result);
id表示发送提醒的控件的ID。
若提醒消息已被处理完,函数应返回TRUE;否则,若需要进一步处理,函数返回FALSE。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wsxz_wsxz/archive/2010/02/27/5332412.aspx