在自己的上下文菜单中显示“打开方式”上下文菜单

时间:2013-03-22 12:39:41

标签: winapi explorer windows-shell wofstream

我写了一个命名空间扩展(c ++)。我现在要做的是复制Windows资源管理器'打开'菜单。我已经使用IContextMenu,IContextMenu2和IContextMenu3实现了我的上下文菜单。我为一个虚拟文件构建了一个标准的上下文菜单,并将带有子菜单的open打开到我自己的菜单中。到目前为止我所做的是以下内容:

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),它将不再关闭进程。有人知道为什么吗?

亲切的问候, 迈克尔

0 个答案:

没有答案