VS2008中自定義C++工程模板與修改新建文件默認編碼的辦法
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
一、 需求
網上講VS(以下VS均特指VS2008)自定義模板的不少,不過大部分都是講C#或者Web開發的,什麼export template的,都不適合C++工程,由於MS的確是減弱了對C++的支持,(這點沒有人否認吧?)所以在VS中C++總是被遺忘在那個沒有人理睬的角落,所以現在很多人寧願還用着C++與MFC最輝煌的版本VC6.0,哪怕那個版本的C++這麼不符合標準。。。。。既然MS不關心C++使用者,那就只有自己奮發圖強羅,還好再怎麼樣,沒有了VS,我們總還是有VIM+G+++GDB/Emacs的,沒有了MFC我們還有Qt,GTK+的,何況個人用Eclipse在Linux下做Qt程序的感覺也不錯,閒話不說了,看看正題。
自定義工程模板是用途很大的,當你有一個簡單的模板用於開發的時候,沒有VS內部的支持時,你有兩種辦法,其一你將原有整個工程拷貝一份,然後改工程名(在我以前的公司就是這樣乾的),改名不說,要進VSS,還得改工程的GUID(不懂的就算了),其二是新建一個工程,然後一個一個添加文件,假如有自己的目錄結構的時候,還得重新控制目錄結構,工程大時也是異常麻煩,其實這些用上了VS自定義模板,一切都可以很簡單,就像你進行Win32 SDK,MFC開發MS給你的模板一樣。
修改VS中新建文件的默認編碼嘛,純Windows人士請忽略,我是因爲需要在Linux下編輯和查看這些文件纔有此需求。事實上,即使想要在Linux下查看或者編輯這些代碼也可以不做改變,但是我就是想將其全部改成UTF8,不喜歡將Linux下設置一大堆東西,gcc需要加gb2312的選項,vim需要加配置,Eclipse也需要改配置,其他文本編輯工具也需要選定編碼,全部是因爲VS在中文Windows下的默認編碼是gb2312(我用的是英文VS2008,這個可能是跟着操作系統環境走的),雖然也不怪MS。。。。既然VS也支持UTF8,就讓Windows遷就Linux了。。。。還需要遷就的是Linux下的換行與Windows不同,順面一起解決了,雖然大部分時候,在公司,都是用Linux的東西來遷就Windows。修改默認編碼的辦法我在網上找了很久也沒有找到,大部分人都說是直接用Advanced Save Option來選擇保存,那樣多麻煩啊,或者先建立工程以後用find批量改,那樣也不見的簡單啊。。。。。。。。看下面的解決辦法。
二、 解決辦法
1. 新建文件
奧祕在Microsoft Visual Studio 9.0/VC/vcprojectitems中(Microsoft Visual Studio 9.0根據你安裝目錄而定)
新建的C++文件,主要是newc++file.cpp這個文件,目前是空的,你將其改成什麼樣,那就是什麼樣,比如,我需要在每個文件的頭部添加一大串的GPL說明,(不是我想,這是FSF規定的),那麼就直接在此文件添加我的文件頭即可,以後用add->add new item->C++ files時,就都會自動帶着文件頭出來了。。。更好用的是,我現在將此文件轉爲UTF8+Unix換行格式,那麼以後新建的文件都是如此了。。。呵呵,此謂之一勞永逸。
新建的頭文件是hfile.h這個文件,如上更改,一勞永逸。事實上,我將上面的文件複製一份,重命名爲hfile.h^^
普通文本文件由於常做Readme用,也改了。是text.txt這個文件。
2. 授人以魚不如授人以漁
我當然不是一個一個文件試出來的,也不是猜出來的,授人以魚不如授人以漁,這裏告訴大家怎麼去自己摸索。上述三個文件有個共同特點,那就是可以通過右鍵add->new item,那麼我首先查看的就是new item了,這裏,我的Visual C++下的下面有UI,Code,Data,Resource,Web,Utility,Property Sheets7個選項,與Microsoft Visual Studio 9.0/VC/vcprojectitems下面的7個目錄及目錄名一一對應,很明顯了,這些選項由此7個目錄中的內容控制的,首先看Code目錄,一個code.vsdir的文件,打開一看
../NewC++File.cpp|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#1075|10|#1076|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|9031|4096|#1077
../HFile.h|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#1078|15|#1079|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|9030|4096|#1080
../IDLFile.idl|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#1084|20|#1085|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|9035|4096|#1086
../DEFFile.vsz|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#1087|35|#1088|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|9036|4096|#1089
../addmc++componentclass.vsz|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#1236|85|#1237|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|9563|4096|#1238
../installer.vsz|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|#1245|85|#1246|{1B027A40-8F43-11D0-8D11-00A0C91BC942}|9564|4096|#1247
咋一看,亂碼?2進制文件?的確像,再仔細看看,前面的一部分,那不就是菜單中有的Items項?一一對應的。再仔細看,發現其實前面的字符串都是一個目錄,指向父目錄下的各個文件,其中前面兩個就是.. /NewC++File.cpp,.. /HFile.h兩個文件,那就是上一節中我發現的兩個文件,對應新添加的C++文件和頭文件。vsdir後面的東西是更詳細的說明,長串的{}是GUID,#xxx是通過ID來表示資源。但是這裏我們不去詳細瞭解了,想要詳細瞭解的參看MSDN這裏,同理,文本文件在Utility目錄下的VCUtilityItems.vsdir制定的,我就不多說了。
3. 自定義工程模板
新建工程中有個Custom Wizard選項,我將其命名爲Win32OpenGLWizard。建立以後是一個完整的Wizard工程,天哪,一看,真複雜,我僅僅想建立一個簡單的C++工程嘛,至於這樣複雜嗎?很顯然,MS設計VS的自定義模板的時候就是給其他軟件開發商用的,根本沒有考慮過個人使用-_-!因爲其中包含了HTML,CSS,JS….並不是每個人都是做網頁的**。。。。作爲用C++的我們,就知道想辦法摸索摸索羅,符合我們的要求就好。要將引導框設計的多麼完美我個人是沒有什麼希望了。所以建立Win32OpenGLWizard工程時,用戶的UI選擇就不需要了吧,直接通過名字就好。
首先利用剛纔新建的Wizard去建立一個工程,(會出現在New Project的Wizard下,實際的文件放在 我的文檔/Visual Studio 2008/Wizards中)發現我們主要關注的是Template Files下的兩個文件,那就是生成後工程會包含的文件。嘗試一下。
在template Files下添加main.cpp,修改Readme.txt,刪除sample.txt,實際操作時請將文件添加到/Templates/1033目錄下面去,並且手動修改Templates.inf添加進main.cpp。新建工程後果然可行。
4. 修改自定義工程模板
有個問題是Readme.txt在Source File目錄下,而main.cpp跑到Source Files外面去了。作爲半個完美主義者,雖然工程已經能編譯通過,但是還是有點不爽,我希望進一步改進,那麼下一步看看Source Files是哪裏規定的羅,在default.js中可以看到
function AddFilters(proj)
{
try
{
// Add the folders to your project
var strSrcFilter = wizard.FindSymbol('SOURCE_FILTER');
var group = proj.Object.AddFilter('Source Files');
group.Filter = strSrcFilter;
}
catch(e)
{
throw e;
}
}
此函數,已經明白一半了,此函數不就是尋找匹配的過濾文字,然後將其加入Source Files中去嘛。^^就看SOURCE_FILTER是什麼symbo了
這裏分兩種情況:
無wizard UI
假如沒有添加Wizards UI可以在添加的wizard工程下看到一個vsz文件,我這裏如下:
VSWIZARD 7.0
Wizard=VsWizard.VsWizardEngine.9.0
Param="WIZARD_NAME = Win32OpenGL"
Param="ABSOLUTE_PATH = D:/MyDocument/Visual Studio 2008/WizardTemplate/Win32OpenGL/Win32OpenGL"
Param="FALLBACK_LCID = 1033"
Param="WIZARD_UI = FALSE"
Param="SOURCE_FILTER = txt"
這就是一個簡單的類INI文件,詳細信息可以參考MSDN這裏。我們關心的自然是SOURCE_FILTER參數,改成cpp,竟然沒有效果,不知道其他人怎麼樣,我這裏沒有效果的原因不明。但是雖然不知道此js 的wizard.FindSymbol的實現方法,但是我們還是可以用暴力解決!呵呵,將上述js函數改成如下形式:
function AddFilters(proj)
{
try
{
// Add the folders to your project
//var strSrcFilter = wizard.FindSymbol('SOURCE_FILTER');
var strSrcFilter = 'cpp';
var group = proj.Object.AddFilter('Source Files');
group.Filter = strSrcFilter;
}
catch(e)
{
throw e;
}
}
就好了。我得意的笑啊,我得意的笑^^對於MS奇怪的失靈,有的時候暴力也是必須的。
有wizard UI
假如添加了UI,MS就要考慮你在wizard UI中改變此Symbo的可能了,會在HTML/1033/default.htm這個UI管理文件下看到
<SYMBOL NAME='SOURCE_FILTER' TYPE=text VALUE='txt'></SYMBOL>
改之
<SYMBOL NAME='SOURCE_FILTER' TYPE=cpp VALUE='cpp'></SYMBOL>
有效。
再次創建工程,cpp文件已經在Source Files中了,ReadMe.txt也死出去了,以後再需要頭文件什麼的也一樣處理就好了。
5. 接近完美
好了嗎?已經很好了,但是作爲3/4個完美主義者,我還有有點想改的地方,那就是我平時建工程,很簡單的工程主文件與工程名一直,這樣萬一哪天想全部拷貝到一起管理也方便,但是按上述方式文件將全部是main.cpp,解決之,電腦上沒有咋程序員解決不了的事情。
看上述js腳本,如下函數:
function GetTargetName(strName, strProjectName)
{
try
{
// TODO: set the name of the rendered file based on the template filename
var strTarget = strName;
if (strName == 'readme.txt')
strTarget = 'ReadMe.txt';
if (strName == 'sample.txt')
strTarget = 'Sample.txt';
return strTarget;
}
catch(e)
{
throw e;
}
}
再看看它的使用,就知道此處就是我們需要修改的地方,實際上MS已經考慮了這樣的情況了,我們不需要暴力^^改成如下內容:
function GetTargetName(strName, strProjectName)
{
try
{
// TODO: set the name of the rendered file based on the template filename
var strTarget = strName;
if (strName == 'readme.txt')
strTarget = 'ReadMe.txt';
if (strName == 'main.cpp')
strTarget = strProjectName + ".cpp";
return strTarget;
}
catch(e)
{
throw e;
}
}
測試,OK!
三、 後記
所有的說明,版權信息都在,文件內容,編碼,換行符都搞定了,文件名也符合我的要求了,接近完美,鑑定完畢!
此過程發狂的得不到MSDN滿篇.Net的幫助,又難領悟廣大C#網民的旁敲側擊,獨自在VS的漆黑中摸索,逢JS大山則開路,逢HTML大石則劈之,屢次撞壁,失敗數回,嘆MS之棄cpper至此,捶胸頓足,奮發自強,吐血三升,乃作此文,以茲紀念。