理解COM编程中的“种类”(Category)概念
2006-07-21 11:42:52 来源:WEB开发网用这接口可以枚举实现给定种类的类。为了说明ICatInformation接口使用,我写了一个小程序CatView,用这个程序可以浏览系统中注册的种类。如图一所示:
图一 CatView 浏览系统中注册的种类下面是CatView 有关的代码:(全部源代码可以从本文最前面的链接下载)
// CoolCat.h — helper stuff for COMponent categories.
//
#pragma once
#include
//////////////////
// Helper function to get GUID in human-readable format as CString.
//
inline CString CStringFromGuid(GUID& guid)
{
LPOLESTR pstr=NULL;
StringFromCLSID(guid, &pstr);
return CString(pstr);
}
////////////////
// Handy Category Information class. Instantiate and go.
//
class CCatInformation : public CComPtr {
public:
CCatInformation() {
CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL,
CLSCTX_INPROC);
ASSERT(p);
}
};
//////////////////
// Handy class to enumerate categories
//
class CCatIterator {
protected:
CComPtr spEnumCatInfo; // IEnumCATEGORYINFO
CCatInformation spCatInfo; // ICatInformation
public:
CCatIterator(LCID lcid = GetUserDefaultLCID()) {
HRESULT hr = spCatInfo->EnumCategories(lcid, &spEnumCatInfo);
ASSERT(SUCCEEDED(hr));
}
BOOL Next(CATEGORYINFO& catinfo) {
ULONG nRet=0;
return SUCCEEDED(spEnumCatInfo->Next(1, &catinfo, &nRet)) &&
nRet==1;
}
};
//////////////////
// Handy class to enumerate classes that implement a category
//
class CCatClassIterator {
protected:
CComPtr spEnumCLSID; // IEnumCLSID
CCatInformation spCatInfo; // ICatInformation
public:
CCatClassIterator(CATID* arImplCatids, ULONG nImpl,
CATID* arReqdCatids=NULL, ULONG nReqd=0) {
HRESULT hr = spCatInfo->EnumClassesOfCategories(
nImpl, // num implemented cats in array
arImplCatids, // array of cats to look for (implement)
nReqd, // num required categories in array
arReqdCatids, // array of required categories to look for
&spEnumCLSID); // IEnum returned
ASSERT(SUCCEEDED(hr));
}
BOOL Next(CLSID& clsid) {
ULONG nRet=0;
return SUCCEEDED(spEnumCLSID->Next(1, &clsid, &nRet)) && nRet==1;
}
};
View.h
#pragma once
//////////////////
// Right pane is a list of controls that implement a category.
//
class CRightView : public CListView {
public:
CRightView();
virtual ~CRightView();
BOOL ShowCategory(CATID& catid);
protected:
virtual void OnInitialUpdate(); // called first time after construct
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
DECLARE_DYNCREATE(CRightView)
DECLARE_MESSAGE_MAP()
};
//////////////////
// Left pane is a list of categories.
//
class CLeftView : public CListView {
public:
virtual ~CLeftView();
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
void SetRightPane(CRightView* pRightPane) {
m_pRightPane = pRightPane;
}
protected:
CRightView* m_pRightPane;
CLeftView();
void PopulateCategoryList();
virtual void OnInitialUpdate(); // called first time after construct
afx_msg void OnItemChanged(NMHDR* pNMHDR, LRESULT* pRes);
afx_msg LRESULT OnWinMgr(WPARAM wp, LPARAM lp);
DECLARE_MESSAGE_MAP()
DECLARE_DYNCREATE(CLeftView)
};
LeftView.cpp
//
#include "stdafx.h"
#include "View.h"
#include "WinMgr.h"
#include "CoolCat.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CLeftView, CListView)
BEGIN_MESSAGE_MAP(CLeftView, CListView)
ON_NOTIFY_REFLECT(LVN_ITEMCHANGED,OnItemChanged)
ON_REGISTERED_MESSAGE(WM_WINMGR, OnWinMgr)
END_MESSAGE_MAP()
CLeftView::CLeftView() : m_pRightPane(NULL)
{
}
CLeftView::~CLeftView()
{
}
BOOL CLeftView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= LVS_REPORT | LVS_SORTASCENDING | LVS_NOSORTHEADER;
return CListView::PreCreateWindow(cs);
}
void CLeftView::OnDraw(CDC* pDC)
{
}
//////////////////
// First-time init: add column headers
//
void CLeftView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
const COLWIDTH = 250;
CListCtrl& lc = GetListCtrl();
lc.InsertColumn(0, _T("Category Name"),LVCFMT_LEFT,COLWIDTH);
lc.InsertColumn(1, _T("CATID"),LVCFMT_LEFT,COLWIDTH,1);
PopulateCategoryList();
}
//////////////////
// Populate list of categories.
//
void CLeftView::PopulateCategoryList()
{
CListCtrl& lc = GetListCtrl();
lc.DeleteAllItems();
CATEGORYINFO catinfo;
CCatIterator it;
while (it.Next(catinfo)) {
// add category name to list
CString sName = catinfo.szDescription;
if (sName.IsEmpty()) {
sName = _T("");
}
int iItem = lc.InsertItem(0,sName);
// Add CATID as 1st subitem
lc.SetItemText(iItem,1,CStringFromGuid(catinfo.catid));
}
}
//////////////////
// User selected a new category: show controls in right pane.
//
void CLeftView::OnItemChanged(NMHDR* pNMHDR, LRESULT* pRes)
{
NMLISTVIEW nm = *(NMLISTVIEW*)pNMHDR;
if (nm.iItem>=0 && (nm.uNewState & LVIS_SELECTED)) {
CListCtrl& lc = GetListCtrl();
CString sguid = lc.GetItemText(nm.iItem,1);
CATID catid;
USES_CONVERSION;
if (SUCCEEDED(CLSIDFromString(T2OLE((LPCTSTR)sguid),&catid)))
m_pRightPane->ShowCategory(catid);
else
MessageBeep(0);
}
*pRes= 0;
}
//////////////////
// Handle WinMgr request for size info: compute TOFIT size for list view,
// which is sum of widths of columns.
//
LRESULT CLeftView::OnWinMgr(WPARAM wp, LPARAM lp)
{
ASSERT(lp);
NMWINMGR& nmw = *(NMWINMGR*)lp;
if (nmw.code==NMWINMGR::GET_SIZEINFO && (int)wp==GetDlgCtrlID()) {
CSize sz(0,0);
CListCtrl& lc = GetListCtrl();
int nCols = lc.GetHeaderCtrl()->GetItemCount();
for (int iCol=0; iCol");
lc.SetItemText(iItem,1,sProgID);
}
return TRUE;
}
//
更多精彩
赞助商链接