CMFCShellListCtrl使用方法

CMFCShellListCtrl是个很有用的新类,用它可以直接构造出文件/文件夹选择页面,先看看结果图

CMFCShellListCtrl使用方法_第1张图片

1.替换中文列名并改变列宽及居中显示

CMFCShellListCtrl创建出来的时候默认列名是英文的,这样改成中文:
  1. 从CMFCShellListCtrl派生出自定义类
    class CMyShelistCtrl : public CMFCShellListCtrl

  2. 定义CMyShelistCtrl变量
  3. 控件风格改为Report
    	m_ShelListCtrl.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
    

  4. 重载虚函数
    	virtual void OnSetColumns();
    

  5. 重载函数写
    LVCOLUMN lvColumn;
    	lvColumn.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH ;
    	LPWSTR sName[4] = {_T("名称"),_T("大小"),_T("类型"),_T("修改")};
    	int nWidth[4] = {200,100,100,200};
    
    	for(int i=0;i<4;i++)
    	{
    		lvColumn.pszText = sName[i];
    		lvColumn.cx = nWidth[i];	
    		lvColumn.fmt = LVCFMT_CENTER;
    		SetColumn(i,&lvColumn);
    	}

  6. END

2.获得鼠标单击控件列出的文件夹/文件的名字

  1. 响应控件NM_CLICK事件
    	ON_NOTIFY(NM_CLICK, IDC_MFCSHELLLIST, &CShellListCtrlDlg::OnNMClickMfcshelllist)
    

  2. 响应函数里添加代码
    void CShellListCtrlDlg::OnNMClickMfcshelllist(NMHDR *pNMHDR, LRESULT *pResult)
    {
    	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast(pNMHDR);
    	// TODO: Add your control notification handler code here
    	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    	if(pNMListView->iItem != -1)
    	{
    	
    		m_sCurrName = m_ShelListCtrl.GetItemText(pNMListView->iItem,
    			pNMListView->iSubItem);
    		m_FileNameEdit.SetWindowText(m_sCurrName);
    		
    	}
    	*pResult = 0;
    }

  3. 其中m_sCurrName即为点击获得的文件夹/文件名END

3.过滤要显示的文件夹/文件

  1. 重载虚函数
    	virtual HRESULT EnumObjects (LPSHELLFOLDER pParentFolder, LPITEMIDLIST pidlParent); 
    

  2. 填写下面的代码
    HRESULT CMyShelistCtrl :: EnumObjects (LPSHELLFOLDER pParentFolder, LPITEMIDLIST pidlParent) 
    {
    	ASSERT_VALID(this);
    
    
    	LPENUMIDLIST pEnum = NULL;
    	HRESULT hRes = pParentFolder->EnumObjects(NULL, m_nTypes, &pEnum);
    
    	if (SUCCEEDED(hRes) && pEnum != NULL)
    	{
    		LPITEMIDLIST pidlTemp;
    		DWORD dwFetched = 1;
    		LPAFX_SHELLITEMINFO pItem;
    
    		//enumerate the item's PIDLs
    		while (pEnum->Next(1, &pidlTemp, &dwFetched) == S_OK && dwFetched)
    		{
    			LVITEM lvItem;
    			ZeroMemory(&lvItem, sizeof(lvItem));
    
    			//fill in the TV_ITEM structure for this item
    			lvItem.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
    
    			//AddRef the parent folder so it's pointer stays valid
    			pParentFolder->AddRef();
    
    			//put the private information in the lParam
    			pItem = (LPAFX_SHELLITEMINFO)GlobalAlloc(GPTR, sizeof(AFX_SHELLITEMINFO));
    
    			pItem->pidlRel = pidlTemp;
    			pItem->pidlFQ = afxShellManager->ConcatenateItem(pidlParent, pidlTemp);
    
    			pItem->pParentFolder = pParentFolder;
    
    			
    
    			lvItem.lParam = (LPARAM)pItem;
    
    			lvItem.pszText = _T("");
    			lvItem.iImage = OnGetItemIcon(GetItemCount(), pItem);
    
    			//determine if the item is shared
    			DWORD dwAttr = SFGAO_FOLDER | SFGAO_DISPLAYATTRMASK;
    			pParentFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidlTemp, &dwAttr);
    
    			if (dwAttr & SFGAO_SHARE)
    			{
    				lvItem.mask |= LVIF_STATE;
    				lvItem.stateMask |= LVIS_OVERLAYMASK;
    				lvItem.state |= INDEXTOOVERLAYMASK(1); //1 is the index for the shared overlay image
    			}
    
    			if (dwAttr & SFGAO_GHOSTED)
    			{
    				lvItem.mask |= LVIF_STATE;
    				lvItem.stateMask |= LVIS_CUT;
    				lvItem.state |= LVIS_CUT;
    			}
    			if (dwAttr & SFGAO_FOLDER)
    			{
    			}
    			else
    			{
    				
    				TCHAR szPath [MAX_PATH];
    
    				if (SHGetPathFromIDList(pItem->pidlFQ, szPath))
    				{
    					CFileStatus fs;
    					if (CFile::GetStatus(szPath, fs))
    					{
    						CString s = szPath;
    						int n = s.ReverseFind('.');
    						if(n!=-1)
    						{
    							s = s.Mid(n+1);
    							s.MakeLower();					
    							
    							if(s == _T("exe"))//改写扩展名就可以过滤
    								continue;
    							
    							
    						}
    					}
    				}
    
    
    			}
    			int iItem = InsertItem(&lvItem);
    			if (iItem >= 0)
    			{
    				// Set columns:
    				const int nColumns = m_wndHeader.GetItemCount();
    				for (int iColumn = 0; iColumn < nColumns; iColumn++)
    				{
    					SetItemText(iItem, iColumn, OnGetItemText(iItem, iColumn, pItem));
    				}
    			}
    
    			dwFetched = 0;
    		}
    
    		pEnum->Release();
    	}
    
    	return hRes;
    }
    

  3. 过滤之后结果CMFCShellListCtrl使用方法_第2张图片END

4.只显示文件夹或文件或都显示

	m_ShelListCtrl.SetItemTypes(SHCONTF_FOLDERS | SHCONTF_NONFOLDERS);//看名字就应该知道怎么用吧



你可能感兴趣的:(CMFCxxx类,MFC)