📄 atlshellext.h
字号:
#ifndef __ATLSHELLEXT_H__
#define __ATLSHELLEXT_H__
#pragma once
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2001 Bjarke Viksoe.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//
#ifndef __ATLSHELLEXTBASE_H__
#error atlshellext.h requires atlshellextbase.h to be included first
#endif
#include <atlwin.h>
#include <prsht.h>
#include "resource.h"
//////////////////////////////////////////////////////////////////////////////
// CPidl
class CPidl
{
public:
LPITEMIDLIST m_pidl;
public:
CPidl() : m_pidl(NULL)
{
}
virtual ~CPidl()
{
Delete();
}
BOOL IsEmpty() const
{
return PidlIsEmpty(m_pidl);
}
operator LPITEMIDLIST() const
{
return m_pidl;
}
LPITEMIDLIST* operator&()
{
ATLASSERT(m_pidl==NULL);
return &m_pidl;
}
void Attach(LPITEMIDLIST pSrc)
{
Delete();
m_pidl = pSrc;
}
LPITEMIDLIST Detach()
{
LPITEMIDLIST pidl = m_pidl;
m_pidl = NULL;
return pidl;
}
DWORD GetByteSize() const
{
return PidlGetByteSize(m_pidl);
}
UINT GetCount() const
{
return PidlGetCount(m_pidl);
}
LPCITEMIDLIST GetNextItem() const
{
return PidlGetNextItem(m_pidl);
}
LPCITEMIDLIST GetLastItem() const
{
return PidlGetLastItem(m_pidl);
}
LPITEMIDLIST CopyFirstItem() const
{
return PidlCopyFirstItem(m_pidl);
}
LPITEMIDLIST Copy() const
{
return PidlCopy(m_pidl);
}
void Delete()
{
PidlDelete(m_pidl);
m_pidl = NULL;
}
void Copy(LPCITEMIDLIST pidlSource)
{
Delete();
m_pidl = PidlCopy(pidlSource);
}
void Concatenate(LPCITEMIDLIST pidl2)
{
if( (m_pidl==NULL) && (pidl2==NULL) ) return;
if( m_pidl==NULL ) {
m_pidl = PidlCopy(pidl2);
return;
}
if( pidl2==NULL ) return;
DWORD cb1, cb2;
cb1 = GetByteSize() - sizeof(USHORT);
cb2 = PidlGetByteSize(pidl2);
LPITEMIDLIST pidlNew = (LPITEMIDLIST)_Module.m_Allocator.Alloc(cb1 + cb2);
if( pidlNew!=NULL ) {
::CopyMemory( pidlNew, m_pidl, cb1 );
::CopyMemory( ((LPBYTE)pidlNew) + cb1, pidl2, cb2 );
}
Attach(pidlNew);
}
void RemoveLast()
{
LPITEMIDLIST pidlLast = const_cast<LPITEMIDLIST>(PidlGetLastItem(m_pidl));
if( pidlLast!=NULL ) pidlLast->mkid.cb = 0;
}
inline static BOOL PidlIsEmpty(LPCITEMIDLIST pidl)
{
return pidl==NULL || pidl->mkid.cb==0;
}
static LPCITEMIDLIST PidlGetLastItem(LPCITEMIDLIST pidl)
{
// Get the PIDL of the last item in the list
LPCITEMIDLIST pidlLast = NULL;
if( pidl!=NULL ) {
while( pidl->mkid.cb > 0 ) {
pidlLast = pidl;
pidl = PidlGetNextItem(pidl);
}
}
return pidlLast;
}
inline static LPITEMIDLIST PidlGetNextItem(LPCITEMIDLIST pidl)
{
return pidl==NULL ? NULL : (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
}
static UINT PidlGetCount(LPCITEMIDLIST pidlSource)
{
UINT cbTotal = 0;
if( pidlSource!=NULL ) {
while( pidlSource->mkid.cb > 0 ) {
cbTotal++;
pidlSource = PidlGetNextItem(pidlSource);
}
}
return cbTotal;
}
static DWORD PidlGetByteSize(LPCITEMIDLIST pidlSource)
{
DWORD cbTotal = 0;
if( pidlSource!=NULL ) {
while( pidlSource->mkid.cb > 0 ) {
cbTotal += pidlSource->mkid.cb;
pidlSource = PidlGetNextItem(pidlSource);
}
// Add the size of the NULL terminating ITEMIDLIST
cbTotal += sizeof(USHORT);
}
return cbTotal;
}
static void PidlDelete(LPITEMIDLIST pidlSource)
{
if( pidlSource==NULL ) return;
_Module.m_Allocator.Free( pidlSource );
}
static LPITEMIDLIST PidlCopy(LPCITEMIDLIST pidlSource)
{
LPITEMIDLIST pidlTarget = NULL;
DWORD cbSource = 0;
if( NULL==pidlSource ) return NULL;
// Allocate the new pidl
cbSource = PidlGetByteSize(pidlSource);
pidlTarget = (LPITEMIDLIST)_Module.m_Allocator.Alloc(cbSource);
if( pidlTarget==NULL ) return NULL; // Copy the source to the target
::CopyMemory( pidlTarget, pidlSource, cbSource );
return pidlTarget;
}
static LPITEMIDLIST PidlCopyFirstItem(LPCITEMIDLIST pidlSource)
{
LPITEMIDLIST pidlTarget = NULL;
DWORD cbSource = 0;
if( NULL==pidlSource ) return NULL;
// Allocate the new pidl
cbSource = pidlSource->mkid.cb + sizeof(USHORT);
pidlTarget = (LPITEMIDLIST)_Module.m_Allocator.Alloc(cbSource);
if( pidlTarget==NULL ) return NULL; // Copy the source to the target
::CopyMemory( pidlTarget, pidlSource, cbSource );
// Terminate the IDList
*(WORD *)(((LPBYTE)pidlTarget)+pidlTarget->mkid.cb) = 0;
return pidlTarget;
}
};
/////////////////////////////////////////////////////////////////////////////
// CPidlList
class CPidlList
{
public:
CPidlList()
{
m_pidls = NULL;
m_nCount = 0;
m_bOwner = false;
}
CPidlList(HWND hwndList, DWORD dwListViewMask=LVNI_SELECTED)
{
ATLASSERT(::IsWindow(hwndList));
m_pidls = NULL;
m_nCount = 0;
UINT nCount = ( dwListViewMask==LVNI_SELECTED ? ListView_GetSelectedCount(hwndList) : ListView_GetItemCount(hwndList) );
if( nCount==0 ) return;
LPITEMIDLIST *pidls = (LPITEMIDLIST *)_Module.m_Allocator.Alloc(nCount * sizeof(LPITEMIDLIST));
if( pidls==NULL ) return;
int nItem = -1;
UINT i = 0;
while( (nItem = ListView_GetNextItem(hwndList, nItem, dwListViewMask))!=-1 )
{
LVITEM lvi = { 0 };
lvi.mask = LVIF_PARAM;
lvi.iItem = nItem;
ListView_GetItem(hwndList, &lvi);
pidls[i++] = (LPITEMIDLIST)lvi.lParam;
}
m_pidls = pidls;
m_nCount = i;
m_bOwner = false;
}
virtual ~CPidlList()
{
Delete();
}
operator LPCITEMIDLIST *() const
{
return const_cast<LPCITEMIDLIST *>(m_pidls);
}
UINT GetCount() const
{
return m_nCount;
}
LPITEMIDLIST *Detach()
{
LPITEMIDLIST *pidls = m_pidls;
m_pidls = NULL;
m_nCount = 0;
m_bOwner = false;
return pidls;
}
HRESULT Attach(LPITEMIDLIST *pidlSource, UINT nCount, BOOL bOwnItems=FALSE)
{
Delete();
m_pidls = pidlSource;
m_nCount = nCount;
m_bOwner = (bOwnItems==TRUE);
return S_OK;
}
HRESULT Copy(LPCITEMIDLIST *pidlSource, UINT nCount, BOOL bOwnItems=FALSE)
{
ATLASSERT(pidlSource);
ATLASSERT(nCount>0);
if( (pidlSource==NULL) || (nCount==0) ) return E_INVALIDARG;
Delete();
m_pidls = (LPITEMIDLIST *)_Module.m_Allocator.Alloc(nCount * sizeof(LPITEMIDLIST));
if( m_pidls==NULL ) return E_OUTOFMEMORY;
m_nCount = nCount;
// If requested, we'll make a copy of each PIDL structure too, otherwise
// simply copy memory (weak reference).
if( bOwnItems ) {
for( UINT i=0; i<nCount; i++ ) m_pidls[i] = CPidl::PidlCopy(pidlSource[i]);
m_bOwner = true;
}
else {
::CopyMemory(m_pidls, pidlSource, nCount * sizeof(LPITEMIDLIST));
m_bOwner = false;
}
return S_OK;
}
void Delete()
{
if( m_pidls!=NULL ) {
if( m_bOwner ) for( UINT i=0; i<m_nCount; i++ ) _Module.m_Allocator.Free((LPVOID)m_pidls[i]);
_Module.m_Allocator.Free(m_pidls);
m_pidls = NULL;
m_nCount = 0;
m_bOwner = false;
}
}
HRESULT Filter(IShellFolder *pFolder, DWORD dwItemMask)
{
ATLASSERT(pFolder);
ATLASSERT(dwItemMask!=0);
ATLASSERT(!m_bOwner);
if( m_nCount==0 ) return S_OK;
LPITEMIDLIST *pidls = (LPITEMIDLIST *)_Module.m_Allocator.Alloc(m_nCount * sizeof(LPITEMIDLIST));
if( pidls==NULL ) return E_OUTOFMEMORY;
UINT nCount=0;
for( UINT i=0; i<m_nCount; i++ ) {
DWORD dwAttr = dwItemMask;
LPCITEMIDLIST pidl = m_pidls[i];
pFolder->GetAttributesOf(1, &pidl, &dwAttr);
if( (dwAttr & dwItemMask)==dwItemMask ) {
pidls[nCount] = m_pidls[i];
nCount++;
}
}
// We've recreated a new PIDL list.
// The allocated memory for the list may actually be too large, but
// it doesn't matter for the PIDL functions.
return Attach(pidls, nCount, FALSE);
}
LPITEMIDLIST *m_pidls;
UINT m_nCount;
bool m_bOwner;
};
#ifdef __ATLCOM_H__
/////////////////////////////////////////////////////////////////////////////
// CPidlEnum
class ATL_NO_VTABLE CPidlEnum :
public CComObjectRootEx<CComSingleThreadModel>,
public IEnumIDList
{
public:
CPidlEnum() : m_iCount(0), m_iPos(0), m_pCur(NULL)
{
}
DECLARE_NO_REGISTRY()
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CPidlEnum)
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList,IEnumIDList)
END_COM_MAP()
public:
HRESULT _Init(LPCITEMIDLIST pPidlArray, UINT nCount)
{
m_pidl.Copy(pPidlArray);
m_iCount = nCount;
Reset();
return S_OK;
}
STDMETHOD(Next)(ULONG /*celt*/, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -