打印本文 打印本文 关闭窗口 关闭窗口
仿Explorer的目录树视图类
作者:武汉SEO闵涛  文章来源:敏韬网  点击数5113  更新时间:2009/4/25 0:44:57  文章录入:mintao  责任编辑:mintao
tPath(HTREEITEM hNode);  // 取得结点的对应的路径
 BOOL AttachFolders(HTREEITEM hNode);  // 展开指定的结点下的子结点
 LONG GetVol_Ser(LPCTSTR strDriver);   // 获取卷标
 void ShowDesktop();                   // 显示桌面
 void RetrieveSysImageList();          // 获取系统图像列表
 void FreeNode(HTREEITEM hNode);       // 释放结点
 void FreeNodeData(LPFOLDERNODE lpfn); // 释放结点数据
 int  Expand(HTREEITEM hNode, UINT nCode); // 展开结点

};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_SHELLFOLDERVIEW_H__D30D10ED_3D11_4873_9909_146B8E18BEB1__INCLUDED_)

///////////////////////////////////////////////////////////////////////////
// ShellFolderView.cpp : implementation file
///////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ShellFolderView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define  WM_U_FOLDERCHANGED   (WM_USER+215)  // 消息

// 一些固定的名字:
static const char c_cMyComputer[] = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}";  // Normal = 我的电脑
static const char c_cNetworkNeighborhood[] = "::{208D2C60-3AEA-1069-A2D7-08002B30309D}";  // Normal = 网上邻居
static const char c_cRecycleBin[] = "::{645FF040-5081-101B-9F08-00AA002F954E}";  // Normal = 回收站
static const char c_cController[] = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}";  // Normal = 控制面板
static const char c_cPrinter[] = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}";  // Normal = 打印机
static const char c_cDial[] = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}";  // Normal = 网络和拨号连接
static const char c_cFonts[] = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D20EA4E1-3957-11D2-A40B-0C5020524152}";  // Normal = 字体
static const char c_cManager[] = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D20EA4E1-3957-11D2-A40B-0C5020524153}";  // Normal = 管理工具
static const char c_cPlans[] = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}";  // Normal = 任务计划

// 文件夹监视线程类
class  CFolderChangeMonitor
{
public:
 CFolderChangeMonitor(LPCTSTR lpszPath, HWND hWnd, WPARAM wParam);
 ~CFolderChangeMonitor();

private:
 CWinThread* m_pThread;
 CString     m_strPath;
 HWND        m_hWnd;
 WPARAM      m_wParam;
 BOOL        m_bStop;

 friend UINT MonitorProc(void* lp);
 void Run();
};

/////////////////////////////////////////////////////////////////////////////
// CFolderChangeMonitor class
/////////////////////////////////////////////////////////////////////////////
// 文件夹监视线程类的构造函数
// lpszPath : 被监视的文件夹
// hWnd     : 文件夹已经改变的消息将发往该窗口
// wParam   : 消息的参数,在这里是树上的一结点句柄
CFolderChangeMonitor::CFolderChangeMonitor(LPCTSTR lpszPath, HWND hWnd, WPARAM wParam)
:m_hWnd(hWnd), m_wParam(wParam), m_strPath(lpszPath)
{
 m_bStop = FALSE;
 // 开始监视线程
 m_pThread = AfxBeginThread(MonitorProc, (void*)this);
}

CFolderChangeMonitor::~CFolderChangeMonitor()
{
 // 停止监视线程
 m_bStop = TRUE;
 // 原来可以等待线程结束后才返回,后来不知道怎么搞的,居然会死锁,只好先不等待了,嘻嘻
// ::WaitForSingleObject(m_pThread->m_hThread, INFINITE);
}

// 监视线程函数
UINT MonitorProc(void*lp)
{
 if(lp)
 {
  // 将线程反调回类中
  ((CFolderChangeMonitor*)lp)->Run();
 }
 return 0;
}

// 监视函数
void CFolderChangeMonitor::Run()
{
 // 检测结束标志, 没有就一直循环
 while(!m_bStop)
 {
  // 创建事件句柄,当文件夹发生了指定的变化时,该事件被触发
  HANDLE handle = ::FindFirstChangeNotification(m_strPath, FALSE,
   FILE_NOTIFY_CHANGE_DIR_NAME);
  // 如果事件创建不成功则结束
  if(handle == INVALID_HANDLE_VALUE) break;

  // 开始监视
  if(::FindNextChangeNotification(handle))
  {
   int i = WAIT_TIMEOUT;
   // 除非指明结束监视或者发生了一次事件,否则一直循环等待
   while(i == WAIT_TIMEOUT && !m_bStop)
   {
    // 等待事件发生(每次等待20mS)因为线程需要不断检测m_bStop
    // 标志,以便及时退出,所以不能无限制地等待下去
    i = ::WaitForSingleObject(handle, 20);
   }
   // 循环结束,如果不是指定结束,则一定是发事件被触发了
   if(!m_bStop)
   {
    // 发送消息通知窗口来更新目录树
    ::SendMessage(m_hWnd, WM_U_FOLDERCHANGED, m_wParam,0);
   }
  }
  else
  {
   // 监视不能开始,则退出
   ::FindCloseChangeNotification(handle);
   break;
  }
  // 关闭事件
  ::FindCloseChangeNotification(handle);
 }
}


/***************************************************************
  FUNCTION : GetName

  描述:lpio lpsf所指的IshellFolder接口代表的文件夹下的相对PIDL,
  本函数获得lpi所指项的显示名称,dwFlags表明欲得到的显示名称类型,
  lpFriendlyName为存放显示名称的缓冲区。
 ***************************************************************/

BOOL GetName(LPSHELLFOLDER lpsf,LPITEMIDLIST lpi,DWORD dwFlags,LPSTR lpFriendlyName)
{
 STRRET str;
AGAIN:
 //得到显示名称
 if(NOERROR!=lpsf->GetDisplayNameOf(lpi,dwFlags,&str))
  return FALSE;

 //根据返回值进行转换
 switch(str.uType)
 {
 case STRRET_WSTR: //如为Unicode字符串,则转成Ansi字符集的字符串case STRRET_WSTR:
  if(str.pOleStr != NULL)
   WideCharToMultiByte(CP_ACP,0,str.pOleStr,-1,lpFriendlyName,MAX_PATH,NULL,NULL);
  else if(dwFlags == SHGDN_NORMAL)
  {
    dwFlags = SHGDN_FORPARSING;
    goto AGAIN;
  }
  break;
 case STRRET_OFFSET: //如为偏移量,则去除偏移量
  lstrcpy(lpFriendlyName,(LPSTR)lpi+str.uOffset);
  break;
 case STRRET_CSTR: // 如为Ansi字符串,则直接拷贝
  lstrcpy(lpFriendlyName,(LPSTR)str.cStr);
  break;
 default: //非法情况
  return FALSE;

 }

 return TRUE;
}

// 获取路径
void GetLongFilePath(IShellFolder* pShellFolder, LPITEMIDLIST  lpidl, LPFILEPATHLIST lpfpl)
{
 BOOL bRelease = FALSE;
 // 如果IShellFolder接口为空,则使用桌面的IShellFolder接口
 if(pShellFolder == NULL)
 {
  if(SHGetDesktopFolder(&pShellFolder) != NOERROR)
   return;
  bRelease = TRUE;
 }
 // 取得显示, PIDL及相对名称
 GetName(pShellFolder, lpidl, SHGDN_NORMAL,     lpfpl->cNormal);
 GetName(p

上一页  [1] [2] [3] [4] [5] [6]  下一页

打印本文 打印本文 关闭窗口 关闭窗口