管理文件系统(一)

MSDN 2005 -> Win32 和 COM 开发 -> User Interface -> Windows User Experience -> Windows Shell -> Windows Shell -> Shell Programmer's Guide -> Shell Basics -> Managing the File System

翻译完这篇文章后,对《浏览名字空间》一文的示例程序进行了修改,增加在右键单击列表项时弹出菜单,提供剪切、复制、粘贴和删除功能。每次粘贴后,会把所有目标文件(文件夹)添加到当前用户的最近文档列表中,从开始菜单中选择“文档”命令就可以看到这个列表。主要使用的API为SHFileOperationSHAddToRecentDocsSHChangeNotify。程序修改后新的界面如下:

主要代码为:

1 在弹出右键菜单前更新菜单项状态
 


int CShellNamespace::UpdateContextMenu(HMENU hMenu)
{
    BOOL bRet;
    TCHAR* pNames;

    // 如果当前有选中的文件系统对象,则启用剪切/复制/删除,否则禁用
    pNames = GetSelectedItemNames();
    EnableMenuItem(hMenu,IDC_CUT,   MF_BYCOMMAND | (pNames ? MF_ENABLED : MF_GRAYED));
    EnableMenuItem(hMenu,IDC_COPY,  MF_BYCOMMAND | (pNames ? MF_ENABLED : MF_GRAYED));
    EnableMenuItem(hMenu,IDC_DELETE,MF_BYCOMMAND | (pNames ? MF_ENABLED : MF_GRAYED));
    delete []pNames;
   
    // 先前进行过剪切/复制操作,且当前文件夹是文件系统文件夹时,启用"粘贴",否则变灰
    bRet = FALSE;
    if (NULL != m_pSaveObjNames)
    {
        TCHAR szCurPath[MAX_PATH];
        bRet = SHGetPathFromIDList(m_pIdl,szCurPath);
    }
    EnableMenuItem(hMenu,IDC_PASTE,MF_BYCOMMAND | (bRet ? MF_ENABLED : MF_GRAYED));

    return 0;
}

GetSelectedItemNames()用于根据当前选中项生成SHFileOperation所要求格式的文件名列表,即多个以空字符结束的文件名字符串串接在一起,最后再多加一个空字符,表示整个列表的结束。如果没有选中任何项,GetSelectedItemNames()会返回空,此时使菜单中的剪切、复制、删除三项变灰。

SHGetPathFromIDList(m_pIdl,szCurPath)会判断当前文件夹是否是文件系统文件夹。如果不是文件系统文件夹,就不可能是粘贴目标,需要使菜单中的粘贴项变灰。

2 剪切和复制

int CShellNamespace::Cut()
{
    if (m_pSaveObjNames) delete []m_pSaveObjNames;
    m_pSaveObjNames = GetSelectedItemNames();
    m_bCutFlag = TRUE;
    return 0;
}

int CShellNamespace::Copy()
{
    if (m_pSaveObjNames) delete []m_pSaveObjNames;
    m_pSaveObjNames = GetSelectedItemNames();
    m_bCutFlag = FALSE;
    return 0;
}

 
执行剪切和复制命令时只是保存选中项的文件名列表,真正的操作要到粘贴时才进行。
 
3 粘贴
 

int CShellNamespace::Paste()
{
    SHFILEOPSTRUCT opStruct={0};
    TCHAR szDstDir[MAX_PATH + 10]={0};
   
    if (!SHGetPathFromIDList(m_pIdl,szDstDir)) return -1;
   
    opStruct.hwnd   = GetParent(m_pListCtrl->m_hWnd);
    opStruct.wFunc  = (m_bCutFlag ? FO_MOVE : FO_COPY);
    opStruct.pFrom  = m_pSaveObjNames;
    opStruct.pTo    = szDstDir;
    opStruct.fFlags = FOF_SIMPLEPROGRESS;

    SHFileOperation(&opStruct);

    // 所有目标文件(夹)添加到最近文档列表
    AddDstObjectsToRecentDocs(szDstDir);
   
    // 目标文件夹内容已经改变
    SHChangeNotify(SHCNE_UPDATEDIR,SHCNF_IDLIST,m_pIdl,0);
    // 源文件夹内容已经改变
    if (m_bCutFlag)
    {
        TCHAR szSrcDir[MAX_PATH];
        StrCpy(szSrcDir,m_pSaveObjNames);
        PathRemoveBackslash(szSrcDir);
        PathRemoveFileSpec(szSrcDir);
        SHChangeNotify(SHCNE_UPDATEDIR,SHCNF_PATH,szSrcDir,0);
        // 剪切后,源文件(夹)已经不存在了,不能再次粘贴
        delete []m_pSaveObjNames;
        m_pSaveObjNames = NULL;
    }

    RefreshList();

    return 0;
}

代码很简单,主要是调用SHFileOperation执行文件和文件夹的移动和复制操作。AddDstObjectsToRecentDocs()把所有目标文件和文件夹添加到当前用户的最近文档列表中,会在下面介绍。执行粘贴操作后,目标文件夹增加了新的内容;如果先前执行的是剪切操作,则源文件夹减少了一些内容。这时应该调用SHChangeNotify通知Shell名字空间已经发生的变化。

4 删除

int CShellNamespace::Delete()
{
    SHFILEOPSTRUCT opStruct={0};
    TCHAR* pDelObjNames;
   
    pDelObjNames = GetSelectedItemNames();
    if (NULL == pDelObjNames) return -1;
   
    opStruct.hwnd   = GetParent(m_pListCtrl->m_hWnd);
    opStruct.wFunc  = FO_DELETE;
    opStruct.pFrom  = pDelObjNames;
    opStruct.fFlags = FOF_SIMPLEPROGRESS;
   
    SHFileOperation(&opStruct);
   
    // 当前文件夹内容已经发生变化
    SHChangeNotify(SHCNE_UPDATEDIR,SHCNF_IDLIST,m_pIdl,0);
   
    RefreshList();

    delete []pDelObjNames;

    return 0;
}

 
与移动和复制文件操作类似,只是SHFILEOPSTRUCT结构体的wFunc成员值是FO_DELETE,表示删除对象。
 
5 添加粘贴的目标文件和文件夹到用户最近文档列表中
 


void CShellNamespace::AddDstObjectsToRecentDocs(const TCHAR* pszDstDir)
{
    const TCHAR* pNextItem;
    TCHAR szObjName[MAX_PATH];
    TCHAR szDstObjName[MAX_PATH];
   
    pNextItem = m_pSaveObjNames;
    while (_T('/0') != *pNextItem)
    {
        StrCpy(szObjName,pNextItem);
        PathStripPath(szObjName);

        StrCpy(szDstObjName,pszDstDir);
        PathAddBackslash(szDstObjName);
        StrCat(szDstObjName,szObjName);

        SHAddToRecentDocs(SHARD_PATH,szDstObjName);

        pNextItem += (lstrlen(pNextItem) + 1);
    }
}

 

主要是调用SHAddToRecentDocs添加名字空间对象的链接到用户的最近文档列表中。m_pSaveObjNames是粘贴的源文件和文件夹列表,注意其格式为:多个以空字符结束的文件名字符串串接在一起,最后再多加一个空字符,表示整个列表的结束。

翻译的文档原文见本文第二部分  


菊子曰 这就是 菊子曰啦!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值