⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shellpidl.cpp

📁 vc座的资源管理器源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// You may use this source code, compile or redistribute it as part of your application 
// for free. You cannot redistribute it as a part of a software development 
// library without the agreement of the author. If the sources are 
// distributed along with the application, you should leave the original 
// copyright notes in the source code without any changes.
// This code can be used WITHOUT ANY WARRANTIES at your own risk.
// 
// For the latest updates to this code, check this site:
// http://www.masmex.com 
// after Sept 2000
// 
// Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
//*******************************************************************************

// ShellPidl.cpp: implementation of the CShellPidl class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ShellPidl.h"
#include "UIMessages.h"
#include <intshcut.h>
#include <subsmgr.h>
#include <ExDisp.h>
#include "ShellContextMenu.h"
#include "UICoolMenu.h"
#include "cbformats.h"

#define SF_DRAGDROP_FLAGS SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK;
UINT CF_IDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
UINT CF_SHELLURL = RegisterClipboardFormat(CFSTR_SHELLURL);

#define TPM_FLAGS               (TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD)

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CShellPidl::CShellPidl()
{
	SHGetMalloc(&m_pMalloc);
    SHGetDesktopFolder(&m_psfDesktop);
	ZeroMemory(&m_EmptyPidl,sizeof(ITEMIDLIST));
}

CShellPidl::~CShellPidl()
{
	if (m_pMalloc)
		m_pMalloc->Release();
	if (m_psfDesktop)
		m_psfDesktop->Release();
}

IMalloc *CShellPidl::GetMalloc()
{
	return m_pMalloc;
}

DWORD CShellPidl::GetDragDropAttributes(LPLVITEMDATA plvid)
{
	return GetDragDropAttributes(plvid->lpsfParent,plvid->lpi);
}

DWORD CShellPidl::GetDragDropAttributes(LPTVITEMDATA ptvid)
{
	return GetDragDropAttributes(ptvid->lpsfParent,ptvid->lpi);
}

DWORD CShellPidl::GetDragDropAttributes(LPSHELLFOLDER pFolder,LPCITEMIDLIST pidl)
{
	if (pFolder == NULL)
		pFolder = m_psfDesktop;
	DWORD dwAttrs=SF_DRAGDROP_FLAGS;
	HRESULT hr = pFolder->GetAttributesOf(1,(LPCITEMIDLIST*)&pidl,&dwAttrs);
	if (FAILED(hr))
		dwAttrs = SF_DRAGDROP_FLAGS;
	return dwAttrs;
}

DWORD CShellPidl::GetDragDropAttributes(COleDataObject *pDataObject)
{
	IDataObject *pDataObj = pDataObject->m_lpDataObject;

	STGMEDIUM stgm;
	ZeroMemory(&stgm, sizeof(stgm));

    FORMATETC fetc;
    fetc.cfFormat = CF_IDLIST;
    fetc.ptd = NULL;
    fetc.dwAspect = DVASPECT_CONTENT;
    fetc.lindex = -1;
    fetc.tymed = TYMED_HGLOBAL;

	DWORD dwAttrs=DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
    HRESULT hr = pDataObj->QueryGetData(&fetc);
	if (FAILED(hr))
		return dwAttrs;
    hr = pDataObj->GetData(&fetc, &stgm);
	if (FAILED(hr))
		return dwAttrs;
    DWORD pData = (DWORD)GlobalLock(stgm.hGlobal);
	LPIDA pIDList = (LPIDA)pData;
	UINT nFolderOffset = pIDList->aoffset[0];
	TRACE2("PIDL(%u) offfset=%u\n",0,nFolderOffset);
	DWORD pFolder = pData+nFolderOffset;
    LPITEMIDLIST pidl = (LPITEMIDLIST)pFolder;
    LPSHELLFOLDER psfParent = GetFolder(pidl);
	if (psfParent)
	{
		// get attributes for the children
		TRACE1("PIDL count=%u\n",pIDList->cidl);
		for(UINT i=1;i < (pIDList->cidl+1);i++)
		{
			UINT nListOffset = pIDList->aoffset[i];
			TRACE2("PIDL(%u) offfset=%u\n",i,nListOffset);
			ULONG ulAttrs = SF_DRAGDROP_FLAGS;
			DWORD dwPidl = pData+nListOffset;
			LPITEMIDLIST pidlist = (LPITEMIDLIST)dwPidl;
			psfParent->GetAttributesOf(1,(LPCITEMIDLIST*)&pidlist,&ulAttrs);
#ifdef _DEBUG
			CString sPath;
			SHPidlToPathEx(pidlist,sPath,psfParent);
			TRACE2("Drag drop source path=%s Attributes=%u\n",sPath,ulAttrs);
#endif
			if (ulAttrs)
				dwAttrs = dwAttrs & ulAttrs;
		}
		psfParent->Release();
	}
	GlobalUnlock(stgm.hGlobal);
    ReleaseStgMedium(&stgm);
	return dwAttrs;
}

LPCITEMIDLIST CShellPidl::GetEmptyPidl()
{
	return &m_EmptyPidl;
}

bool CShellPidl::IsDesktopFolder(LPSHELLFOLDER psFolder)
{
	return psFolder == NULL || psFolder == m_psfDesktop;
}

LPSHELLFOLDER CShellPidl::GetDesktopFolder()
{
	return m_psfDesktop;
}

LPSHELLFOLDER CShellPidl::GetFolder(LPITEMIDLIST pidl)
{
	if (pidl == NULL || pidl->mkid.cb == 0)
		return m_psfDesktop;
	LPSHELLFOLDER pFolder=NULL;
	if (FAILED(m_psfDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pFolder)))
		return NULL;
	return pFolder;
}

// CopyItemID - creates an item identifier list containing the first 
//     item identifier in the specified list. 
// Returns a PIDL if successful, or NULL if out of memory. 
LPITEMIDLIST CShellPidl::CopyItemID(LPITEMIDLIST pidl,int n) 
{ 
	// Get the size of the specified item identifier. 
	ASSERT(pidl);
	if (n == 0)
	{
		int cb = pidl->mkid.cb;
		int nSize = cb + sizeof(pidl->mkid.cb);
		// Allocate a new item identifier list. 
		LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(nSize); 
		ZeroMemory(pidlNew,nSize);
		if (pidlNew == NULL) 
			return NULL; 
		// Copy the specified item identifier. 
		CopyMemory(pidlNew, pidl, nSize-sizeof(pidl->mkid.cb)); 
		return pidlNew; 
	}
	else
	{
		LPITEMIDLIST pidl_index=NULL;
  		for(int i=0;i < n && pidl->mkid.cb;i++)
		{
			pidl_index = pidl;
			pidl = Next(pidl);
		}
		return pidl_index ? CopyItemID(pidl_index,0) : NULL;
	}
	return NULL;
}

// Returns a PIDL if successful, or NULL if out of memory. 
LPITEMIDLIST CShellPidl::CopyLastItemID(LPITEMIDLIST pidl) 
{ 
	// Get the size of the specified item identifier. 
	ASSERT(pidl);
    if (pidl == NULL)
		return NULL;
	LPITEMIDLIST last_pidl=pidl;
    while (pidl->mkid.cb)
    {
		last_pidl = pidl;
        pidl = Next(pidl);
    }
	if (last_pidl == NULL)
		return NULL;
	return CopyItemID(last_pidl);
}

// copies the absolute pidl up till n
LPITEMIDLIST CShellPidl::CopyAbsItemID(LPITEMIDLIST pidl,int n) 
{ 
	// Get the size of the specified item identifier. 
	ASSERT(pidl);
    if (pidl == NULL)
		return NULL;
	LPITEMIDLIST first_pidl=NULL;
	LPITEMIDLIST abs_pidl=NULL;
	LPITEMIDLIST new_abs_pidl=NULL;
    for(int i=0;i < n && pidl && pidl->mkid.cb;i++)
    {
		first_pidl = CopyItemID(pidl);
		new_abs_pidl = ConcatPidl(abs_pidl,first_pidl);
		if (abs_pidl)
		{
			m_pMalloc->Free(abs_pidl);
		}
		abs_pidl = new_abs_pidl;
		if (first_pidl)
		{
			m_pMalloc->Free(first_pidl);
		}
        pidl = Next(pidl);
    }
	return new_abs_pidl;
}

// Makes a copy of an ITEMIDLIST 
LPITEMIDLIST CShellPidl::CopyItemIDList(LPITEMIDLIST pidl) 
{ 
	// Allocate a new item identifier list. 
	int nSize = GetSize(pidl);
	LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(nSize); 
	ZeroMemory(pidlNew,nSize);
	if (pidlNew == NULL) 
		return NULL; 
	// Copy the specified item identifier. 
	CopyMemory(pidlNew, pidl, nSize); 

	return pidlNew; 
}

bool CShellPidl::CompareMemPidls(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2) 
{ 
	// Allocate a new item identifier list. 
	if (pidl1 == NULL || pidl2 == NULL)
		return false;
	return memcmp(pidl1,pidl2,(size_t)GetSize(pidl1)) == 0;
}

// Returns true if lists are the same
bool CShellPidl::ComparePidls(LPSHELLFOLDER pFolder,LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2) 
{ 
	// Allocate a new item identifier list. 
	if (pFolder == NULL)
		pFolder = GetDesktopFolder();
	if (pidl1 == NULL || pidl2 == NULL)
		return false;
	return (short)pFolder->CompareIDs(0,pidl1,pidl2) == 0;
}

void CShellPidl::Free(void *pv)
{
	if (m_pMalloc)
		m_pMalloc->Free(pv);
}

void CShellPidl::FreePidl(LPITEMIDLIST pidl)
{
	if (m_pMalloc)
		m_pMalloc->Free(pidl);
}

UINT CShellPidl::GetCount(LPCITEMIDLIST pidl)
{
    UINT nCount = 0;
    if (pidl)
    {
        while (pidl->mkid.cb)
        {
            pidl = Next(pidl);
			nCount++;
        }
    }
    return nCount;
}

UINT CShellPidl::GetSize(LPCITEMIDLIST pidl)
{
    UINT cbTotal = 0;
    if (pidl)
    {
        cbTotal += sizeof(pidl->mkid.cb);       // Null terminator
        while (pidl->mkid.cb)
        {
            cbTotal += pidl->mkid.cb;
            pidl = Next(pidl);
        }
    }
    return cbTotal;
}

LPITEMIDLIST CShellPidl::Next(LPCITEMIDLIST pidl)
{
   LPSTR lpMem=(LPSTR)pidl;

   lpMem+=pidl->mkid.cb;

   return (LPITEMIDLIST)lpMem;
}

LPITEMIDLIST CShellPidl::ConcatPidl(LPITEMIDLIST pidlDest,LPITEMIDLIST pidlSrc) 
{ 
	// Get the size of the specified item identifier. 
    UINT cbDest=0;
    UINT cbSrc=0;
    if (pidlDest)  //May be NULL
       cbDest = GetSize(pidlDest) - sizeof(pidlDest->mkid.cb);
    cbSrc = GetSize(pidlSrc);

	// Allocate a new item identifier list. 
	LPITEMIDLIST pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(cbSrc+cbDest); 
	if (pidlNew == NULL) 
		return NULL; 
	ZeroMemory(pidlNew,cbSrc+cbDest);
	// Copy the specified item identifier. 
	if (pidlDest)
		CopyMemory(pidlNew, pidlDest, cbDest); 
	CopyMemory(((USHORT*)(((LPBYTE)pidlNew)+cbDest)), pidlSrc, cbSrc); 

	return pidlNew; 
}

int CShellPidl::GetIcon(LPITEMIDLIST lpi, UINT uFlags)
{
   SHFILEINFO    sfi;
   ZeroMemory(&sfi,sizeof(sfi));
   if (uFlags == 0)
		uFlags |= (SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
   uFlags |= SHGFI_PIDL;
   SHGetFileInfo((LPCTSTR)lpi, 0, &sfi, sizeof(SHFILEINFO), uFlags);

   return sfi.iIcon;
}

STDMETHODIMP CShellPidl::SHPidlToPathEx(LPCITEMIDLIST pidl, CString &sPath, LPSHELLFOLDER pFolder, DWORD dwFlags)
{
	STRRET StrRetFilePath;
	LPTSTR pszFilePath = NULL;
	HRESULT hr=E_FAIL;
	if (pFolder == NULL)
		pFolder = GetDesktopFolder();
	if (pFolder == NULL)
		return E_FAIL;
	hr = pFolder->GetDisplayNameOf(pidl, dwFlags, &StrRetFilePath);
	if (SUCCEEDED(hr))
	{
		StrRetToStr(StrRetFilePath, &pszFilePath, (LPITEMIDLIST)pidl);
		sPath = pszFilePath;
	}
	if (pszFilePath)
		m_pMalloc->Free(pszFilePath);
	return hr;
}

STDMETHODIMP CShellPidl::SHPathToPidlEx(LPCTSTR szPath, LPITEMIDLIST* ppidl, LPSHELLFOLDER pFolder)
{
   OLECHAR wszPath[MAX_PATH] = {0};
   ULONG nCharsParsed = 0;
   LPSHELLFOLDER pShellFolder = NULL;
   BOOL bFreeOnExit = FALSE;
#ifdef UNICODE
   lstrcpy(wszPath,szPath);
#else
   MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH);
#endif
   // Use the desktop's IShellFolder by default
   if(pFolder == NULL)
   {
      SHGetDesktopFolder(&pShellFolder);
      bFreeOnExit = TRUE;
   }
   else
      pShellFolder = pFolder;

   HRESULT hr = pShellFolder->ParseDisplayName(NULL, NULL, wszPath, &nCharsParsed, ppidl, NULL);

   if(bFreeOnExit)
      pShellFolder->Release();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -