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

📄 shellctrls.h

📁 remote debug and compile tools
💻 H
📖 第 1 页 / 共 3 页
字号:
#if !defined(AFX_SHELLCTRLS_H__20010531_6E5C_D354_4C09_0080AD509054__INCLUDED_)
#define AFX_SHELLCTRLS_H__20010531_6E5C_D354_4C09_0080AD509054__INCLUDED_

#pragma once

/////////////////////////////////////////////////////////////////////////////
// CShellBaseCtrl - A few controls that display shell data
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2001 Bjarke Viksoe.
//
// Thanks to Anatoly Ivasyuk for adding sorting to the controls.
// Idea from a WTL Explorer sample by Leon Finker.
//
// 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 __cplusplus
  #error ATL requires C++ compilation (use a .cpp suffix)
#endif

#ifndef __ATLAPP_H__
  #error ShellCtrls.h requires atlapp.h to be included first
#endif

#ifndef __ATLCTRLS_H__
  #error ShellCtrls.h requires atlctrls.h to be included first
#endif

#ifndef __ATLSHELLEXT_H__
  #error ShellCtrls.h requires atlshellext.h to be included first
#endif

#if (_WIN32_IE < 0x0400)
  #error ShellCtrls.h requires _WIN32_IE >= 0x0400
#endif

#include <shlobj.h>


// The PARAM data of all controls
typedef struct {
   CComPtr<IShellFolder> spFolder;
   CPidl pidlFull;
   CPidl pidlNode;
   DWORD dwAttribs;
} SHELLITEMINFO, *PSHELLITEMINFO;

// Shell styles for all controls
#define SCT_EX_NOFOLDERS      0x00000001
#define SCT_EX_NOFILES        0x00000002
#define SCT_EX_SHOWHIDDEN     0x00000004
#define SCT_EX_NOREADONLY     0x00000008
#define SCT_EX_LOCALCOMPUTER  0x00000010
#define SCT_EX_FILESYSTEMONLY 0x00000020
#define SCT_EX_NOROOT         0x00000040


/////////////////////////////////////////////////////////////////////////////
// Misc Shell methods

inline BOOL AtlGetFilePidl(LPCTSTR pstrFileName, LPITEMIDLIST* pidl)
{
   ATLASSERT(!::IsBadStringPtr(pstrFileName, MAX_PATH));
   ATLASSERT(pidl);
   *pidl = NULL;
   // Make sure the file name is fully qualified and in Unicode format.
   TCHAR szFileName[MAX_PATH];
   ::GetFullPathName(pstrFileName, sizeof(szFileName)/sizeof(TCHAR), szFileName, NULL);
   USES_CONVERSION;
   LPOLESTR pwchPath = const_cast<LPOLESTR>(T2COLE(pstrFileName));
   // Convert the path name into a PIDL relative to the desktop
   CComPtr<IShellFolder> spFolder;
   if( FAILED( ::SHGetDesktopFolder(&spFolder) ) ) return FALSE;
   ULONG ulAttr;
   if( FAILED(spFolder->ParseDisplayName(NULL, NULL, pwchPath, NULL, pidl, &ulAttr)) ) return FALSE;   
   return TRUE;
};

inline BOOL AtlGetShellPidl(LPCITEMIDLIST pidl, IShellFolder** ppFolder, LPITEMIDLIST* pidlRel)
{
   ATLASSERT(pidl);
   ATLASSERT(ppFolder);
   ATLASSERT(pidlRel);

   *ppFolder = NULL;
   *pidlRel = NULL;

   // Get the desktop folder as a starting point
   CComPtr<IShellFolder> spFolder;
   if( FAILED( ::SHGetDesktopFolder(&spFolder) ) ) return FALSE;

   CPidl pidlMain;
   pidlMain.Copy(pidl);

   // Traverse each PIDL item and create a new IShellFolder for each of
   // them. Eventually we get to the last IShellFolder object and is left
   // with a simple (as opposed to complex) PIDL.
   int nCount = pidlMain.GetCount();
   while( --nCount > 0 ) {
      // Get the next PIDL entry
      CPidl pidlNext;
      pidlNext.Attach( pidlMain.CopyFirstItem() );
      if( pidlNext.IsEmpty() ) return FALSE;
      // Bind to the folder specified in the new item ID list.
      CComPtr<IShellFolder> spNextFolder;
      if( FAILED( spFolder->BindToObject(pidlNext, NULL, IID_IShellFolder, (LPVOID*) &spNextFolder)) ) return FALSE;
      spFolder = spNextFolder;
      // Strip first PIDL entry and copy remaining
      CPidl temp;
      temp.Copy( pidlMain.GetNextItem() );
      pidlMain.Attach(temp.Detach());
   }

   *ppFolder = spFolder.Detach();
   *pidlRel = pidlMain.Detach();
   return TRUE;
};


/////////////////////////////////////////////////////////////////////////////
// CShellBaseCtrl - Common shell control methods and properties

template< class T, typename TItem=int >
class CShellBaseCtrl
{
protected:
   DWORD m_dwShellStyle;

public:
   CShellBaseCtrl() : m_dwShellStyle(0UL)
   {
   }

   void SetShellStyle(DWORD dwStyle)
   {
      m_dwShellStyle = dwStyle;
   }

   DWORD GetShellStyle() const
   {
      return m_dwShellStyle;
   }

   BOOL Populate(int csidl = CSIDL_DESKTOP)
   {
      CPidl pidl;
      if( FAILED( ::SHGetSpecialFolderLocation(NULL, csidl, &pidl) ) ) return FALSE;
      CComPtr<IShellFolder> spDesktop;
      if( FAILED( ::SHGetDesktopFolder(&spDesktop) ) ) return FALSE;
      return Populate(spDesktop, pidl, csidl == CSIDL_DESKTOP ? NULL : (LPCITEMIDLIST)pidl);
   }

   BOOL Populate(LPCTSTR pstrPath)
   {
      ATLASSERT(!::IsBadStringPtr(pstrPath,MAX_PATH));
      USES_CONVERSION;
      CComPtr<IShellFolder> spDesktop;
      if( FAILED( ::SHGetDesktopFolder(&spDesktop) ) ) return FALSE;
      CPidl pidl;
      DWORD dwAttribs;
      DWORD dwEaten;
      LPCOLESTR pwstrPath = T2COLE(pstrPath);
      if( FAILED( spDesktop->ParseDisplayName(NULL, NULL, const_cast<LPOLESTR>(pwstrPath), &dwEaten, &pidl, &dwAttribs) ) ) return FALSE;
      return Populate(pidl);
   }

   BOOL Populate(LPCITEMIDLIST pidl)
   {
      CComPtr<IShellFolder> spFolder;
      CPidl pidlItem;
      if( !AtlGetShellPidl(pidl, &spFolder, &pidlItem) ) return FALSE;
      return Populate(spFolder, pidl, pidlItem);
   }

   BOOL Populate(IShellFolder* pFolder, LPCITEMIDLIST pidlPath, LPCITEMIDLIST pidlNode)
   {
      ATLASSERT(pFolder);
      ATLASSERT(pidlPath);
      CComPtr<IShellFolder> spFolder;
      DWORD dwAttribs = SFGAO_FILESYSANCESTOR | SFGAO_HASSUBFOLDER;
      if( pFolder != NULL && !CPidl::PidlIsEmpty(pidlNode) ) {
         // Get the new IShellFolder object
         if( FAILED( pFolder->BindToObject(pidlNode, NULL, IID_IShellFolder, (LPVOID*)&spFolder) ) ) return 0;
         // Get this folder's attributes
         pFolder->GetAttributesOf(1, &pidlNode, &dwAttribs);
      }
      else {
         // Folder is Desktop
         if( FAILED( ::SHGetDesktopFolder(&spFolder) ) ) return FALSE;
         dwAttribs = SFGAO_HASSUBFOLDER;
      }
      T* pT = static_cast<T*>(this);
      return pT->_Populate(spFolder, pidlPath, dwAttribs);
   }

   BOOL GetItemPidl(TItem hItem, LPITEMIDLIST* pidl)
   {
      T* pT = static_cast<T*>(this);
      pT;
      ATLASSERT(::IsWindow(pT->m_hWnd));
      ATLASSERT(pidl);
      // NOTE: We can't really check the 'hItem' argument here because it may
      //       actually be 0 for some controls (i.e. ListView has 0 as index)
      //       so we need to rely on the argument being passed is a valid item!
      *pidl = NULL;
      DWORD_PTR lParam = pT->GetItemData(hItem);
      if( lParam == NULL || lParam == -1 ) return FALSE;
      PSHELLITEMINFO pItem = reinterpret_cast<PSHELLITEMINFO>(lParam);
      *pidl = CPidl::PidlCopy(pItem->pidlFull);
      return TRUE;
   }

   BOOL GetItemPath(TItem hItem, LPTSTR pstrPath)
   {
      ATLASSERT(!::IsBadWritePtr(pstrPath, MAX_PATH));
      pstrPath[0]=_T('\0');
      CPidl pidl;
      if( !GetItemPidl(hItem, &pidl) ) return FALSE;
      if( !::SHGetPathFromIDList(pidl, pstrPath) ) return FALSE;
      return TRUE;
   }

   // Returns TRUE if PIDL should be filtered out...
   BOOL _FilterItem(IShellFolder* pFolder, LPCITEMIDLIST pidl, DWORD& dwAttribs) const
   {
      ATLASSERT(pFolder);
      ATLASSERT(pidl);

      if( m_dwShellStyle == 0 && dwAttribs == 0 ) return FALSE;
      dwAttribs |= SFGAO_DISPLAYATTRMASK | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR;

      // A fix by Anatoly Ivasyuk to only query for limited attributes on a
      // removable media (prevents floppy activity)...
      DWORD dwRemovable = SFGAO_REMOVABLE;
      pFolder->GetAttributesOf(1, &pidl, &dwRemovable);
      if( dwRemovable & SFGAO_REMOVABLE ) dwAttribs &= ~SFGAO_READONLY;
      pFolder->GetAttributesOf(1, &pidl, &dwAttribs);

      // Filter some items
      if( (m_dwShellStyle & SCT_EX_NOFOLDERS) && (dwAttribs & SFGAO_FOLDER) ) return TRUE;
      if( (m_dwShellStyle & SCT_EX_NOFILES) && ((dwAttribs & SFGAO_FOLDER) == 0) ) return TRUE;
      if( (m_dwShellStyle & SCT_EX_NOREADONLY) && (dwAttribs & SFGAO_READONLY) ) return TRUE;;
      if( (m_dwShellStyle & SCT_EX_FILESYSTEMONLY) && ((dwAttribs & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR)) == 0) ) return TRUE;

      return FALSE;
   }
};


/////////////////////////////////////////////////////////////////////////////
// CShellTreeCtrl

class CShellTreeCtrl :
   public CWindowImpl< CShellTreeCtrl, CTreeViewCtrl, CControlWinTraits >,
   public CShellBaseCtrl< CShellTreeCtrl, HTREEITEM >
{
public:
   typedef CWindowImpl< CShellTreeCtrl, CTreeViewCtrl, CControlWinTraits > parentClass;

   BEGIN_MSG_MAP(CShellTreeCtrl)
      MESSAGE_HANDLER(WM_CREATE, OnCreate)
      REFLECTED_NOTIFY_CODE_HANDLER(TVN_GETDISPINFO, OnGetDispInfo)
      REFLECTED_NOTIFY_CODE_HANDLER(TVN_DELETEITEM, OnDeleteItem)
      REFLECTED_NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING, OnItemExpanding)
      DEFAULT_REFLECTION_HANDLER()
   END_MSG_MAP()

   // Operations

   BOOL SubclassWindow(HWND hWnd)
   {
      ATLASSERT(m_hWnd==NULL);
      ATLASSERT(::IsWindow(hWnd));
      BOOL bRet = parentClass::SubclassWindow(hWnd);
      if( bRet ) _Init();
      return bRet;
   }

   BOOL SelectPidl(LPCITEMIDLIST pidlTarget)
   {
      ATLASSERT(::IsWindow(m_hWnd));
      // BUG: Assumes tree control's root is desktop!
      CPidl pidlItem;
      HTREEITEM hItem = GetRootItem();
      ATLASSERT(hItem!=NULL);
      while( !CPidl::PidlIsEmpty(pidlTarget) ) {
         hItem = GetChildItem(hItem);
         pidlItem.Attach( CPidl::PidlCopyFirstItem(pidlTarget) );

⌨️ 快捷键说明

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