📄 enumidl.cpp
字号:
/******************************************************************
*
* Project.....: Windows View (Namespace Extension)
*
* Application.: WINVIEW.dll
* Module......: EnumIDL.cpp
* Description.: IEnumIDList implementation
*
* Compiler....: MS Visual C++
* Written by..: D. Esposito
*
* Environment.: Windows 9x/NT
*
*******************************/
/*---------------------------------------------------------------*/
// INCLUDE section
/*---------------------------------------------------------------*/
#include "EnumIDL.h"
#include "ShlFldr.h"
/*---------------------------------------------------------------*/
// Class constructor and destructor
/*---------------------------------------------------------------*/
CEnumIDList::CEnumIDList(HWND hwnd, DWORD dwFlags, HRESULT* pResult)
{
if(pResult)
*pResult = S_OK;
m_pFirst = NULL;
m_pLast = NULL;
m_pCurrent = NULL;
// Creates the PIDL manager
m_pPidlMgr = new CPidlMgr();
if(!m_pPidlMgr)
{
if(pResult)
*pResult = E_OUTOFMEMORY;
delete this;
return;
}
// Get the shell's memory manager
if(FAILED(SHGetMalloc(&m_pMalloc)))
{
if(pResult)
*pResult = E_OUTOFMEMORY;
delete this;
return;
}
// Creates the list of the items
if(!CreateEnumList(hwnd, dwFlags))
{
if(pResult)
*pResult = E_OUTOFMEMORY;
delete this;
return;
}
m_ObjRefCount = 1;
g_DllRefCount++;
}
CEnumIDList::~CEnumIDList()
{
DeleteList();
if( m_pMalloc )
m_pMalloc->Release();
if( m_pPidlMgr )
delete m_pPidlMgr;
g_DllRefCount--;
}
/*---------------------------------------------------------------*/
// IUnknown methods
/*---------------------------------------------------------------*/
STDMETHODIMP CEnumIDList::QueryInterface( REFIID riid, LPVOID *ppReturn )
{
*ppReturn = NULL;
if(IsEqualIID(riid, IID_IUnknown))
*ppReturn = this;
else
if(IsEqualIID(riid, IID_IEnumIDList))
*ppReturn = (IEnumIDList*)this;
if( *ppReturn )
{
LPUNKNOWN pUnk = (LPUNKNOWN)(*ppReturn);
pUnk->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(DWORD) CEnumIDList::AddRef()
{
return ++m_ObjRefCount;
}
STDMETHODIMP_(DWORD) CEnumIDList::Release()
{
if(--m_ObjRefCount == 0)
{
delete this;
return 0;
}
return m_ObjRefCount;
}
/*---------------------------------------------------------------*/
// IEnumIDList methods
/*---------------------------------------------------------------*/
STDMETHODIMP CEnumIDList::Next(DWORD dwElements, LPITEMIDLIST apidl[], LPDWORD pdwFetched)
{
DWORD dwIndex;
HRESULT hr = S_OK;
if(dwElements > 1 && !pdwFetched)
return E_INVALIDARG;
for(dwIndex = 0 ; dwIndex < dwElements ; dwIndex++)
{
// Is this the last item in the list?
if(!m_pCurrent)
{
hr = S_FALSE;
break;
}
// Copy PIDLs
apidl[dwIndex] = m_pPidlMgr->Copy(m_pCurrent->pidl);
m_pCurrent = m_pCurrent->pNext;
}
// Returns the number of fetched items
if(pdwFetched)
*pdwFetched = dwIndex;
return hr;
}
// Skip
STDMETHODIMP CEnumIDList::Skip(DWORD dwSkip)
{
DWORD dwIndex;
HRESULT hr = S_OK;
for( dwIndex=0; dwIndex < dwSkip; dwIndex++ )
{
// is this the last item in the list?
if( !m_pCurrent )
{
hr = S_FALSE;
break;
}
m_pCurrent = m_pCurrent->pNext;
}
return hr;
}
// Reset
STDMETHODIMP CEnumIDList::Reset( VOID )
{
m_pCurrent = m_pFirst;
return S_OK;
}
STDMETHODIMP CEnumIDList::Clone( LPENUMIDLIST *ppEnum )
{
return E_NOTIMPL;
}
/*---------------------------------------------------------------*/
// PRIVATE methods: CreateEnumList
// Creates the list that renders the active windows
/*---------------------------------------------------------------*/
BOOL CEnumIDList::CreateEnumList(HWND hWndRoot, DWORD dwFlags)
{
// Get the desktop window
if(hWndRoot == NULL)
{
// If we must consider the root window (the desktop), we don't need to
// enumerate anything. Just get the desktop HWND and add a new
// element to the list. This is what's done by NewEnumItem().
hWndRoot = GetDesktopWindow();
NewEnumItem(hWndRoot);
return TRUE;
}
// Enumerate the child windows of the specified window
ENUMWND ew;
ew.lParam = reinterpret_cast<LPARAM>(this);
ew.hwndParent = hWndRoot;
ew.dwFlags = dwFlags;
// We need a function that only considers immediate children of the
// specified window. We're not interested in children of children. We'll
// correct this aspect of EnumChildWindows' behavior in callback code.
EnumChildWindows(hWndRoot, AddToEnumList, reinterpret_cast<LPARAM>(&ew));
return TRUE;
}
/*---------------------------------------------------------------*/
// PRIVATE methods: AddToEnumList
// Class static member adding a new window to the folder's list
/*---------------------------------------------------------------*/
BOOL CALLBACK CEnumIDList::AddToEnumList(HWND hwndChild, LPARAM lParam)
{
LPENUMWND lpew = reinterpret_cast<LPENUMWND>(lParam);
// Avoid windows that aren't children of the specified window's parent.
// This test is meant to skip over all those windows that aren't
// immediate children of the window whose children we're enumerating.
// This check is due to a feature of EnumChildWindows() that enumerates
// not just children but also grandchildren. We avoid grandchildren.
HWND h = GetParent(hwndChild);
if((h != NULL) && (h != lpew->hwndParent))
return TRUE;
// We stored the pointer to the class in the lParam argument
CEnumIDList* pEnumIDList = reinterpret_cast<CEnumIDList*>(lpew->lParam);
// IMPORTANT: This is where we decide what's a 'folder' and what's a
// 'leaf'. For windows, this rests on whether they have children.
// Explorer wants non-folder items
if(lpew->dwFlags & SHCONTF_NONFOLDERS)
return pEnumIDList->NewEnumItem(hwndChild);
// Explorer wants folder items
if(lpew->dwFlags & SHCONTF_FOLDERS)
{
// If it has no children, drop it because it has already been added.
if(!pEnumIDList->m_pPidlMgr->HasChildren(hwndChild))
return TRUE;
else
pEnumIDList->NewEnumItem(hwndChild);
}
return TRUE;
}
/*---------------------------------------------------------------*/
// PRIVATE methods: DeleteList
// Delete the previous list
/*---------------------------------------------------------------*/
BOOL CEnumIDList::DeleteList( VOID )
{
LPENUMLIST pDelete;
while( m_pFirst )
{
pDelete = m_pFirst;
m_pFirst = pDelete->pNext;
// free the pidl
m_pPidlMgr->Delete( pDelete->pidl );
//free the list item
m_pMalloc->Free( pDelete );
}
m_pFirst = m_pLast = m_pCurrent = NULL;
return TRUE;
}
/*---------------------------------------------------------------*/
// PRIVATE methods: NewEnumItem
// Add a new item to the list.
/*---------------------------------------------------------------*/
BOOL CEnumIDList::NewEnumItem(HWND hwndChild)
{
LPENUMLIST pNew = NULL;
pNew = reinterpret_cast<LPENUMLIST>(m_pMalloc->Alloc(sizeof(ENUMLIST)));
if(pNew)
{
// Create the new PIDL for the new element
pNew->pNext = NULL;
pNew->pidl = m_pPidlMgr->Create(hwndChild);
// Is this the first item in the list?
if(!m_pFirst)
{
m_pFirst = pNew;
m_pCurrent = m_pFirst;
}
// Add the new item to the end of the list
if(m_pLast)
m_pLast->pNext = pNew;
// Update the last item pointer
m_pLast = pNew;
return TRUE;
}
return FALSE;
}
/* End of file: EnumIDL.cpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -