我写了一个命名空间扩展(c++)。我现在要做的是复制 Windows 资源管理器的“打开方式”菜单。我已经使用 IContextMenu、IContextMenu2 和 IContextMenu3 实现了我的上下文菜单。我为一个虚拟文件构建了一个标准上下文菜单,并将打开方式子菜单放入我自己的菜单中。到目前为止,我所做的如下:
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;
}
在handleMenuMsg 函数中,我将所有内容传递给标准界面,并且XP 正在毫无问题地绘制图标和文本。然后,在“InvokeCommand”中,我知道是否执行了我自己的命令,或者它是否来自标准上下文菜单。因此,假设您使用资源管理器打开一个 txt 文件,一切正常。问题是尽快
this->m_stdCMT->InvokeCommand(pici);
执行并关闭资源管理器(Win7,x64),它不会再关闭进程。有人知道为什么吗?
亲切的问候,迈克尔