📄 bcgpshelllist.cpp
字号:
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This is a part of the BCGControlBar Library
// Copyright (C) 1998-2000 BCGSoft Ltd.
// All rights reserved.
//
// This source code can be used, distributed or modified
// only under terms and conditions
// of the accompanying license agreement.
//*******************************************************************************
// BCGPShellList.cpp : implementation file
//
#include "stdafx.h"
#include "BCGPShellList.h"
#include "BCGPShellTree.h"
#include ".\bcgpshelllist.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
UINT BCGPM_CHANGE_CURRENT_FOLDER = ::RegisterWindowMessage (_T("BCGPM_CHANGE_CURRENT_FOLDER"));
UINT BCGPM_SELECT_ITEMS_CHANGED = ::RegisterWindowMessage (_T("BCGPM_SELECT_ITEMS_CHANGED"));
IMPLEMENT_DYNAMIC(CBCGPShellList, CBCGPListCtrl)
IContextMenu2* CBCGPShellList::m_pContextMenu2 = NULL;
/////////////////////////////////////////////////////////////////////////////
// CBCGPShellList
CBCGPShellList::CBCGPShellList()
{
m_psfCurFolder = NULL;
m_pidlCurFQ = NULL;
m_bContextMenu = TRUE;
m_hwndRelatedTree = NULL;
m_bIsDesktop = FALSE;
m_bNoNotify = FALSE;
m_nTypes = (SHCONTF) (SHCONTF_FOLDERS | SHCONTF_NONFOLDERS);
}
CBCGPShellList::~CBCGPShellList()
{
}
BEGIN_MESSAGE_MAP(CBCGPShellList, CBCGPListCtrl)
//{{AFX_MSG_MAP(CBCGPShellList)
ON_WM_CREATE()
ON_NOTIFY_REFLECT(LVN_DELETEITEM, OnDeleteitem)
ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnLvnItemchanged)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
ON_NOTIFY_REFLECT(NM_RETURN, OnReturn)
ON_WM_CONTEXTMENU()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBCGPShellList message handlers
void CBCGPShellList::ReleaseCurrFolder ()
{
ASSERT_VALID (g_pShellManager);
if (m_psfCurFolder != NULL)
{
m_psfCurFolder->Release();
m_psfCurFolder = NULL;
g_pShellManager->FreeItem (m_pidlCurFQ);
m_pidlCurFQ = NULL;
}
}
//*****************************************************************************************
int CBCGPShellList::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CBCGPListCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
if (!InitList ())
{
return -1;
}
return 0;
}
//***************************************************************************************
HIMAGELIST CBCGPShellList::GetShellImageList (BOOL bLarge)
{
TCHAR szWinDir [MAX_PATH + 1];
if (GetWindowsDirectory (szWinDir, MAX_PATH) == 0)
{
return NULL;
}
SHFILEINFO sfi;
HIMAGELIST hImageList = (HIMAGELIST) SHGetFileInfo (szWinDir,
0,
&sfi,
sizeof (SHFILEINFO),
SHGFI_SYSICONINDEX | (bLarge ? 0 : SHGFI_SMALLICON));
return hImageList;
}
//***************************************************************************************
HRESULT CBCGPShellList::LockCurrentFolder (LPBCGCBITEMINFO pItemInfo)
{
ASSERT_VALID (g_pShellManager);
HRESULT hr = E_FAIL;
m_pidlCurFQ = NULL;
if (pItemInfo != NULL && pItemInfo->pParentFolder != NULL)
{
ASSERT (pItemInfo->pidlRel != NULL);
hr = pItemInfo->pParentFolder->BindToObject(pItemInfo->pidlRel, NULL, IID_IShellFolder, (LPVOID*)&m_psfCurFolder);
m_bIsDesktop = FALSE;
}
else
{
hr = SHGetDesktopFolder (&m_psfCurFolder);
m_bIsDesktop = TRUE;
}
if (SUCCEEDED (hr))
{
m_pidlCurFQ = g_pShellManager->CopyItem (pItemInfo->pidlFQ);
}
return hr;
}
//***************************************************************************************
HRESULT CBCGPShellList::DisplayFolder (LPBCGCBITEMINFO pItemInfo)
{
HRESULT hr = E_FAIL;
if (g_pShellManager == NULL)
{
ASSERT (FALSE);
return hr;
}
if (pItemInfo != NULL)
{
ReleaseCurrFolder();
hr = LockCurrentFolder(pItemInfo);
if (FAILED(hr))
{
return hr;
}
}
DeleteAllItems ();
if (m_psfCurFolder != NULL)
{
CWaitCursor wait;
SetRedraw (FALSE);
hr = EnumObjects (m_psfCurFolder, m_pidlCurFQ);
if (GetStyle () & LVS_REPORT)
{
Sort (BCGPShellList_ColumnName);
}
SetRedraw (TRUE);
RedrawWindow ();
}
if (SUCCEEDED (hr) && pItemInfo != NULL)
{
CBCGPShellTree* pTree = GetRelatedTree ();
if (pTree != NULL && !m_bNoNotify)
{
ASSERT_VALID (pTree);
pTree->SelectPath (m_pidlCurFQ);
}
if (GetParent () != NULL)
{
GetParent ()->SendMessage (BCGPM_CHANGE_CURRENT_FOLDER);
}
}
return hr;
}
//***************************************************************************************
HRESULT CBCGPShellList::DisplayParentFolder ()
{
ASSERT_VALID (g_pShellManager);
HRESULT hr = E_FAIL;
if (m_pidlCurFQ == NULL)
{
return hr;
}
BCGCBITEMINFO info;
int nLevel = g_pShellManager->GetParentItem (m_pidlCurFQ, info.pidlFQ);
if (nLevel < 0)
{
return hr;
}
if (nLevel == 0) // Desktop
{
hr = DisplayFolder (&info);
}
else
{
LPSHELLFOLDER pDesktopFolder;
hr = SHGetDesktopFolder(&pDesktopFolder);
if (SUCCEEDED (hr))
{
info.pParentFolder = pDesktopFolder;
info.pidlRel = info.pidlFQ;
hr = DisplayFolder (&info);
pDesktopFolder->Release();
}
}
g_pShellManager->FreeItem (info.pidlFQ);
return hr;
}
//***************************************************************************************
HRESULT CBCGPShellList::DisplayFolder (LPCTSTR lpszPath)
{
if (g_pShellManager == NULL)
{
ASSERT (FALSE);
return E_FAIL;
}
ASSERT (lpszPath != NULL);
ASSERT_VALID (g_pShellManager);
BCGCBITEMINFO info;
HRESULT hr = g_pShellManager->ItemFromPath (lpszPath, info.pidlRel);
if (FAILED (hr))
{
return hr;
}
LPSHELLFOLDER pDesktopFolder;
hr = SHGetDesktopFolder(&pDesktopFolder);
if (SUCCEEDED (hr))
{
info.pParentFolder = pDesktopFolder;
info.pidlFQ = info.pidlRel;
hr = DisplayFolder (&info);
pDesktopFolder->Release();
}
g_pShellManager->FreeItem (info.pidlFQ);
return hr;
}
//****************************************************************************************
HRESULT CBCGPShellList::Refresh ()
{
return DisplayFolder ((LPBCGCBITEMINFO) NULL);
}
//***************************************************************************************
HRESULT CBCGPShellList::EnumObjects (LPSHELLFOLDER pParentFolder,
LPITEMIDLIST pidlParent)
{
ASSERT_VALID (this);
ASSERT_VALID (g_pShellManager);
LPENUMIDLIST pEnum;
HRESULT hRes = pParentFolder->EnumObjects (NULL, m_nTypes, &pEnum);
if (SUCCEEDED (hRes))
{
LPITEMIDLIST pidlTemp;
DWORD dwFetched = 1;
LPBCGCBITEMINFO pItem;
//enumerate the item's PIDLs
while (pEnum->Next(1, &pidlTemp, &dwFetched) == S_OK && dwFetched)
{
LVITEM lvItem;
ZeroMemory(&lvItem, sizeof(lvItem));
//fill in the TV_ITEM structure for this item
lvItem.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
//AddRef the parent folder so it's pointer stays valid
pParentFolder->AddRef();
//put the private information in the lParam
pItem = (LPBCGCBITEMINFO)GlobalAlloc(GPTR, sizeof(BCGCBITEMINFO));
pItem->pidlRel = pidlTemp;
pItem->pidlFQ = g_pShellManager->ConcatenateItem (pidlParent, pidlTemp);
pItem->pParentFolder = pParentFolder;
lvItem.lParam = (LPARAM)pItem;
lvItem.pszText = _T("");
lvItem.iImage = OnGetItemIcon (GetItemCount (), pItem);
//determine if the item is shared
DWORD dwAttr = SFGAO_DISPLAYATTRMASK;
pParentFolder->GetAttributesOf (1, (LPCITEMIDLIST*)&pidlTemp, &dwAttr);
if (dwAttr & SFGAO_SHARE)
{
lvItem.mask |= LVIF_STATE;
lvItem.stateMask |= LVIS_OVERLAYMASK;
lvItem.state |= INDEXTOOVERLAYMASK(1); //1 is the index for the shared overlay image
}
if (dwAttr & SFGAO_GHOSTED)
{
lvItem.mask |= LVIF_STATE;
lvItem.stateMask |= LVIS_CUT;
lvItem.state |= LVIS_CUT;
}
int iItem = InsertItem (&lvItem);
if (iItem >= 0)
{
//-------------
// Set columns:
//-------------
const int nColumns = (GetStyle () & LVS_REPORT) ?
m_wndHeader.GetItemCount () : 1;
for (int iColumn = 0; iColumn < nColumns; iColumn++)
{
SetItemText (iItem, iColumn,
OnGetItemText (iItem, iColumn, pItem));
}
}
dwFetched = 0;
}
pEnum->Release ();
}
return hRes;
}
//***************************************************************************************
void CBCGPShellList::DoDefault (int iItem)
{
LVITEM lvItem;
ZeroMemory(&lvItem, sizeof(lvItem));
lvItem.mask = LVIF_PARAM;
lvItem.iItem = iItem;
if (!GetItem (&lvItem))
{
return;
}
LPBCGCBITEMINFO pInfo = (LPBCGCBITEMINFO) lvItem.lParam;
if (pInfo == NULL || pInfo->pParentFolder == NULL || pInfo->pidlRel == NULL)
{
ASSERT (FALSE);
return;
}
IShellFolder *psfFolder = pInfo->pParentFolder;
if (psfFolder == NULL)
{
SHGetDesktopFolder (&psfFolder);
}
else
{
psfFolder->AddRef ();
}
if (psfFolder == NULL)
{
return;
}
//-----------------------------------------------------
// If specified element is a folder, try to display it:
//-----------------------------------------------------
ULONG ulAttrs = SFGAO_FOLDER;
psfFolder->GetAttributesOf (1,
(const struct _ITEMIDLIST **) &pInfo->pidlRel, &ulAttrs);
if (ulAttrs & SFGAO_FOLDER)
{
DisplayFolder (pInfo);
}
else
{
//-------------------------------
// Invoke a default menu command:
//-------------------------------
IContextMenu *pcm;
HRESULT hr = psfFolder->GetUIObjectOf (GetSafeHwnd (),
1,
(LPCITEMIDLIST*)&pInfo->pidlRel,
IID_IContextMenu,
NULL,
(LPVOID*)&pcm);
if (SUCCEEDED (hr))
{
HMENU hPopup = CreatePopupMenu ();
if (hPopup != NULL)
{
hr = pcm->QueryContextMenu (hPopup, 0, 1, 0x7fff,
CMF_DEFAULTONLY | CMF_EXPLORE);
if (SUCCEEDED (hr))
{
UINT idCmd = ::GetMenuDefaultItem (hPopup, FALSE, 0);
if (idCmd != 0 && idCmd != (UINT)-1)
{
CMINVOKECOMMANDINFO cmi;
cmi.cbSize = sizeof (CMINVOKECOMMANDINFO);
cmi.fMask = 0;
cmi.hwnd = GetParent()->GetSafeHwnd ();
cmi.lpVerb = (LPCSTR)(INT_PTR)(idCmd - 1);
cmi.lpParameters = NULL;
cmi.lpDirectory = NULL;
cmi.nShow = SW_SHOWNORMAL;
cmi.dwHotKey = 0;
cmi.hIcon = NULL;
hr = pcm->InvokeCommand (&cmi);
}
}
}
pcm->Release ();
}
}
psfFolder->Release ();
}
//***************************************************************************************
void CBCGPShellList::OnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult)
{
ASSERT_VALID (g_pShellManager);
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
LPBCGCBITEMINFO pItem = (LPBCGCBITEMINFO)pNMListView->lParam;
//free up the pidls that we allocated
g_pShellManager->FreeItem (pItem->pidlFQ);
g_pShellManager->FreeItem (pItem->pidlRel);
//this may be NULL if this is the root item
if (pItem->pParentFolder != NULL)
{
pItem->pParentFolder->Release ();
pItem->pParentFolder = NULL;
}
GlobalFree ((HGLOBAL) pItem);
*pResult = 0;
}
//*****************************************************************************************
void CBCGPShellList::OnDblclk(NMHDR* /*pNMHDR*/, LRESULT* pResult)
{
int nItem = GetNextItem(-1, LVNI_FOCUSED);
if (nItem != -1)
{
DoDefault (nItem);
}
*pResult = 0;
}
//****************************************************************************************
void CBCGPShellList::OnReturn(NMHDR* /*pNMHDR*/, LRESULT* pResult)
{
int nItem = GetNextItem(-1, LVNI_FOCUSED);
if (nItem != -1)
{
DoDefault(nItem);
}
*pResult = 0;
}
//***************************************************************************************
BOOL CBCGPShellList::GetItemPath (CString& strPath, int iItem) const
{
ASSERT_VALID (this);
strPath.Empty ();
LPBCGCBITEMINFO pItem = (LPBCGCBITEMINFO) GetItemData (iItem);
if (pItem == NULL || pItem->pidlFQ == NULL)
{
return FALSE;
}
TCHAR szPath [MAX_PATH];
if (!SHGetPathFromIDList (pItem->pidlFQ, szPath))
{
return FALSE;
}
strPath = szPath;
return TRUE;
}
//***************************************************************************************
BOOL CBCGPShellList::GetCurrentFolder (CString& strPath) const
{
ASSERT_VALID (this);
strPath.Empty ();
if (m_pidlCurFQ == NULL)
{
return FALSE;
}
TCHAR szPath [MAX_PATH];
if (!SHGetPathFromIDList (m_pidlCurFQ, szPath))
{
return FALSE;
}
strPath = szPath;
return TRUE;
}
//***************************************************************************************
BOOL CBCGPShellList::GetCurrentFolderName (CString& strName) const
{
ASSERT_VALID (this);
strName.Empty ();
if (m_pidlCurFQ == NULL)
{
return FALSE;
}
SHFILEINFO sfi;
if (!SHGetFileInfo((LPCTSTR)m_pidlCurFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_DISPLAYNAME))
{
return FALSE;
}
strName = sfi.szDisplayName;
return TRUE;
}
//****************************************************************************************
CString CBCGPShellList::OnGetItemText (int /*iItem*/, int iColumn,
LPBCGCBITEMINFO pItem)
{
ASSERT_VALID (this);
ASSERT (pItem != NULL);
SHFILEINFO sfi;
TCHAR szPath [MAX_PATH];
switch (iColumn)
{
case BCGPShellList_ColumnName:
if (SHGetFileInfo((LPCTSTR)pItem->pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_DISPLAYNAME))
{
return sfi.szDisplayName;
}
break;
case BCGPShellList_ColumnType:
if (SHGetFileInfo((LPCTSTR)pItem->pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_TYPENAME))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -