• <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>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運(yùn)轉(zhuǎn),開心的工作
            簡單、開放、平等的公司文化;尊重個(gè)性、自由與個(gè)人價(jià)值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            給VC增加注釋/反注釋的功能

            Posted on 2009-11-23 18:35 S.l.e!ep.¢% 閱讀(546) 評(píng)論(0)  編輯 收藏 引用 所屬分類: VC

            給VC增加注釋/反注釋的功能
            ??????????????? ――楊科? 注:本文可隨意轉(zhuǎn)載, 但請(qǐng)保留我的署名(CopyLeft)

            用過VB,PowerBuilder的朋友一定知道在它們的工具條上有兩個(gè)按鈕,用來完成對(duì)選中的代碼進(jìn)行注釋或反注釋,而在VC中如果要注釋一段選中的代碼,除了在要注釋的代碼中添加/* 和 */外,就是對(duì)每一行都使用單行注釋//。其實(shí)在VC中提供了編寫插件的功能,VC將開發(fā)環(huán)境中的各種對(duì)象以COM接口的形式暴露出來,而且提供的插件應(yīng)用程序向?qū)Э梢酝瓿纱蟛糠值目蚣艽a,所以我們只需要添加我們想要的功能就可以了。所以我們可以利用這些COM接口來對(duì)VC的開發(fā)環(huán)境進(jìn)行操作,這樣我們就可以完成對(duì)選中的代碼的注釋和反注釋功能。

            下面具體描述以下開發(fā)這個(gè)插件的過程:
            首先創(chuàng)建一個(gè)新工程,類型選擇DevStudio Add-in Widzard,填寫工程名稱后,單擊OK繼續(xù)。在接下來的頁面中選中Provides a toolbar,這會(huì)使我們創(chuàng)建的插件具有一個(gè)工具條,不需要選中Responds to Developer Studio events,因?yàn)槲覀儾恍枰獙?duì)開發(fā)環(huán)境中的事件作出響應(yīng),在上面的兩個(gè)文本框中,可以隨便輸入一些你對(duì)這個(gè)插件的描述及功能介紹,單擊Finish完成向?qū)А?/p>

            對(duì)了,首先聲明以下,在VC中每一個(gè)Add-in都是一個(gè)COM組件,在Add-in的向?qū)е猩傻某绦蚴怯肕FC和ATL共同實(shí)現(xiàn)的,所以在生成的原代碼中你會(huì)看到兩個(gè)分別叫做theApp和_Module的全局變量。另外向?qū)槲覀兩闪艘粋€(gè)成為ICommands的接口,我們必須在這個(gè)接口添加適當(dāng)?shù)姆椒▉硗瓿晌覀冃枰墓δ堋?/p>

            讓我們看一下AppWidzard為我們生成了哪些類,首先我們會(huì)看到一個(gè)CCommands的類,而且其中實(shí)現(xiàn)了我們?cè)谏厦嫣岬降腎Commands接口。一個(gè)稱為CDSAddIn的類,這個(gè)類中實(shí)現(xiàn)兩個(gè)方法OnConnection(), OnDisconnection(), 這兩個(gè)方法我們不會(huì)直接在程序中調(diào)用,而是由VC集成環(huán)境調(diào)用的,當(dāng)VC啟動(dòng)時(shí)它會(huì)首先查詢關(guān)于Add-ins的注冊(cè)信息,然后調(diào)用相應(yīng)組件的OnConnection()方法,所以在這個(gè)方法中我們應(yīng)該把我們要實(shí)現(xiàn)的命令添加到VC的繼承環(huán)境中,當(dāng)這個(gè)插件被卸載或VC關(guān)閉時(shí),VC會(huì)調(diào)用OnDisconnection()方法,在這里我們應(yīng)該釋放我們?cè)贠nConnection()中分配的資源。

            剩下的就是應(yīng)用程序類了,另外還有一些必須的全局函數(shù)DllGetClassObject, DllCanUnloadNow, DllRegisterServer和DllUnregisterServer是COM組件的幾個(gè)通用實(shí)現(xiàn),可以查閱關(guān)于COM的書籍來了解這些知識(shí)。

            AppWidzard生成的代碼中在ICommands接口中實(shí)現(xiàn)了一個(gè)與應(yīng)用程序同名的方法,通常這個(gè)方法名稱并不是我們需要的,所以下面就開始來改寫這個(gè)方法,把它改成CommentCode。雙擊ICommands接口中的與你應(yīng)用程序同名的方法,VC會(huì)打開一個(gè)與你的應(yīng)用程序同名的一個(gè)擴(kuò)展名是odl的文件,找到一行叫做HRESULT YourAppCommandMethod()并把YourAppCommandMethod改成CommentCode(),然后打開Commands.cpp和Commands.h把其中的YourAppCommandMethod都改成CommentCode()。

            現(xiàn)在我們修改DSAddIn.cpp,找到OnConnection方法,直接找到下面這斷代碼:
            LPCTSTR szCommand = _T("YourAppCommand");
            VARIANT_BOOL bRet;
            CString strCmdString;
            strCmdString.LoadString(IDS_CMD_STRING);
            strCmdString = szCommand + strCmdString;
            CComBSTR bszCmdString(strCmdString);
            CComBSTR bszMethod(_T("YourAppCommandMethod"));
            CComBSTR bszCmdName(szCommand);
            VERIFY_OK(pApplication->AddCommand(bszCmdString, bszMethod, 0, m_dwCookie, &bRet));
            并把它改成下面的樣子:
            LPCTSTR szCommand = _T("CommentCode");
            VARIANT_BOOL bRet;
            CString strCmdString;
            strCmdString.LoadString(IDS_CMD_STRING);
            strCmdString = szCommand + strCmdString;
            CComBSTR bszCmdString(strCmdString);
            CComBSTR bszMethod(_T("CommentCode"));
            CComBSTR bszCmdName(szCommand);
            VERIFY_OK(pApplication->AddCommand(bszCmdString, bszMethod, 0, m_dwCookie, &bRet));
            由于上面的代碼涉及到了字符串資源,所以我們?cè)賮砜纯瓷厦嫣岬降腎DS_CMD_STRING的內(nèi)容,打開這個(gè)字符串資源改成下面的形式:
            Comment Code Comment the selected code Comment the selected code

            現(xiàn)在我們可以編譯這個(gè)應(yīng)用程序,應(yīng)該不會(huì)出現(xiàn)錯(cuò)誤,單擊運(yùn)行會(huì)彈出一個(gè)對(duì)話框要你指定一個(gè)宿主應(yīng)用程序來調(diào)用這個(gè)DLL, 因?yàn)槲覀兪菫閂C開發(fā)插件應(yīng)用,所以找到你VC的可執(zhí)行文件目錄并選中msdev.exe。當(dāng)另一個(gè)VC啟動(dòng)后,選擇Tools&brvbar;Customize...,叢屬性頁種選擇Add-ins and Macro Files標(biāo)簽,單擊Browse按鈕,選擇你剛生成的DLL文件,這時(shí)旁邊的列表框,會(huì)出現(xiàn)你編寫的插件的名字,單擊Close關(guān)閉對(duì)話框,這是在工具條的下面會(huì)出現(xiàn)一個(gè)小工具條,將鼠標(biāo)移動(dòng)工具條的按鈕上面,會(huì)出現(xiàn)Comment the selected code的代碼提示, 單擊按鈕會(huì)彈出一個(gè)對(duì)話框,這是AppWidzard對(duì)這個(gè)命令的缺省實(shí)現(xiàn)。

            下面我們?cè)搶?shí)現(xiàn)我們的具體功能的代碼了。由于VC把它集成環(huán)境中對(duì)象通過COM接口暴露出來,所以我們就利用這些對(duì)象來實(shí)現(xiàn)注釋代碼的功能。這里有兩個(gè)問題:1、我們?cè)趺茨苤繴C中當(dāng)前打開的文檔是否是源代碼而不是圖形或?qū)υ捒颍?、我們?cè)趺床拍苤喇?dāng)前源代碼文檔中的被選擇的文本。下面我通過實(shí)際的代碼來解釋這兩個(gè)問題。

            1、查找當(dāng)前打開的源代碼編輯其中的文檔并查找當(dāng)前選中的文本。這里我寫了一個(gè)函數(shù)因?yàn)樵趯?shí)現(xiàn)反注釋的時(shí)候我們還需要完成相同的功能。請(qǐng)參閱代碼中的注釋(注意相應(yīng)接口指針的釋放):
            HRESULT CCommands::GetTextSelection(IApplication *pApplication, ITextSelection** pTextSelection)
            {
            IDispatch* pDispatch;
            //通過有集成環(huán)境傳進(jìn)來的應(yīng)用程序?qū)ο蟛檎耶?dāng)前處于活動(dòng)狀態(tài)的文檔對(duì)象,注意返回的是一個(gè)IDispatch接口指針。
            HRESULT hr = pApplication->get_ActiveDocument(&pDispatch);
            //此處應(yīng)注意即使get_ActiveDocument()函數(shù)成功返回pDispatch指針仍有可能為空(即VC中沒有文檔打開),所以此處要判 //斷pDispatch是否為空
            if (SUCCEEDED(hr) && pDispatch != NULL)
            {
            //取得IGenericDocument接口的指針,我們可以通過該接口指針來查詢當(dāng)前的活動(dòng)文檔是否是文本文檔。
            IGenericDocument* pDocument;
            hr = pDispatch->QueryInterface(IID_IGenericDocument, (void**)&pDocument);
            if (FAILED(hr))
            {
            pDispatch->Release();
            return E_NOINTERFACE;
            }
            pDispatch->Release();

            //在此處查詢ITextDocument接口,如果能成功返回,就說明當(dāng)前文檔是文本文檔。
            ITextDocument* pTextDocument;
            hr = pDocument->QueryInterface(IID_ITextDocument, (void**)&pTextDocument);
            if (FAILED(hr))
            {
            pDocument->Release();
            return E_NOINTERFACE;
            }
            pDocument->Release();

            //現(xiàn)在我們有了當(dāng)前的活動(dòng)的文本文檔,我們就可以通過get_Selection函數(shù)來獲得當(dāng)前選中的文本,這里要求的還是 //一個(gè)IDispatch接口的指針
            hr = pTextDocument->get_Selection(&pDispatch);
            if (FAILED(hr))
            {
            pTextDocument->Release();
            return E_NOINTERFACE;
            }
            pTextDocument->Release();
            //通過QueryInterface()方法取回ITextSelection的接口指針。
            hr = pDispatch->QueryInterface(IID_ITextSelection, (void**)pTextSelection);
            if (FAILED(hr))
            {
            pDispatch->Release();
            return E_NOINTERFACE;
            }
            pDispatch->Release();

            }
            else
            return E_NOINTERFACE;
            return S_OK;
            }

            上面的方法已經(jīng)解決了這兩個(gè)問題,接下來的任務(wù)就是實(shí)現(xiàn)注釋被選中的代碼。請(qǐng)參閱下面的代碼(省略了錯(cuò)誤處理的部分代碼)
            HRESULT CCommands::CommentSelectedCode(ITextSelection *pTextSelection)
            {
            long lTopLine = -1;
            long lBottomLine = -1;
            long lCurLine;
            long lCurColumn;
            //取得被選中文本的最上面一行的行號(hào)
            HRESULT hr = pTextSelection->get_TopLine(&lTopLine);
            //取得被選中文本的最下面一行的行號(hào)
            hr = pTextSelection->get_BottomLine(&lBottomLine);

            long iLine;
            CString s;
            _variant_t v((long)dsMove);
            //循環(huán),針對(duì)選中的每一行,在前面加上VC的單行注釋//
            for(iLine = lTopLine; iLine <= lBottomLine; iLine++)
            {
            hr = pTextSelection->MoveTo(iLine, 1, v);
            if (SUCCEEDED(hr))
            {
            pTextSelection->SelectLine();
            BSTR bstrLineText;
            hr = pTextSelection->get_Text(&bstrLineText);
            if (SUCCEEDED(hr))
            {
            s = bstrLineText;
            s = _T("http://") + s;
            pTextSelection->put_Text(s.AllocSysString());
            }
            }
            }
            return S_OK;
            }

            上面的代碼就完成了對(duì)選中的代碼的注釋問題,下面添加對(duì)選中的代碼的反注釋功能,其中的代碼大體相同,這里主要講解如何間命令添加到VC的開發(fā)環(huán)境中去。
            在ClassView中右鍵單擊ICommands接口,選擇Add method...,添加UncommentCode方法,參照上面的代碼實(shí)現(xiàn)相應(yīng)的功能。
            打開CDSAddIn類的OnConnection方法,在添加CommentCode方法的下面添加下面的代碼:
            szCommand = _T("UncommentCode");
            strCmdString.LoadString(IDS_CMD_UNCOMMENT);
            strCmdString = szCommand + strCmdString;
            bszCmdString = strCmdString;
            bszMethod = _T("UncommentCode");
            CComBSTR bszCmdUncommentName = szCommand;
            VERIFY_OK(pApplication->AddCommand(bszCmdString, bszMethod, 1, m_dwCookie, &bRet));

            然后在OnConnection()方法的下面的代碼中
            if (bFirstTime == VARIANT_TRUE)
            {
            VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));
            }
            添加一行,如下面的代碼
            if (bFirstTime == VARIANT_TRUE)
            {
            VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));
            VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszCmdUncommentName, m_dwCookie));
            }
            在上面的pApplication->AddCommand()調(diào)用中,第三個(gè)參數(shù)1,指定了該命令所對(duì)應(yīng)的圖像在位圖資源中的位置。

            適當(dāng)?shù)男拚こ痰馁Y源,完成的應(yīng)用程序應(yīng)該可以完成VB,PowerBuilder中的代碼的注釋和反注釋功能。

            另外,由于VC中的插件是通過COM技術(shù)實(shí)現(xiàn)的,所以能支持COM規(guī)范的語言都可以用來編寫VC插件。

            本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/panbinfeng/archive/2006/04/17/666816.aspx

            久久国产精品久久久| 国产偷久久久精品专区| 久久夜色tv网站| 国产精品美女久久久久av爽| 国产香蕉97碰碰久久人人| 亚洲а∨天堂久久精品| 午夜天堂精品久久久久| 精品久久久久久无码中文野结衣 | 2021国内久久精品| 久久精品国产亚洲AV香蕉| 精品久久人人做人人爽综合| 久久青青草原亚洲av无码app| 国产精品亚洲美女久久久| 久久精品国产AV一区二区三区| 久久91亚洲人成电影网站| 综合网日日天干夜夜久久| 93精91精品国产综合久久香蕉 | 久久精品免费一区二区| 91精品婷婷国产综合久久| 亚洲精品无码久久久久去q| 久久国产成人| 国产亚州精品女人久久久久久| 婷婷久久香蕉五月综合加勒比| 香蕉99久久国产综合精品宅男自| 青青草国产精品久久| 久久婷婷五月综合97色一本一本 | 国产精品99久久久精品无码| 国产亚洲精午夜久久久久久| 国产精品福利一区二区久久| 囯产精品久久久久久久久蜜桃| 伊人热热久久原色播放www | 精品久久久久久国产三级| 夜夜亚洲天天久久| 91久久福利国产成人精品| 国产91久久精品一区二区| 精品免费久久久久久久| 久久人人妻人人爽人人爽| 久久婷婷激情综合色综合俺也去| 亚洲狠狠婷婷综合久久蜜芽 | 久久久久亚洲?V成人无码| 久久无码一区二区三区少妇|