屬性表 COM 對象的實作範例程序代碼
下列程式代碼範例可用來實作 Active Directory 屬性表延伸模組。
IShellExtInit 實作
下列 C++ 程式代碼範例可用來實 作 IShellExtInit 方法。
/**************************************************************************
CPropSheetExt::Initialize()
**************************************************************************/
STDMETHODIMP CPropSheetExt::Initialize( LPCITEMIDLIST pidlFolder,
IDataObject *pDataObj,
HKEY hKeyProgId)
{
STGMEDIUM stm;
FORMATETC fe;
HRESULT hr = S_OK;
if(NULL == pDataObj)
{
return E_INVALIDARG;
}
hr = pDataObj->QueryInterface(IID_IDataObject, (LPVOID*)&m_pdo);
if(FAILED(hr))
{
return hr;
}
fe.cfFormat = RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = m_pdo->GetData(&fe, &stm);
if(SUCCEEDED(hr))
{
LPDSOBJECTNAMES pdson = (LPDSOBJECTNAMES)GlobalLock(stm.hGlobal);
if(pdson)
{
LPWSTR pwszName = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetName);
m_pwszADsPath = (LPWSTR)GlobalAlloc(GPTR, (lstrlenW(pwszName) + 1) * sizeof(WCHAR));
if(m_pwszADsPath)
{
wcscpy_s(m_pwszADsPath, pwszName);
}
LPWSTR pwszClass = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetClass);
pwszClass = NULL;
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
m_hwndNotifyObj = CreateADsNotificationObject(pDataObj);
if(m_hwndNotifyObj)
{
ADSPROPINITPARAMS InitParams;
hr = GetADsPageInfo(m_hwndNotifyObj, &InitParams);
if(SUCCEEDED(hr))
{
if(InitParams.pDsObj)
{
hr = InitParams.pDsObj->QueryInterface( IID_IDirectoryObject,
(LPVOID*) & m_pDirObj);
}
}
}
fe.cfFormat = RegisterClipboardFormat(CFSTR_DS_DISPLAY_SPEC_OPTIONS);
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = pDataObj->GetData(&fe, &stm);
if(SUCCEEDED(hr))
{
PDSDISPLAYSPECOPTIONS pdso;
pdso = (PDSDISPLAYSPECOPTIONS)GlobalLock(stm.hGlobal);
if(pdso)
{
DWORD dwBytes = GlobalSize(stm.hGlobal);
m_pDispSpecOpts = (PDSDISPLAYSPECOPTIONS)GlobalAlloc(GPTR, dwBytes);
if(m_pDispSpecOpts)
{
CopyMemory(m_pDispSpecOpts, pdso, dwBytes);
}
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
return hr;
}
IShellPropSheetExt 實作
下列 C++ 程式代碼範例可用來實 作 IShellPropSheetExt 方法。
/**************************************************************************
CPropSheetExt::AddPages()
**************************************************************************/
STDMETHODIMP CPropSheetExt::AddPages( LPFNADDPROPSHEETPAGE pfnAddPage,
LPARAM lParam)
{
PROPSHEETPAGE psp;
HPROPSHEETPAGE hPage;
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
psp.hInstance = g_hInst;
psp.pszTemplate = MAKEINTRESOURCE(IDD_PAGEDLG);
psp.hIcon = 0;
psp.pszTitle = g_szPageTitle;
psp.pfnDlgProc = (DLGPROC)PageDlgProc;
psp.pcRefParent = NULL;
psp.pfnCallback = PageCallbackProc;
//pass the object pointer to the dialog box
psp.lParam = (LPARAM)this;
hPage = CreatePropertySheetPage(&psp);
if(hPage)
{
if(pfnAddPage(hPage, lParam))
{
/*
Maintain this object until the page is released in
PageCallbackProc.
*/
this->AddRef();
return S_OK;
}
else
{
DestroyPropertySheetPage(hPage);
}
}
else
{
return E_OUTOFMEMORY;
}
return E_FAIL;
}
/**************************************************************************
CPropSheetExt::ReplacePage()
**************************************************************************/
STDMETHODIMP CPropSheetExt::ReplacePage( UINT uPageID,
LPFNADDPROPSHEETPAGE lpfnAddPage,
LPARAM lParam)
{
return E_NOTIMPL;
}
其他實作
下列 C++ 程式代碼範例可用來實作上一個程式代碼範例中使用的公用程式方法和函式。
HWND CreateADsNotificationObject(IDataObject *pDataObject)
{
STGMEDIUM stm;
FORMATETC fe;
HRESULT hr;
HWND hwndNotifyObject = NULL;
/*
The "DsAdminMultiSelectClipFormat" clipboard format is supported by the
data object if the Active Directory Users and Computers snap-in supports
multi-selection property sheets.
*/
fe.cfFormat = RegisterClipboardFormat(TEXT("DsAdminMultiSelectClipFormat"));
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = pDataObject->GetData(&fe, &stm);
if (SUCCEEDED(hr))
{
PWSTR pwzUniqueID = (LPWSTR)GlobalLock(stm.hGlobal);
if (pwzUniqueID)
{
hr = ADsPropCreateNotifyObj(pDataObject, pwzUniqueID, &hwndNotifyObject);
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
else
{
fe.cfFormat = RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = pDataObject->GetData(&fe, &stm);
if(SUCCEEDED(hr))
{
LPDSOBJECTNAMES pdson = (LPDSOBJECTNAMES)GlobalLock(stm.hGlobal);
if(pdson)
{
LPWSTR pwszName = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetName);
hr = ADsPropCreateNotifyObj(pDataObject, pwszName, &hwndNotifyObject);
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
}
return hwndNotifyObject;
}
/**************************************************************************
GetADsPageInfo()
**************************************************************************/
HRESULT GetADsPageInfo(HWND hwndNotifyObject, ADSPROPINITPARAMS *pip)
{
if(!IsWindow(hwndNotifyObject))
{
return E_INVALIDARG;
}
ADSPROPINITPARAMS InitParams;
InitParams.dwSize = sizeof(ADSPROPINITPARAMS);
if(ADsPropGetInitInfo(hwndNotifyObject, &InitParams))
{
*pip = InitParams;
return InitParams.hr;
}
return E_FAIL;
}
/**************************************************************************
CPropSheetExt::PageDlgProc
**************************************************************************/
#define THIS_POINTER_PROP TEXT("ThisPointerProperty")
BOOL CALLBACK CPropSheetExt::PageDlgProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
// Get the object pointer.
CPropSheetExt *pExt = (CPropSheetExt*)GetProp(hWnd, THIS_POINTER_PROP);
switch(uMsg)
{
case WM_INITDIALOG:
{
/*
Get the pointer to the object. This is contained in the LPARAM of
the PROPSHEETPAGE structure.
*/
LPPROPSHEETPAGE pPage = (LPPROPSHEETPAGE)lParam;
if(pPage)
{
pExt = (CPropSheetExt*)pPage->lParam;
if(pExt)
{
// Set the page window handle in the object.
pExt->m_hwndPage = hWnd;
// Store the object pointer with this particular page dialog.
SetProp(hWnd, THIS_POINTER_PROP, (HANDLE)pExt);
ADsPropSetHwnd(pExt->m_hwndNotifyObj, hWnd, g_szPageTitle);
// Forward the message to the message handler.
return pExt->OnInitDialog(wParam, lParam);
}
}
}
break;
case WM_NOTIFY:
if(pExt)
{
// Forward the message to the message handler.
return pExt->OnNotify(wParam, lParam);
}
break;
case WM_COMMAND:
if(pExt)
{
// Forward the message to the message handler.
return pExt->OnCommand(wParam, lParam);
}
return FALSE;
case WM_DESTROY:
if(pExt)
{
// Forward the message to the message handler.
pExt->OnDestroy();
}
// Remove the property from the page.
RemoveProp(hWnd, THIS_POINTER_PROP);
break;
}
return FALSE;
}
/**************************************************************************
CPropSheetExt::PageCallbackProc()
This function is called when the page is created and released. This is
even called if the page is never actually displayed.
**************************************************************************/
UINT CALLBACK CPropSheetExt::PageCallbackProc( HWND hWnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
switch(uMsg)
{
case PSPCB_CREATE:
// Must return TRUE to create the page.
return TRUE;
case PSPCB_RELEASE:
{
/*
Release the object. This is called even if the page dialog was
never actually created.
*/
CPropSheetExt *pPropSheetExt = (CPropSheetExt*)ppsp->lParam;
if(pPropSheetExt)
{
if(IsWindow(pPropSheetExt->m_hwndNotifyObj))
{
SendMessage(pPropSheetExt->m_hwndNotifyObj,
WM_ADSPROP_NOTIFY_EXIT,
0,
0);
pPropSheetExt->m_hwndNotifyObj = NULL;
}
pPropSheetExt->Release();
}
}
break;
}
return FALSE;
}