65.9K
CodeProject 正在变化。 阅读更多。
Home

删除子菜单

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.13/5 (3投票s)

2004年4月23日

GPL3

2分钟阅读

viewsIcon

45095

如何在 VC++ 的文档/视图程序的文件菜单中添加删除子菜单

引言

使用过 Paint Shop Pro 7.0 的人一定见过菜单栏的文件菜单中的删除子菜单,并且一定想知道如何在自己的文档/视图程序中实现相同的功能,以编程方式从程序本身删除硬盘上的当前文档并将其发送到回收站。我不知道任何正确或标准的方法来做同样的事情,但我实现了一种方法,我将在这里介绍。

先决条件

本教程假设您熟悉 Visual C++/MFC、文档/视图架构、Windows 注册表以及本教程中使用的其他技术。虽然不需要非常详细地理解它们的底层原理,但您至少应该对这些底层原理的含义有一个基本的了解。

实现

这个实现并不难。 Windows 提供了一种标准方法来实现从内存中删除任何文档到回收站。我们只需要用正确的参数调用命令 SHFileOperation。首先,我们必须在程序的 Document 类中编写删除子菜单的菜单处理程序,并按如下所示实现它。在这个实现中,我们首先找出内存中文档的实际路径,并正确填充 SHFILEOPSTRUCT 结构,用该结构作为参数调用 SHFileOperation 命令。这将从内存中删除当前文档。还要记得关闭文档。然后我们将删除的文档文件路径写入注册表。不要忘记根据您的程序将注册表 string 更改为正确的路径。

///////////////////////////////////////////////////////////////
void CDemoDoc::OnFileDelete() 
{
    // OnFileDelete() Contributed by: 
    // <Priyank Bolia> priyank_bolia@yahoo.com
    // TODO: Add your command handler code here
    CString FileToDelete = GetPathName();
    FileToDelete+='\0';
    SHFILEOPSTRUCT sh={0};
    sh.hwnd=AfxGetApp()->m_pActiveWnd->GetSafeHwnd();
    sh.pFrom=FileToDelete;
    sh.wFunc=FO_DELETE;
    sh.fFlags=FOF_ALLOWUNDO;
    if(SHFileOperation(&sh)==0 && 
             sh.fAnyOperationsAborted==FALSE)
    {
        OnCloseDocument();
        FileToDelete.TrimRight('\0');
        HKEY hchildkey;
        DWORD dwdispositon;
        ::RegCreateKeyEx(HKEY_CURRENT_USER,
            "Software\\Company\\Product\\Settings",
            0,NULL,REG_OPTION_NON_VOLATILE,
            KEY_CREATE_SUB_KEY|KEY_ALL_ACCESS,NULL,
            &hchildkey,&dwdispositon);
        ::RegSetValueEx(hchildkey,"FileToDelete", 
            0,REG_SZ,(const BYTE*)(LPCTSTR)FileToDelete,
            (DWORD)FileToDelete.GetLength());
        ::RegCloseKey(hchildkey);
    }
}

void CDemoDoc::OnUpdateFileDelete(CCmdUI* pCmdUI) 
{
    // OnUpdateFileDelete(CCmdUI* pCmdUI) Contributed by: 
    // <Priyank Bolia> priyank_bolia@yahoo.com
    // TODO: Add your command update UI handler code here
    CString PathName = GetPathName();
    if(PathName.IsEmpty())
    {
        pCmdUI->Enable(FALSE);
    }
}
///////////////////////////////////////////////////////////////

文档已删除并关闭,但其路径仍保留在程序的 MRU(最近使用)列表中。要将其从那里删除,只需在应用程序类中为 MRU 列表编写另一个更新菜单处理程序,并按如下所示实现它。在这里,我们从注册表中读取已删除的文件路径,并在 m_pRecentFileList 数组中匹配它,如果我们在那里找到它,然后从那里删除它。同样,不要忘记根据您的程序将注册表路径更改为正确的路径。

void CDemoApp::OnUpdateFileMru(CCmdUI* pCmdUI) 
{
    // <Priyank Bolia> priyank_bolia@yahoo.com 
    // TODO: Add your command update UI handler code here
    ASSERT_VALID(this);
    if (m_pRecentFileList == NULL) // no MRU files
        pCmdUI->Enable(FALSE);
    else
    {
        HKEY hresult;
        if(::RegOpenKeyEx(HKEY_CURRENT_USER,
            "Software\\Company\\Product\\Settings",
            0,KEY_ALL_ACCESS,&hresult)==ERROR_SUCCESS)
        {
            BYTE value[255];
            DWORD dwcount=255;
            if(::RegQueryValueEx(hresult,"FileToDelete",
                     0,0,value,&dwcount)==ERROR_SUCCESS)
            {
                CString str=(LPCTSTR)value;
                CString str2;
                for(int i=0;i<m_pRecentFileList->GetSize();i++)
                {
                    str2=(LPCTSTR)(*m_pRecentFileList)[i];
                    if(str==str2)
                    {
                        m_pRecentFileList->Remove(i);
                        ::RegDeleteValue(hresult,"FileToDelete");
                    }
                }
            }
            ::RegCloseKey(hresult);
        }
        m_pRecentFileList->UpdateMenu(pCmdUI);
    }
}

结论

这使我们结束了,我们已经了解了为我们的软件赋予专业风格是多么容易。现在,我们都可以在几秒钟内将删除子菜单添加到我们的程序中,而无需担心过多的编程负担。唯一要做的就是将代码复制到您的程序,就像“即食餐”一样。欢迎您提出宝贵意见,以使本文更好。

Copyright

此代码按“原样”提供,不提供任何明示或暗示的保证。您可以不受任何限制地使用和滥用此代码。如果您在任何商业产品中使用此源代码,则无需致谢,但将不胜感激。

© . All rights reserved.