让 ClistCtrl中 的 CheckBox 实现 单选

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

posted on 2011-02-18 16:53  cy163  阅读(4802)  评论(0编辑  收藏  举报

导航