📄 shlfldr.cpp
字号:
/******************************************************************
*
* Project.....: Windows View (Namespace Extension)
*
* Application.: WINVIEW.dll
* Module......: ShlFldr.cpp
* Description.: IShellFolder implementation
*
* Compiler....: MS Visual C++
* Written by..: D. Esposito
*
* Environment.: Windows 9x/NT
*
*******************************/
#include "ShlFldr.h"
#include "ShlView.h"
#include "ExtrIcon.h"
#include "CtxtMenu.h"
#include "Guid.h"
#include "resource.h"
/*---------------------------------------------------------------*/
// Constructor and destructor
/*---------------------------------------------------------------*/
CShellFolder::CShellFolder(CShellFolder *pParent, LPCITEMIDLIST pidl)
{
m_pSFParent = pParent;
if( m_pSFParent )
m_pSFParent->AddRef();
// get the PIDL manager
m_pPidlMgr = new CPidlMgr();
if( !m_pPidlMgr )
{
delete this;
return;
}
// get the shell's memory manager
if( FAILED(SHGetMalloc(&m_pMalloc)) )
{
delete this;
return;
}
// makes a copy of the PIDL and the HWND
m_pidl = m_pPidlMgr->Copy( pidl );
if( m_pidl )
{
HWND h = m_pPidlMgr->GetData( m_pidl );
if( IsWindow(h) )
m_hWnd = h;
}
// default sort mode
m_uSortField = 3; // by HWNDs
m_ObjRefCount = 1;
g_DllRefCount++;
}
CShellFolder::~CShellFolder()
{
if( m_pidl )
{
m_pPidlMgr->Delete( m_pidl );
m_pidl = NULL;
}
if( m_pSFParent )
m_pSFParent->Release();
if( m_pMalloc )
m_pMalloc->Release();
if( m_pPidlMgr )
delete m_pPidlMgr;
g_DllRefCount--;
}
/*---------------------------------------------------------------*/
// IUnknown methods
/*---------------------------------------------------------------*/
STDMETHODIMP CShellFolder::QueryInterface( REFIID riid, LPVOID *ppReturn )
{
*ppReturn = NULL;
if(IsEqualIID(riid, IID_IUnknown))
*ppReturn = this;
else
if(IsEqualIID(riid, IID_IPersistFolder))
*ppReturn = (IPersistFolder*)this;
else
if(IsEqualIID(riid, IID_IShellFolder))
*ppReturn = (IShellFolder*)this;
if( *ppReturn )
{
LPUNKNOWN pUnk = (LPUNKNOWN)(*ppReturn);
pUnk->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(DWORD) CShellFolder::AddRef()
{
return ++m_ObjRefCount;
}
STDMETHODIMP_(DWORD) CShellFolder::Release()
{
if(--m_ObjRefCount == 0)
{
delete this;
return 0;
}
return m_ObjRefCount;
}
/*---------------------------------------------------------------*/
// IPersistFolder methods
/*---------------------------------------------------------------*/
STDMETHODIMP CShellFolder::GetClassID(LPCLSID lpClassID)
{
*lpClassID = CLSID_WinView;
return S_OK;
}
STDMETHODIMP CShellFolder::Initialize(LPCITEMIDLIST pidl)
{
return S_OK;
}
/*---------------------------------------------------------------*/
// IShellFolder methods
/*---------------------------------------------------------------*/
// BindToObject
STDMETHODIMP CShellFolder::BindToObject(
LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID* ppvOut)
{
CShellFolder* pShellFolder = new CShellFolder(this, pidl);
if(!pShellFolder)
return E_OUTOFMEMORY;
HRESULT hr = pShellFolder->QueryInterface(riid, ppvOut);
pShellFolder->Release();
return hr;
}
// BindToStorage
STDMETHODIMP CShellFolder::BindToStorage( LPCITEMIDLIST pidl,
LPBC pbcReserved, REFIID riid, LPVOID *ppvOut )
{
return E_NOTIMPL;
}
// CompareIDs
STDMETHODIMP CShellFolder::CompareIDs(
LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
// This function is always called with lParam set to 0. By convention,
// this means "sort by name"; other non-zero values are usually meant to
// indicate specific folder-sorting rules. Note that here I'm using the
// m_uSortField data member as a 'replacement' for lParam.
HWND hwnd1 = m_pPidlMgr->GetData(pidl1);
HWND hwnd2 = m_pPidlMgr->GetData(pidl2);
// Sorting by CHILDREN
if(m_uSortField == 1 || m_uSortField == -1)
{
int fChildren1 = m_pPidlMgr->HasChildren(hwnd1);
int fChildren2 = m_pPidlMgr->HasChildren(hwnd2);
if(fChildren1 < fChildren2)
return m_uSortField;
else if(fChildren1 > fChildren2)
return m_uSortField * -1;
else
return 0;
}
// Sorting by CLASS
if(m_uSortField == 2 || m_uSortField == -2)
{
TCHAR szClass1[100];
TCHAR szClass2[100];
GetClassName(hwnd1, szClass1, 100);
GetClassName(hwnd2, szClass2, 100);
return m_uSortField * lstrcmpi(szClass1, szClass2);
}
// Sorting by TITLE
if(m_uSortField == 4 || m_uSortField == -4)
{
TCHAR szTitle1[100];
TCHAR szTitle2[100];
GetWindowText(hwnd1, szTitle1, 100);
GetWindowText(hwnd2, szTitle2, 100);
return m_uSortField * lstrcmpi(szTitle1, szTitle2);
}
// sorting by HWND
if(hwnd1 < hwnd2)
return m_uSortField;
else if(hwnd1 > hwnd2)
return m_uSortField * -1;
else
return 0;
}
// CreateViewObject
STDMETHODIMP CShellFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID* ppvOut)
{
CShellView* pShellView = new CShellView(this, m_pidl);
if(!pShellView)
return E_OUTOFMEMORY;
m_pShellView = pShellView;
HRESULT hr = pShellView->QueryInterface(riid, ppvOut);
pShellView->Release();
return hr;
}
// EnumObjects
STDMETHODIMP CShellFolder::EnumObjects(
HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST* ppEnumIDList)
{
// hwndOwner is just the HWND to use as the parent for any message box
HRESULT hr;
*ppEnumIDList = NULL;
HWND hWnd = m_pPidlMgr->GetData(m_pidl);
*ppEnumIDList = new CEnumIDList(hWnd, dwFlags, &hr);
if(*ppEnumIDList == NULL)
return hr;
return S_OK;
}
// GetAttributesOf
STDMETHODIMP CShellFolder::GetAttributesOf(
UINT uCount, LPCITEMIDLIST aPidls[], LPDWORD pdwAttribs)
{
*pdwAttribs = -1;
for(UINT i = 0 ; i < uCount ; i++)
{
DWORD dwAttribs = 0;
// Is this item a window?
HWND hwnd = m_pPidlMgr->GetData(aPidls[i]);
if(IsWindow(hwnd))
{
// Assign here all the styles you want the items to have in common
// Of course, it's then up to you to manage them properly.
if(m_pPidlMgr->HasChildren(hwnd))
{
dwAttribs |= SFGAO_FOLDER;
if(m_pPidlMgr->HasChildrenOfChildren(hwnd))
dwAttribs |= SFGAO_HASSUBFOLDER;
}
}
*pdwAttribs = dwAttribs;
}
return S_OK;
}
// GetUIObjectOf
STDMETHODIMP CShellFolder::GetUIObjectOf( HWND hwndOwner,
UINT uCount, LPCITEMIDLIST *pPidl, REFIID riid,
LPUINT puReserved, LPVOID *ppvReturn )
{
*ppvReturn = NULL;
if( uCount != 1 )
return E_FAIL;
// IExtractIcon
if( IsEqualIID(riid, IID_IExtractIcon) )
{
CExtractIcon *pei;
pei = new CExtractIcon( (LPCITEMIDLIST)pPidl[0] );
if(pei)
{
*ppvReturn = pei;
return S_OK;
}
return E_OUTOFMEMORY;
}
// IContextMenu
if( IsEqualIID(riid, IID_IContextMenu) )
{
CContextMenu *pcm;
pcm = new CContextMenu( (LPCITEMIDLIST)pPidl[0] );
if( pcm )
{
pcm->AddRef();
pcm->QueryInterface( riid, ppvReturn );
pcm->Release();
return S_OK;
}
return E_OUTOFMEMORY;
}
return E_NOINTERFACE;
}
// GetDisplayNameOf
STDMETHODIMP CShellFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET lpName)
{
TCHAR szText[MAX_PATH] = {0};
// Get the name to display in the left pane, address bar, etc
m_pPidlMgr->GetPidlPath(pidl, szText);
// Must convert string to Unicode, so allocate a wide character string
int cchOleStr = lstrlen(szText) + 1;
lpName->pOleStr = reinterpret_cast<LPWSTR>(m_pMalloc->Alloc(cchOleStr * sizeof(WCHAR)));
if(!lpName->pOleStr)
return E_OUTOFMEMORY;
lpName->uType = STRRET_WSTR;
mbstowcs(lpName->pOleStr, szText, cchOleStr);
return S_OK;
}
// ParseDisplayName
STDMETHODIMP CShellFolder::ParseDisplayName( HWND hwndOwner,
LPBC pbcReserved, LPOLESTR lpDisplayName,
LPDWORD pdwEaten, LPITEMIDLIST *pPidlNew,
LPDWORD pdwAttributes )
{
return E_NOTIMPL;
}
// SetNameOf
STDMETHODIMP CShellFolder::SetNameOf( HWND hwndOwner,
LPCITEMIDLIST pidl, LPCOLESTR lpName,
DWORD dw, LPITEMIDLIST *pPidlOut )
{
return E_NOTIMPL;
}
/* End of file: ShlFldr.cpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -