📄 bcgpshelltree.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.
//*******************************************************************************
// BCGShellTree.cpp : implementation file
//
#include "stdafx.h"
#include "BCGPShellTree.h"
#include "BCGPShellList.h"
#include "BCGPShellManager.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBCGPShellTree
IMPLEMENT_DYNAMIC(CBCGPShellTree, CTreeCtrl)
IContextMenu2* CBCGPShellTree::m_pContextMenu2 = NULL;
CBCGPShellTree::CBCGPShellTree()
{
m_bContextMenu = TRUE;
m_hwndRelatedList = NULL;
m_bNoNotify = FALSE;
m_dwFlags = SHCONTF_FOLDERS;
}
CBCGPShellTree::~CBCGPShellTree()
{
}
BEGIN_MESSAGE_MAP(CBCGPShellTree, CTreeCtrl)
//{{AFX_MSG_MAP(CBCGPShellTree)
ON_WM_CREATE()
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteitem)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONDOWN()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBCGPShellTree message handlers
int CBCGPShellTree::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
if (g_pShellManager == NULL)
{
TRACE0("You need to initialize CBCGPShellManager first\n");
return -1;
}
InitTree ();
return 0;
}
//***************************************************************************************
void CBCGPShellTree::SetRelatedList (CBCGPShellList* pShellList)
{
ASSERT_VALID (this);
m_hwndRelatedList = (pShellList == NULL) ? NULL : pShellList->GetSafeHwnd ();
if (pShellList != NULL)
{
pShellList->m_hwndRelatedTree = GetSafeHwnd ();
}
}
//***************************************************************************************
CBCGPShellList* CBCGPShellTree::GetRelatedList () const
{
ASSERT_VALID (this);
if (m_hwndRelatedList == NULL || !::IsWindow (m_hwndRelatedList))
{
return NULL;
}
CBCGPShellList* pList = DYNAMIC_DOWNCAST (CBCGPShellList,
CWnd::FromHandlePermanent (m_hwndRelatedList));
return pList;
}
//****************************************************************************************
void CBCGPShellTree::Refresh ()
{
ASSERT_VALID (this);
DeleteAllItems ();
GetRootItems ();
TreeView_SetScrollTime (GetSafeHwnd (), 100);
}
//***************************************************************************************
BOOL CBCGPShellTree::GetRootItems ()
{
ASSERT_VALID (this);
ASSERT_VALID (g_pShellManager);
LPITEMIDLIST pidl;
if (FAILED (SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOP, &pidl)))
{
return FALSE;
}
//--------------------------------
// Get the desktop's IShellFolder:
//--------------------------------
LPSHELLFOLDER pDesktop;
if (FAILED (SHGetDesktopFolder (&pDesktop)))
{
return FALSE;
}
//--------------------------------------------
// Fill in the TVITEM structure for this item:
//--------------------------------------------
TV_ITEM tvItem;
tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
//-------------------------------------------
// Put the private information in the lParam:
//-------------------------------------------
LPBCGCBITEMINFO pItem = (LPBCGCBITEMINFO) GlobalAlloc (GPTR, sizeof(BCGCBITEMINFO));
ASSERT (pItem != NULL);
pItem->pidlRel = pidl;
pItem->pidlFQ = g_pShellManager->CopyItem (pidl);
//-------------------------------------------------------------
// The desktop doesn't have a parent folder, so make this NULL:
//-------------------------------------------------------------
pItem->pParentFolder = NULL;
tvItem.lParam = (LPARAM)pItem;
CString strItem = OnGetItemText (pItem);
tvItem.pszText = strItem.GetBuffer (strItem.GetLength ());
tvItem.iImage = OnGetItemIcon (pItem, FALSE);
tvItem.iSelectedImage = OnGetItemIcon (pItem, TRUE);
//---------------------------------
// Assume the desktop has children:
//---------------------------------
tvItem.cChildren = TRUE;
//-----------------------------------------------------
// Fill in the TV_INSERTSTRUCT structure for this item:
//-----------------------------------------------------
TV_INSERTSTRUCT tvInsert;
tvInsert.item = tvItem;
tvInsert.hInsertAfter = TVI_LAST;
tvInsert.hParent = TVI_ROOT;
//--------------
// Add the item:
//--------------
HTREEITEM hParentItem = InsertItem (&tvInsert);
//-------------------------------
// Go ahead and expand this item:
//-------------------------------
Expand (hParentItem, TVE_EXPAND);
pDesktop->Release();
return TRUE;
}
//***************************************************************************************
BOOL CBCGPShellTree::GetChildItems (HTREEITEM hParentItem)
{
ASSERT_VALID (this);
CWaitCursor wait;
//----------------------------
// Get the parent item's pidl:
//----------------------------
TVITEM tvItem;
ZeroMemory (&tvItem, sizeof(tvItem));
tvItem.mask = TVIF_PARAM;
tvItem.hItem = hParentItem;
if (!GetItem (&tvItem))
{
return FALSE;
}
SetRedraw (FALSE);
LPBCGCBITEMINFO pItem = (LPBCGCBITEMINFO) tvItem.lParam;
ASSERT (pItem != NULL);
LPSHELLFOLDER pParentFolder = NULL;
HRESULT hr;
//--------------------------------------------------------------------
// If the parent folder is NULL, then we are at the root
// of the namespace, so the parent of this item is the desktop folder
//--------------------------------------------------------------------
if (pItem->pParentFolder == NULL)
{
hr = SHGetDesktopFolder (&pParentFolder);
}
else
{
//---------------------------------------------------------
// Otherwise we need to get the IShellFolder for this item:
//---------------------------------------------------------
hr = pItem->pParentFolder->BindToObject (pItem->pidlRel,
NULL, IID_IShellFolder, (LPVOID*) &pParentFolder);
}
if (FAILED (hr))
{
SetRedraw ();
return FALSE;
}
EnumObjects (hParentItem, pParentFolder, pItem->pidlFQ);
//--------------------
// Sort the new items:
//--------------------
TV_SORTCB tvSort;
tvSort.hParent = hParentItem;
tvSort.lpfnCompare = CompareProc;
tvSort.lParam = 0;
SortChildrenCB (&tvSort);
SetRedraw ();
RedrawWindow ();
pParentFolder->Release ();
return TRUE;
}
//***************************************************************************************
HRESULT CBCGPShellTree::EnumObjects (HTREEITEM hParentItem,
LPSHELLFOLDER pParentFolder,
LPITEMIDLIST pidlParent)
{
ASSERT_VALID (this);
ASSERT_VALID (g_pShellManager);
LPENUMIDLIST pEnum;
HRESULT hr = pParentFolder->EnumObjects (NULL, m_dwFlags, &pEnum);
if (FAILED (hr))
{
return hr;
}
LPITEMIDLIST pidlTemp;
DWORD dwFetched = 1;
//----------------------------
// Enumerate the item's PIDLs:
//----------------------------
while (SUCCEEDED (pEnum->Next(1, &pidlTemp, &dwFetched)) && dwFetched)
{
TVITEM tvItem;
ZeroMemory (&tvItem, sizeof (tvItem));
//---------------------------------------------
// Fill in the TV_ITEM structure for this item:
//---------------------------------------------
tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE |
TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
//------------------------------------------------------
// AddRef the parent folder so it's pointer stays valid:
//------------------------------------------------------
pParentFolder->AddRef ();
//-------------------------------------------
// Put the private information in the lParam:
//-------------------------------------------
LPBCGCBITEMINFO pItem = (LPBCGCBITEMINFO)GlobalAlloc (GPTR, sizeof (BCGCBITEMINFO));
ASSERT (pItem != NULL);
pItem->pidlRel = pidlTemp;
pItem->pidlFQ = g_pShellManager->ConcatenateItem (pidlParent, pidlTemp);
pItem->pParentFolder = pParentFolder;
tvItem.lParam = (LPARAM)pItem;
CString strItem = OnGetItemText (pItem);
tvItem.pszText = strItem.GetBuffer (strItem.GetLength ());
tvItem.iImage = OnGetItemIcon (pItem, FALSE);
tvItem.iSelectedImage = OnGetItemIcon (pItem, TRUE);
//------------------------------------
// Determine if the item has children:
//------------------------------------
DWORD dwAttribs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER |
SFGAO_DISPLAYATTRMASK | SFGAO_CANRENAME;
pParentFolder->GetAttributesOf (1, (LPCITEMIDLIST*) &pidlTemp, &dwAttribs);
tvItem.cChildren = (dwAttribs & SFGAO_HASSUBFOLDER);
//---------------------------------
// Determine if the item is shared:
//---------------------------------
if (dwAttribs & SFGAO_SHARE)
{
tvItem.mask |= TVIF_STATE;
tvItem.stateMask |= TVIS_OVERLAYMASK;
tvItem.state |= INDEXTOOVERLAYMASK(1); //1 is the index for the shared overlay image
}
//-----------------------------------------------------
// Fill in the TV_INSERTSTRUCT structure for this item:
//-----------------------------------------------------
TVINSERTSTRUCT tvInsert;
tvInsert.item = tvItem;
tvInsert.hInsertAfter = TVI_LAST;
tvInsert.hParent = hParentItem;
InsertItem (&tvInsert);
dwFetched = 0;
}
pEnum->Release ();
return S_OK;
}
//***************************************************************************************
int CALLBACK CBCGPShellTree::CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
UNREFERENCED_PARAMETER(lParamSort);
LPBCGCBITEMINFO pItem1 = (LPBCGCBITEMINFO)lParam1;
LPBCGCBITEMINFO pItem2 = (LPBCGCBITEMINFO)lParam2;
HRESULT hr = pItem1->pParentFolder->CompareIDs (0,
pItem1->pidlRel,
pItem2->pidlRel);
if (FAILED (hr))
{
return 0;
}
return (short)SCODE_CODE(GetScode(hr));
}
//****************************************************************************************
void CBCGPShellTree::OnShowContextMenu (CPoint point)
{
if (m_pContextMenu2 != NULL)
{
return;
}
if (!m_bContextMenu)
{
Default ();
return;
}
HTREEITEM hItem = NULL;
if (point.x == -1 && point.y == -1)
{
hItem = GetSelectedItem ();
}
else
{
CPoint ptClient = point;
ScreenToClient (&ptClient);
hItem = HitTest (ptClient);
}
if (hItem == NULL)
{
return;
}
TVITEM tvItem;
ZeroMemory (&tvItem, sizeof (tvItem));
tvItem.mask = TVIF_PARAM;
tvItem.hItem = hItem;
if (!GetItem (&tvItem))
{
return;
}
LPBCGCBITEMINFO pInfo = (LPBCGCBITEMINFO)tvItem.lParam;
if (pInfo == NULL)
{
ASSERT (FALSE);
return;
}
IShellFolder* psfFolder = pInfo->pParentFolder;
if (psfFolder == NULL)
{
SHGetDesktopFolder (&psfFolder);
}
else
{
psfFolder->AddRef();
}
if (psfFolder != NULL)
{
HWND hwndParent = GetParent()->GetSafeHwnd ();
IContextMenu* pcm = NULL;
HRESULT hr = psfFolder->GetUIObjectOf (hwndParent,
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_NORMAL | CMF_EXPLORE);
if (SUCCEEDED (hr))
{
pcm->QueryInterface(IID_IContextMenu2, (LPVOID*)&m_pContextMenu2);
HWND hwndThis = GetSafeHwnd ();
UINT idCmd = TrackPopupMenu (hPopup,
TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON,
point.x,
point.y,
0,
GetSafeHwnd (),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -