如何获取List控件头上的复选框的检查状态?

时间:2014-09-05 07:31:17

标签: visual-c++ mfc

我有一个属性表,在第二页中我有一个listcontrol,其中列表控件包含每个项目的复选框。对于第一个标题,我在列标题上添加了一个复选框图像。当我单击复选框时在列标题上,然后所有复选框的状态都根据列标题复选框进行更改。当我单击列表控件中的任何项目时,我启用向导按钮,如果没有选择任何内容下一步和后退按钮将被禁用。到目前为止一切都还可以。但正如我告诉你的那样,我在列标题上添加了一个复选框图像,现在如果我点击列标题,列表控件中的所有项目都将获得检查状态,我再次点击现在,在列标题复选框上,列表控件中的所有项都将取消选中。

正如我告诉你的那样,根据检查状态,我启用了向导按钮。现在,对于这个标题,我在一个派生自" CHeaderCtrl"的类中添加了一个事件。 - " HDN_ITEMCLICK"当我点击标题时它会转到这个事件处理程序,但是从这里我如何根据该事件中的标题检查状态禁用向导按钮。

//Second page where it does contain the list control.
//A class is derived from cListCtrl
//A class is derived from CHeaderCtrl

//In Page Class
BOOL OnInitDialog()
{
  CPropertyPage::OnInitDialog();
  m_listCtrl.Init();//CCheckListCtrl m_listCtrl ;
}
void CMFPSearchListView::OnItemClick(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
int list_row;
list_row = pNMItemActivate->iItem;
int list_col ;
list_col = pNMItemActivate->iSubItem;
int listcount = m_listCtrl.GetItemCount();
BOOL bRet = m_listCtrl.GetCheck(list_row);  
if(TRUE != bRet)
{

    CPropertySheet *TestSheet = (CPropertySheet*)GetParent();
    TestSheet->SetWizardButtons(PSWIZB_NEXT|PSWIZB_BACK);
}
else
{
            //Here I am setting the wizard buttons depending on the Item Check state
    CPropertySheet *TestSheet = (CPropertySheet*)GetParent();
    TestSheet->SetWizardButtons(PSWIZB_CANCEL);
}


*pResult = 0;
}

//In the CCheckListCtrl class(derived from ClistCtrl)
//LVN_ITEMCHANGED

void CCheckListCtrl::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
int row ;
row = pNMLV->iItem;
int col ;
col = pNMLV->iSubItem;
*pResult = 0;

if ( m_blInited && LVIF_STATE == pNMLV->uChanged)
{
    BOOL blAllChecked = TRUE;
    int nCount = GetItemCount();
    for(int nItem = 0; nItem < nCount; nItem++)
    {
        if ( !ListView_GetCheckState(GetSafeHwnd(), nItem) )
        {
            blAllChecked = FALSE;
            break;
        }
    }

    HDITEM hdItem;
    hdItem.mask = HDI_IMAGE;
    if (blAllChecked)
        hdItem.iImage = 2;//0;//2;
    else
        hdItem.iImage = 1;
    VERIFY( m_checkHeadCtrl.SetItem(0, &hdItem) );
}

*pResult = 0;
}
BOOL CCheckListCtrl::Init()
{
if (m_blInited)
    return TRUE;

HINSTANCE hBmpInst = ::LoadLibrary(L"BmpRes.dll");
AfxSetResourceHandle(hBmpInst);
CHeaderCtrl* pHeadCtrl = this->GetHeaderCtrl();
ASSERT(pHeadCtrl->GetSafeHwnd());

VERIFY( m_checkHeadCtrl.SubclassWindow(pHeadCtrl->GetSafeHwnd()) );

INT ImgRet = m_checkImgList->Create(IDB_BMP_CHECKBOX_STATE, 16, 2, RGB(255,0,255)) ;
int i = m_checkImgList->GetImageCount();
m_checkHeadCtrl.SetImageList(m_checkImgList);

HDITEM hdItem;
hdItem.mask = HDI_IMAGE | HDI_FORMAT;
VERIFY( m_checkHeadCtrl.GetItem(0, &hdItem) );
hdItem.iImage = 1;
hdItem.fmt |= HDF_IMAGE;

VERIFY( m_checkHeadCtrl.SetItem(0, &hdItem) );

m_blInited = TRUE;
if(NULL!=hBmpInst)
{  
   ::FreeLibrary(hBmpInst);
   hBmpInst=NULL;
}
return TRUE;
}
//In CheckHeaderCtrl class (derived from CHeaderCtrl)
//HDN_ITEMCLICK
void CCheckHeadCtrl::OnHdnItemclick(NMHDR *pNMHDR, LRESULT *pResult)
{
NMHEADER* pNMHead = (NMHEADER*)pNMHDR;
*pResult = 0;

int nItem = pNMHead->iItem;
if (0 != nItem)
    return;

HDITEM hdItem;
hdItem.mask = HDI_IMAGE;
VERIFY( GetItem(nItem, &hdItem) );

if (hdItem.iImage == 1)
    hdItem.iImage = 2;
else
    hdItem.iImage = 1;

VERIFY( SetItem(nItem, &hdItem) );

BOOL bl = hdItem.iImage == 2 ? TRUE : FALSE;
CListCtrl* pListCtrl = (CListCtrl*)GetParent();
int nCount = pListCtrl->GetItemCount(); 
for(nItem = 0; nItem < nCount; nItem++)
{
    ListView_SetCheckState(pListCtrl->GetSafeHwnd(), nItem, bl);
}
*pResult = 0;
}

你可以观察到所有这些都是为listcontrol,Headerctrl和propertypage实现了三个不同的类。如果你在propertypage中可以看到你可以观察OnItemClick事件我正在设置向导按钮,同样我必须设置何时调用OnHdnItemclick事件。当我点击标题时它正在调试OnHdnItemclick,然后它正在点击OnLvnItemChanged,但是没有进入我的页面类,任何人都可以帮助我,如何在标题点击事件上设置向导按钮。

1 个答案:

答案 0 :(得分:0)

您可以使用CHeaderCtrl::GetItem从标题控件的已点击列中获取HDITEM信息。

一旦你有了这个,你需要检查掩码是否设置了HDI_FORMAT位,并假设它(这意味着fmt成员有有效数据),查找{{ 1}}在HDF_CHECKED结构的fmt成员中标记,以确定是否选中了复选框。

所以在伪代码中:

HDITEM