1. 程式人生 > >[MFC]文件字串、HKEY_CLASSES_ROOT登錄檔、.reg登錄檔檔案

[MFC]文件字串、HKEY_CLASSES_ROOT登錄檔、.reg登錄檔檔案

1. 文件字串的定義:

    1) 也是LoadFrame可以載入的第四種資源(圖示、選單、加速鍵之外的第四種資源);

    2) 定義方式例如:

STRINGTABLE PRELOAD DISCARDABLE 
BEGIN
    IDR_MAINFRAME           "SdiSquares\n\nSdiSqu\nSdiSqu Files (*.sqr)\n.sqr\nSdiSquares.Document\nSdiSqu Document"
END
         i. 定義使用關鍵字STRINGTABLE;

         ii. 裡面的那條字串都要用一條資源ID來標識,就像選單的選單項一樣,每一項都要用一個ID來標識;

    3) 其中的字串是由換行符\n相互隔開的7個子字串構成,如果哪一個字串為空也必須用兩個\n(中間什麼字元都沒有)包夾在一起,標識中間的字串為空;

    4) 7個字串的含義(從頭到尾):

*1. 框架視窗標題欄中的標題,一般用來指示應用程式名,例如:Microsoft Word,中間可以帶空格

*2. 分配給未命名的新建立文件的名字,如果該字串為空將預設為"Untitled"

!!在建立或開啟一個文件後程序標題欄會顯示"文件名-程式名",程式名就是第一個子字串,文件名可以是已存在的文件的名稱也可以是預設的Untitled(即第2個子字串);

*3. MDI文件型別過濾器,在SDI中用不到,可以為空;

*4. SDI文件型別過濾器,會在CFileDialog的文件過濾器列表中顯示,例如:Doc Files(*.doc);

!!!5和6會在登錄檔中註冊時起到作用,後面會具體講解登錄檔的相關內容;

*5. 文件的預設副檔名(在使用者沒輸入字尾的情況下自動新增),例如:.txt就是合法的,注意,一定要加.

*6. 登錄檔文件型別:也成為登錄檔ID;

!!!

*7. 文件型別描述:文件的屬性選項卡中會顯示出來的供人閱讀的名字,可以比較長,可以包含空格,主要作用是簡短地解釋文件的型別,在登錄檔中是登錄檔ID對應的描述性字串;

2. 使用GetDocString來獲取文件字串的各個子字串:

    1) 函式原型:vritual BOOL CDocTemplate::GetDocString(CString& rString, enum DocStringIndex index) const;

    2) rString用於接受想獲得的字串;

    3) index使用列舉型別定義的索引值,它們都已CDocTemplate::作為字首,這裡按照子字串的排列順序給出:

windowTitle:標題

docName:預設的文件名

fileNewName:MDI文件型別過濾器

filterName:SDI文件型別過濾器

filterExt:預設副檔名

regFileTypeID:文件在登錄檔中的名稱,即登錄檔ID

regFileTypeName:最後一個子字串,即登錄檔ID對應的描述性字串

    4) 示例:pDocTemplate->GetDocString(strBuffer, CDocTemplate::filterExt); // strBuffer中將儲存預設文件副檔名;

3. HKEY_CLASSES_ROOT——熱鍵關聯登錄檔(設定檔案的預設圖示和開啟程式):

    1) Windows的登錄檔可以使用regedit.exe開啟並進行編輯;

    2) 在regedit編輯器的最左側可以看到系統中所有的熱鍵目錄表;

    3) 熱鍵HKEY的概念:

         i. 即Hot Key,就是一些快捷操作;

         ii. 最典型的快捷操作介紹:比如在Linux系統中,你要開啟一個文件,必須在命令列上鍵入開啟文件的程式以及目標文件的名稱,回車之後才能開啟,但是Windows中就只要雙擊文件圖示就能用預設的程式來開啟它,非常方便;

!!但不過這些方便都是需要在登錄檔中新增相關資訊後才能達到這樣的效果,否則就還是跟Linux一樣,手動在命令列上鍵入程式和文件回車後才行;

    4) ROOT表示這是某種型別的HKEY的根目錄,該種類型的所有HKEY都存放在這個目錄下;

    5) HEKY_CLASSES_ROOT表示跟檔案型別相關的熱鍵根目錄,比如其中最主要的就是文件型別,裡面儲存著關於各種文件型別的熱鍵,比如.txt文件的預設開啟程式、.doc文件的預設文件圖示等;

    6) Windows使用鍵值的方式來管理熱鍵登錄檔,所有的快捷操作都需要通過定義鍵值並且把鍵值新增(註冊)到登錄檔之後才能生效;

    7) Windows用類似目錄的形式來實現鍵值管理,一個鍵可以有自己的子鍵,那麼就可以說母鍵是子鍵的上級目錄,子鍵是母鍵的子目錄,但這是一種說法,實際上在底層並不是使用目錄來實現的,只不過這樣認為可以讓問題更簡單,而實際上在regedit中也是用目錄的形式來展示母鍵與子鍵的關係的;

!在regedit左側的目錄表中可以看到所有的鍵的圖示都是資料夾,資料夾開啟還有別的資料夾(子鍵),整個登錄檔以樹形目錄的形式來展示;

!沒用滑鼠選中一個鍵(一個資料夾圖示)就會在右側的檢視中看到改建的值(數值名稱-型別-資料),其中資料就是鍵的值;

    8) 特殊鍵:

         i. 是指一些名稱特殊的鍵,如果將一個鍵命名為這些特殊的名稱,Windows會用特定的方式對待和解釋它們;

         ii. 首先是字尾鍵,就是以'.'開頭的鍵,Windows會將這樣的鍵當做檔案的字尾名,當用戶雙擊這種字尾名的檔案時Windows就會根據該鍵的值做一些相應的處理;

         iii. defaulticon:該鍵將定義預設圖示,比如在.txt鍵下建立子鍵defaulticon,然後給defaulticon的值設為一個圖示的絕對路徑,那麼所有以.txt為字尾的文件都會以該圖示作為自己的預設圖示;

         iv. shell:該鍵將定義和命令直譯器(類似於後臺執行的cmd.exe,你在圖形介面上雙擊開啟一個應用程式實際上實在後臺的命令直譯器中輸入了該程式的名稱並回車才打開的)相關的東西;

         v. shell鍵下可以定義子鍵open:用來定義如何用命令直譯器開啟一個文件或程式;

         vi. open子鍵下還可以定義子鍵command:表示用一條命令來開啟一個文件或程式,command鍵的值就是指定應用程式的絕對路徑

!!所以shell\open\command鍵就是指使用預設的外殼命令來開啟某種型別的檔案,那麼.txt\shell\open\command鍵就是指用指定的外殼命令來開啟.txt檔案了;

         vii. command鍵的值:格式是"程式的絕對路徑 %數字",數字可以是0/1/2,其中0表示不啟用,1表示啟用,2表示二進位制(該含義我到現在也不明白,但反正也用不上),啟用就表示啟用預設開啟程式的功能,因此數字一定是1!!

    9) 文件型別ID:

         i. 通常並不會直接在後綴鍵下直接定義defualticon、shell\open\command等鍵,原因很簡單,那就是有可能幾個不同字尾的檔案用同一個程式開啟,如果這些子鍵都定義在後綴鍵下的話,那麼每一個字尾鍵都要重複定義一遍這些子鍵,這不僅非常不方便,而且如果哪一天預設開啟的程式發生改動(名稱發生變化、路徑發生變化),那麼就得到每一個字尾鍵的子鍵中進行修改,工作量非常大;

         ii. 標準的做法——鍵的關聯:Windows允許將一個鍵關聯到另一個鍵,即用一個鍵的名稱來作為另一個鍵的值,那麼在對解析一個鍵的時候就會找到它的值所對應的鍵並解析這個關聯的鍵,例如.doc、.docx的值都為Word.Document,然後在Word.Docment鍵中定義defualticon、shell\open\command等鍵,那麼就能實現.doc和.docx都用Word開啟的目的了;

         iii. 上面的Word.Document就是字尾鍵的值,字尾鍵的值的學名就是文件型別ID,也就是說專業標準的做法就是為每種字尾鍵定義相應的文件型別ID,然後再在文件型別ID中定義相關的熱鍵操作,以後文件型別ID就簡稱為文件型別了;

         iv. 文件型別的命名規則:沒有嚴格的命名規則,可以任意取名,但不過有約定俗稱的規範,規範就是"預設開啟程式名.檔案型別名",比如Word.Document,就是用Word開啟的文件,Vim.Initfile就是用Vim開啟的初始化檔案等,這樣見名知意,習慣非常良好,為未來的登錄檔管理帶來很大的方便;

    10) 和文件字串的關係:

         i. 第5個子字串filterExt將作為字尾鍵;

         ii. 第6個字串regFileTypeID將作為檔案型別ID鍵;

         iii. 最後一個字串regFileTypeName將作為檔案型別ID鍵的鍵值,用來解釋該檔案型別是什麼東西;

4. .reg登錄檔檔案:

    1) 如果要在登錄檔中新增新的鍵值則可以直接在regedit裡操作,右鍵新增專案等,但最方便的也最適合應用程式管理的方法是直接編寫.reg登錄檔檔案;

    2) 可以直接在.reg檔案中定義要新增的鍵值資訊,儲存後直接雙擊.reg檔案就可以將檔案中的鍵值資訊合併到Windows登錄檔中了;

!!注意:如果.reg中定義的鍵和登錄檔中已有的鍵重複則會覆蓋合併,因此在每次雙擊.reg檔案進行合併時Windows都會彈出訊息框警告可能會產生的覆蓋,待使用者十分確定之後再決定是否合併;

    3) .reg檔案的書寫格式:

         i. 第一行必須是關鍵字REGEDIT,表示這是一個登錄檔檔案,需要用regedit.exe來執行合併

         ii. 註釋使用分號;

         iii. 正文部分就是"鍵 = 值",例如一個典型的登錄檔檔案:

REGEDIT
; This .REG file may be used by your SETUP program.
;   If a SETUP program is not available, the entries below will be
;   registered in your InitInstance automatically with a call to
;   CWinApp::RegisterShellFileTypes and COleObjectFactory::UpdateRegistryAll.

HKEY_CLASSES_ROOT\.sqr = SdiSquares.Document
HKEY_CLASSES_ROOT\SdiSquares.Document\shell\open\command = I:\samp\Visual Studio 6.0\MFC\Code\Chap09\SdiSquares\Release\SdiSquares.exe %1
HKEY_CLASSES_ROOT\SdiSquares.Document\shell\open\ddeexec = [open("%1")]
HKEY_CLASSES_ROOT\SdiSquares.Document\shell\open\ddeexec\application = SDISQUARES
    ; note: the application is optional
    ;  (it defaults to the app name in "command")

HKEY_CLASSES_ROOT\SdiSquares.Document = SdiSqu Document
!!.reg檔案一般用於安裝程式,一般會在安裝程式中執行該檔案以完成應用程式的註冊;


5. MFC對登錄檔的支援:

    1) 首先在用Wizzard建立應用程式時就可以預先生成程式的登錄檔檔案;

    2) 在建立MFC[.exe]程式的第4步中開啟Advanced屬性框,可以在裡面設定應用程式的7個文件字串,設定完畢後就會自動生成一個.reg登錄檔檔案;

    3) 如果後面在程式的資源編輯器中修改文件字串,則.reg也會自動被Visual C++修改;

    4) 在InitInstance中自動完成對程式的註冊:

         i. 之前將InitInstance時還漏掉的兩條函式呼叫:

.
.
.
AddDocTemplate(pDocTemplate);

// Enable DDE Execute open
EnableShellOpen();
RegisterShellFileTypes(TRUE);

// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
.
.
.
!!那就是EnableShellOpen和RegisterShellFileTypes函式,它們在AddDocTemplate和ParseCommandLine之間呼叫;

         ii. EnableShellOpen:void CWinApp::EnableShellOpen(); // 開啟雙擊文件用此應用程式開啟的功能

         iii. void CWinApp::RegisterShellFileTypes(BOOL bCompat = FALSE); // 根據文件字串的資訊來為應用程式在登錄檔中註冊,引數必須為TRUE才能註冊!

!!只有在註冊之後才能將雙擊檔案圖示的操作轉換為Shell命令開啟;

6. 支援MDI程式的特殊熱鍵——ddeexec:

    1) 對於MDI程式,在使用Wizzard自動生成.reg檔案,以及用RegisterShellFileTypes時都會多加一個鍵,這就是ddeexec;

    2) ddeexec其實是DDE Execution的縮寫,而DDE就是Do Data Exchange的縮寫;

    3) DDE的作用就是支援在一個程式中同時開啟多個文件;

    4) 在應用程式已經開啟一個文件的情況下再雙擊開啟一個文件時DDE會給已存在的應用程式例項傳送一個Open命令以及待開啟的文件的引數,之後DDE再間接呼叫應用程式的OnOpenDocument來開啟第二個文件並顯示出來,從而避免了在開啟一個應用程式例項來開啟第二個文件,這就達到了一個程式例項開啟多個文件的目的;

    5) 現在再來看一下ddeexec鍵是如何新增的,看一個例子:

HKEY_CLASSES_ROOT\SdiSquares.Document\shell\open\ddeexec = [open("%1")]
HKEY_CLASSES_ROOT\SdiSquares.Document\shell\open\ddeexec\application = SDISQUARES
!這就是上面出現過的例子,ddeexec必然是shell\open的子鍵,因為它是一種開啟命令熱鍵,它的值必須設為[open("%1")],[]表示該值是該鍵的一個函式呼叫,因此這裡的[open]就是鍵ddeexec的一個函式呼叫,即執行ddeexec.open函式,函式的引數都是字串,因此用""括起來,%1就表示命令列的第1號引數,第0號引數是開啟程式本身,第0號引數就待開啟的檔名(絕對路徑);

!!ddeexec的值就代表了利用DDE嚮應用程式發出一條Open命令,並且Open的物件也在引數給出了;

!接著就是ddeexec的子鍵application,該鍵就表示DDE傳送Open命令的物件程式,也就是該文件型別預設的開啟程式了(只不過是用DDE間接開啟的MDI程式而已),這裡的值必須是程式的絕對路徑!!但是不用加“%數字”!