-
March 25th, 2013, 03:24 AM
#1
Display 'open with' context menu in own context menu
Hi,
I've written a namespace extension (c++). What I want to do now is to copy the windows explorers 'open with' menu. I've implemented my context menu using IContextMenu, IContextMenu2 and IContextMenu3. I build a standard context menu for a dummy file and put the open with submenu into my own menu. What I've done so far is the following:
Code:
int AddStdOpenWithMenu(HMENU hmenu, UINT& indexMenu, UINT& idCmdFirst, UINT& idCmdLast, UINT uFlags, CItem* i){
int items = 0;
if(i != 0){
CString filePath = i->GetTempFileDir();
CString fileName = i->getFileName();
if(PathFileExists(filePath)){
if(filePath.Right(1).CompareNoCase(TEXT("\\")) != 0) filePath += TEXT("\\");
filePath += fileName;
// Dumm yerzeugen
wofstream fStream;
fStream.open(filePath, ios::out | ios::app);
fStream.close();
if(PathFileExists(filePath)){
void* ppv = 0;
HRESULT hr;
LPITEMIDLIST pidl;
SFGAOF sfgao;
LPCITEMIDLIST pidlChild;
hr = ::SHParseDisplayName(filePath, NULL, &pidl, 0, &sfgao);
this->stdContextTmpDir = filePath;
if(hr == S_OK){
hr = SHBindToParent(pidl, IID_IShellFolder, (void**)&m_stdPSF, &pidlChild);
if(hr == S_OK){
hr = m_stdPSF->GetUIObjectOf(GetForegroundWindow(), 1, &pidlChild, IID_IContextMenu, NULL, &ppv);
if(hr == S_OK){
this->m_stdCTM = (IContextMenu*)ppv;
IContextMenu2* ctm2 = 0;
hr = this->m_stdCTM->QueryInterface(IID_IContextMenu2,(LPVOID*)&ctm2);
if(hr == S_OK){
HMODULE g = GetModuleHandle(TEXT("shell32.dll"));
if(g != 0){
// "Öffnen mit" Schriftzug ermitteln
int maxBuffer = 1000;
LPTSTR pStr = new TCHAR[maxBuffer];
CString owStr1, owStr2;
int res = LoadString(g, 5376, pStr, maxBuffer);
if(res > 0) owStr1 = pStr;
res = LoadString(g, 5377, pStr, maxBuffer);
if(res > 0) owStr2 = pStr;
if(!owStr1.IsEmpty() || !owStr2.IsEmpty()){
HMENU stdMenu = CreatePopupMenu();
int subIdCmdFirst = idCmdFirst + LASTMI + 1; // hier wird der maximale offset der Items addiert
int ret = ctm2->QueryContextMenu(stdMenu, indexMenu, subIdCmdFirst, idCmdLast, uFlags);
if(HRESULT_SEVERITY(ret) == SEVERITY_SUCCESS){
int count = GetMenuItemCount(stdMenu);
for(int i = 0; i < count; i++){
res = GetMenuString(stdMenu, i, pStr, maxBuffer, MF_BYPOSITION);
if(res > 0){
if(_tcscmp(pStr, owStr1) == 0 || _tcscmp(pStr, owStr2) == 0){
//Öffnen mit Element gefunden
HMENU subMenu = GetSubMenu(stdMenu, i);
if(subMenu != 0){
hr = ctm2->HandleMenuMsg(WM_INITMENUPOPUP, (WPARAM)GetSubMenu(stdMenu,i) , i);
subMenu = GetSubMenu(stdMenu, i);
if(subMenu != 0){
MENUITEMINFO mii;
TCHAR szText[MAX_PATH];
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
_tcscpy(szText, pStr);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU ;
mii.wID = idCmdFirst + MI_OPENWITH;
mii.fType = MFT_STRING;
mii.dwTypeData = szText;
mii.fState = MFS_ENABLED;
mii.hSubMenu = subMenu;
InsertMenuItem( hmenu, indexMenu++, TRUE, &mii);
items = HRESULT_CODE(ret);
}
}else{
MENUITEMINFO stdMi;
stdMi.cbSize = sizeof(stdMi);
stdMi.fMask = MIIM_ID | MIIM_STATE;
stdMi.dwTypeData = 0;
GetMenuItemInfo(stdMenu, i, true, &stdMi);
MENUITEMINFO mii;
TCHAR szText[MAX_PATH];
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
_tcscpy(szText, pStr);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
mii.wID = stdMi.wID;
mii.fType = MFT_STRING;
mii.dwTypeData = szText;
mii.fState = MFS_ENABLED;
InsertMenuItem( hmenu, indexMenu++, TRUE, &mii);
items = HRESULT_CODE(ret);
}
}
}
}
}
}
delete[] pStr;
}
ctm2->Release();
}
}
}
ILFree(pidl);
}
DeleteFile(filePath);
}
}
}
return items;
}
In the handleMenuMsg functions I pass everything to the standard interface and also XP is drawing icons and texts without any problem. In the 'InvokeCommand' I then know if a command for myself is executed or if it came from the standard context menu. So let's say you open a txt file with explorer everything works fine. The problem is as soon as
Code:
this->m_stdCMT->InvokeCommand(pici);
is executed and you close the explorer (Win7, x64), it won't close the process anymore. Does anybody know why?
What I've found out is, that as soon as I do not release a IContextMenu interface properly the whole explorer.exe process won't quit. It simply hangs... So I think InvokeCommand is allocating something which is not freed properly?! Any suggestions?
Kind regards, Michael
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|