Introduction
Those who have worked on Paint Shop Pro 7.0 must have seen the delete submenu in the file menu of the menubar, and must be wondering how to implement the same, in their Document/View program to delete the current document from the hard-disk and send it to the Recycle Bin programmatically from the program itself. I don't know any correct or standard method to do the same, but I have implemented a method that I will be presenting here.
Prerequisite
This tutorial assumes that you are familiar with Visual C++/MFC, Document/View architecture, Windows Registry and other technologies used in this tutorial. Though there is no need to understand their underpinnings in great details, you should at least have a working knowledge of what these underpinnings mean.
Implementation
This implementation is not very hard. Windows provides a standard method to implement the deletion of any document from the memory to the Recycle Bin. Only, we have to call the command SHFileOperation
with proper parameters. First of all, we have to write the menu handlers for the delete submenu in the Document
class of the program and implement it as shown below. In this implementation, we first find out the actual path of the document in memory and fill up the SHFILEOPSTRUCT
structure properly, calling the SHFileOperation
command with the structure as parameter. This will delete the current document from the memory. Remember also to close the document. Then we have written the deleted document file path to the registry. Don't forget to change the registry string
to a proper path according to your program.
void CDemoDoc::OnFileDelete()
{
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)
{
CString PathName = GetPathName();
if(PathName.IsEmpty())
{
pCmdUI->Enable(FALSE);
}
}
The document has been deleted and closed, but still its path resides in MRU (Most Recently Used) list of the program. To remove it from there also, just write another Update menu handler for the MRU list in the application class and implement it as shown below. Here, we read the deleted file path from the registry and match it in the m_pRecentFileList
array, if we found it there, then remove it from there. Don't forget here also to change the registry path to a proper one according to your program.
void CDemoApp::OnUpdateFileMru(CCmdUI* pCmdUI)
{
ASSERT_VALID(this);
if (m_pRecentFileList == NULL)
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);
}
}
Conclusion
This brings us to an end, we have learned how easy it is to give our software a professional touch. Now, we can all add delete submenu to our programs, within a matter of few seconds, without bothering about excessive burden of programming. The only thing to do, is to copy the code to your program, "Ready to eat meal". Your valuable suggestions are always welcome, to make this article better.
Copyright
This code is provided "as is" with no expressed or implied warranty. You can use and abuse this code without any restriction. If you use this source code in any commercial product, acknowledgment is not required but would be appreciated.