• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            l

            成都手游碼農一枚
            隨筆 - 32, 文章 - 0, 評論 - 117, 引用 - 0
            數據加載中……

            windows shell擴展右鍵菜單。

            由于工作的需求要實現像winrara那樣的shell擴展菜單,帶圖標的,針對某個類型的文件執行相應的操作,
            查了不少資料,終于解決了,效果如下圖中紅色矩形部分。



            最先想到的當然是最方便的,直接添加注冊表,只需在HCLR中需要處理的類型(即右鍵選中的文件類型)的注冊表項中的shell子鍵中加入新項,
            修改默認值為顯示名稱,顯示效果如上圖的<用“記事本”打開>菜單項。(*)代表任意類型的文件。



            然后再新項中加入command子鍵,默認值設置為運行程序的參數,如"notepad.exe %1”,其中%1代表右鍵選中的文件。

            這樣當點擊菜單后就可以執行你指定的程序("notepad")并傳入選中的文件名作為命令參數,這樣就可以處理這個文件了。

            其實這樣足以滿足需求了,但效果上還差了一點,很明顯少了個圖標。既然winrar都能實現,肯定是還有其它實現的方法了。

            于是就是處理圖標了,然而最終沒能找到好的方法,但如果是win7的話,還是有的,那就是在command中加入icon項,值為

            你的目標程序,然而如果是xp就行不通了。

            本想簡單的解決,但沒想到還是得用上復雜的方法,僅僅為了一個圖標 - -;。

            復雜的方法只能是通過擴展shell接口來實現,首先肯定得牽涉到COM,所以關于COM可以上網查下資料,再這里就不多說(其實

            讓我講我也不一定講得清楚),這里我就寫下得注意的地方就是了。

            1.創建工程這里我用的VS2005,創建一個ATL 項目,屬性不需要改,點默認的就可以了。

            2.右擊項目,添加,類,添加一個新ATL簡單對象。

            3.編輯代碼,關于IShellExtInit和IContextMenu接口可以查看MSDN,上面寫的很詳細。

             

            // CCContextMenuExt

            class ATL_NO_VTABLE CCContextMenuExt :
                
            public CComObjectRootEx<CComSingleThreadModel>,
                
            public CComCoClass<CCContextMenuExt, &CLSID_CContextMenuExt>,
                
            public IDispatchImpl<ICContextMenuExt, &IID_ICContextMenuExt, &LIBID_CtxMenuExtLib, /*wMajor =*/ 1/*wMinor =*/ 0>,
                
            public IShellExtInit,
                
            public IContextMenu
            {
            public:
                CCContextMenuExt()
                
            {
                }


            DECLARE_REGISTRY_RESOURCEID(IDR_CCONTEXTMENUEXT)


            BEGIN_COM_MAP(CCContextMenuExt)
                COM_INTERFACE_ENTRY(ICContextMenuExt)
                COM_INTERFACE_ENTRY(IDispatch)
                COM_INTERFACE_ENTRY(IShellExtInit)
                COM_INTERFACE_ENTRY(IContextMenu)
            END_COM_MAP()



                DECLARE_PROTECT_FINAL_CONSTRUCT()

                HRESULT FinalConstruct()
                
            {
                    m_hBitmap 
            = LoadBitmap(_hInstance, MAKEINTRESOURCE(IDB_MENU));
                    
            return S_OK;
                }


                
            void FinalRelease()
                
            {
                    
            if (m_hBitmap)
                    
            {
                        DeleteObject(m_hBitmap);
                    }

                }


            public:
                
            enum 
                
            {
                    IDM_CTXMENU 
            = 0,
                }
            ;

            public:

                HRESULT STDMETHODCALLTYPE Initialize( 
                    
            /* [in] */ LPCITEMIDLIST pidlFolder,
                    
            /* [in] */ IDataObject *pdtobj,
                    
            /* [in] */ HKEY hkeyProgID)
                
            {
                    HRESULT hr;
                    UINT    nFileCount;
                    UINT    nLen;

                    FORMATETC fmt 
            = 
                    
            {
                        CF_HDROP,
                        NULL,
                        DVASPECT_CONTENT,
                        
            -1,
                        TYMED_HGLOBAL
                    }
            ;

                    STGMEDIUM sm 
            = 
                    
            {
                        TYMED_HGLOBAL
                    }
            ;

                    hr 
            = pdtobj->GetData(&fmt, &sm);
                   
                    
            if (FAILED(hr))
                    
            {
                        
            return hr;
                    }


                    nFileCount 
            = DragQueryFile((HDROP)sm.hGlobal, 0xFFFFFFFF, NULL, 0);

                    
            if (nFileCount >= 1)
                    
            {
                        nLen 
            = DragQueryFile((HDROP)sm.hGlobal, 0, m_pszFileName, sizeof(m_pszFileName));
                        
                        
            if (nLen >0 && nLen <MAX_PATH)
                        
            {
                            m_pszFileName[nLen] 
            = _T('\0');
                            hr 
            = S_OK;
                        }

                        
            else
                        
            {
                            hr 
            = E_INVALIDARG;
                        }
                
                    }

                    
            else
                    
            {            
                        hr 
            = E_INVALIDARG;
                    }


                    ReleaseStgMedium(
            &sm);

                    
            return hr;
                }


                STDMETHOD(QueryContextMenu)(THIS_
                    HMENU hmenu,
                    UINT indexMenu,
                    UINT idCmdFirst,
                    UINT idCmdLast,
                    UINT uFlags)
                
            {
                    MENUITEMINFO mii;

                    
            if (uFlags & CMF_DEFAULTONLY)
                    
            {
                        
            return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
                    }


                    memset((
            void*)&mii, 0sizeof(mii));
                    mii.cbSize      
            = sizeof(mii);
                    mii.fMask       
            = MIIM_STRING | MIIM_CHECKMARKS | MIIM_ID | MIIM_STATE;
                    mii.cch         
            = lstrlen(SZ_MENUTEXT);
                    mii.dwTypeData  
            = SZ_MENUTEXT;

                    
            /*
                        這里用hbmpChecked而不用hbmpItem的原因
                        - -自己動手試試就知道了。
                    
            */

                    mii.hbmpItem
                    mii.hbmpChecked 
            = m_hBitmap;
                    mii.hbmpUnchecked 
            = m_hBitmap;
                    mii.fState      
            = MFS_ENABLED;
                    mii.wID         
            = idCmdFirst + indexMenu;

                    
            if (!InsertMenuItem(hmenu, indexMenu, TRUE, &mii))       
                    
            {
                         
            return E_FAIL;
                    }


                    lstrcpynA(m_pszVerb, 
            "protected_run"32);
                    lstrcpynW(m_pwszVerb, L
            "protected_run"32);

                    
            return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, IDM_CTXMENU + 1);
                }


                STDMETHOD(InvokeCommand)(THIS_
                    LPCMINVOKECOMMANDINFO lpici)
                
            {
                    BOOL fEx 
            = FALSE;
                    BOOL fUnicode 
            = FALSE;

                    
            if(lpici->cbSize == sizeof(CMINVOKECOMMANDINFOEX))
                    
            {
                        fEx 
            = TRUE;
                        
            if((lpici->fMask & CMIC_MASK_UNICODE))
                        
            {
                            fUnicode 
            = TRUE;
                        }

                    }


                    
            if!fUnicode && HIWORD(lpici->lpVerb))
                    
            {
                        
            if(StrCmpIA(lpici->lpVerb, m_pszVerb))
                        
            {
                            
            return E_FAIL;
                        }

                    }


                    
            else if( fUnicode && HIWORD(((CMINVOKECOMMANDINFOEX *) lpici)->lpVerbW))
                    
            {
                        
            if(StrCmpIW(((CMINVOKECOMMANDINFOEX *)lpici)->lpVerbW, m_pwszVerb))
                        
            {
                            
            return E_FAIL;
                        }

                    }


                    
            else if(LOWORD(lpici->lpVerb) != IDM_CTXMENU)
                    
            {
                        
            return E_FAIL;
                    }


                    
            else
                    
            {
                        
            //在此處理點擊事件.
                        MessageBox(NULL, m_pszFileName, _T(""), MB_OK);

                        
            return S_OK;
                        
                    }


                    
            return E_FAIL;

                }


                STDMETHOD(GetCommandString)(THIS_
                    UINT_PTR    idCmd,
                    UINT        uType,
                    UINT      
            * pwReserved,
                    LPSTR       pszName,
                    UINT        cchMax)
                
            {
                    HRESULT  hr 
            = E_INVALIDARG;
                    
            static CHAR szHelpTextA[] = "windows擴展菜單!";
                    
            static WCHAR szHelpTextW[] = L"windows擴展菜單!";

                    
            if(idCmd != IDM_CTXMENU)
                    
            {
                        
            return hr;
                    }


                    
            switch(uType)
                    
            {
                    
            case GCS_HELPTEXTA:
                        lstrcpynA((CHAR
            *)pszName, szHelpTextA, cchMax);
                        
            break

                    
            case GCS_HELPTEXTW: 
                        lstrcpynW((WCHAR
            *)pszName, szHelpTextW, cchMax);;
                        
            break

                    
            case GCS_VERBA:
                        lstrcpynA((CHAR
            *)pszName, m_pszVerb, cchMax);
                        
            break

                    
            case GCS_VERBW:
                        lstrcpynW((WCHAR
            *)pszName, m_pwszVerb, cchMax);
                        
            break;

                    
            default:
                        hr 
            = S_OK;
                        
            break
                    }

                    
            return hr;
                }


            private:
                TCHAR   m_pszFileName[MAX_PATH];
                HBITMAP m_hBitmap;
                CHAR    m_pszVerb[
            32];
                WCHAR   m_pwszVerb[
            32];

            }
            ;


            4.修改服務注冊、取消注冊函數,這里只需在需要處理的文件類型的shllex下的ContextMenuHandlers下創建項,并設置接口ID。

            // DllRegisterServer - 將項添加到系統注冊表
            STDAPI DllRegisterServer(void)
            {
                
            // 注冊對象、類型庫和類型庫中的所有接口
                HRESULT hr;
                HKEY hKey;

                
            static char pszGUID[] = "{C2397F2E-4BA3-4B9D-858A-F775761C023B}";

                hr 
            = _AtlModule.DllRegisterServer();
                
            if (FAILED(hr))
                
            {
                    
            return hr;
                }


                
            if (RegCreateKeyA(HKEY_CLASSES_ROOT, 
                    
            "*\\shellex\\ContextMenuHandlers\\CtxMenu"&hKey) != ERROR_SUCCESS)
                
            {
                    
            return E_FAIL;
                }


                
            if (RegSetValueA(hKey, NULL, REG_SZ, pszGUID,
                        (DWORD)strlen(pszGUID)) 
            != ERROR_SUCCESS)
                
            {
                    RegCloseKey(hKey);
                    
            return E_FAIL;
                }


              
                
            return hr;
            }



            // DllUnregisterServer - 將項從系統注冊表中移除
            STDAPI DllUnregisterServer(void)
            {
                RegDeleteKeyA(HKEY_CLASSES_ROOT, 
            "*\\shellex\\ContextMenuHandlers\\CtxMenu");

                
            return _AtlModule.DllUnregisterServer();
            }


            5.編譯運行,VS會自動替你注冊,當然也可以用regsvr32 自己注冊。

            下載地址:http://www.shnenglu.com/Files/shly/CtxMenuExt.rar

            注意:注冊后的DLL無法刪除,有種方法可以就是regsvr32 /u 取消注冊dll, 然后重啟explorer.exe。

            posted on 2011-10-09 21:37 l1989 閱讀(12163) 評論(8)  編輯 收藏 引用 所屬分類: windows

            評論

            # re: windows shell擴展右鍵菜單。[未登錄]  回復  更多評論   

            很好收藏!
            2011-10-11 11:13 | 飯中淹

            # re: windows shell擴展右鍵菜單。  回復  更多評論   

            總感覺COM入門太難
            2011-10-11 17:31 | LoveBeyond

            # re: windows shell擴展右鍵菜單。  回復  更多評論   

            @LoveBeyond
            嗯嗯,我也覺得好難,要不是受工作所迫,我才不會去看這些折磨自己。。。
            2011-10-11 17:38 | azl

            # re: windows shell擴展右鍵菜單。[未登錄]  回復  更多評論   

            我測試了下, 點擊文件的右鍵菜單能顯示。 但是點擊文件夾就沒有, 如果讓文件夾的右鍵菜單中也增加???
            2011-12-08 12:53 | WONDER

            # re: windows shell擴展右鍵菜單。  回復  更多評論   

            @WONDER
            怎么點擊文件夾也有自定義菜單,你實現了么
            2013-04-09 20:07 | zxgwxit

            # re: windows shell擴展右鍵菜單。[未登錄]  回復  更多評論   

            恩。很不錯。對于簡單的用第一種方法就可以了,不需要創建com組件。第二種創建com組件的方法,也可以學習一下。
            2013-09-21 11:41 | 王小亮

            # re: windows shell擴展右鍵菜單。[未登錄]  回復  更多評論   

            我拿這個例子操作了為什么,右鍵就是不見菜單呢,求幫助@WONDER
            2013-10-07 21:04 | Jeremy

            # re: windows shell擴展右鍵菜單。  回復  更多評論   

            注冊了重啟explorer以后,右鍵菜單還是沒有新加項嘛
            2014-06-24 13:56 | forcj
            久久免费视频网站| 久久精品国产99国产精品亚洲| 久久精品国产99久久久古代| 国内精品久久久久久久coent | 久久精品国产亚洲av麻豆色欲 | 国产精品久久久99| 午夜精品久久久久久| 久久五月精品中文字幕| 久久精品亚洲男人的天堂| 久久精品亚洲乱码伦伦中文| 久久黄色视频| 国产精品久久久久久久久久影院| 久久无码中文字幕东京热| 久久久久久亚洲精品不卡| 国产伊人久久| 久久久国产打桩机| 久久99精品久久久久久久不卡 | 久久本道综合久久伊人| 久久久99精品一区二区| 污污内射久久一区二区欧美日韩| 中文精品99久久国产| 国产亚洲美女精品久久久2020| 狠狠色综合网站久久久久久久高清| 久久精品国产亚洲av麻豆色欲 | 久久久久人妻一区二区三区vr| 成人资源影音先锋久久资源网| 亚洲国产精品久久久久| 久久这里只有精品视频99| 亚洲va国产va天堂va久久| …久久精品99久久香蕉国产| 久久99国产精品一区二区| 合区精品久久久中文字幕一区| 国产亚洲精品美女久久久| 99热精品久久只有精品| 久久久一本精品99久久精品88| 99久久国语露脸精品国产| 久久久久亚洲爆乳少妇无| 久久综合国产乱子伦精品免费| 久久影院午夜理论片无码| 久久久亚洲欧洲日产国码二区 | 国产精品久久久久久久久鸭|