資原始檔實現多語言介面
這裡介紹的方法是使用不同語言的資原始檔達成多語言的效果。
多語言DLL
第一步:建立一個MFC的DLL
第二步:設定工程屬性為Resource DLL,如果在 .Net 2003中這一步非常簡單:
Project Property->Linker->Advanced->ResourceOnly DLL
如果是主工程為Unicode那麼將工程設定為Unicode,
第三步:刪除工程的resource.h及SC.rc,加入主工程的 resource.h 和 *.rc,同時需要把主工程中res目錄copy到目前的工程,覆蓋掉目前工程的。編譯生成DLL,copy到主工程指定的目錄,例如:.\lang etc…。
第四步:在主工程中使用DLL中的資源,程式碼如下:
//Source Code-> Add in BOOL CXXXApp::InitInstance()
//---------------------------------------------------------
strDllPath= strPath + _T("\\lang\\SC.dll");
//load DLL
m_hLangDLL= ::AfxLoadLibrary(strDllPath);
if (!m_hLangDLL) {
//Fail toload DLL
}
//Set theresource handle
AfxSetResourceHandle(m_hLangDLL);
//---------------------------------------------------------
基本上就可以了,這個時候執行程式,使用的資源就應該是DLL中的了。
第五步:進行多語言的對應,基本上就是在SC的工程中直接更改資源。如果主工程使用U.S.語言建立,直接在UI上進行中文的更改是行不通的,會出現亂碼,因為.rc檔案認為描述的是英文資訊,可以直接使用編輯軟體開啟相應的.rc檔案,會看到:可以建立一箇中文的工程進行一下對比,將其替換成中文版本中的內容即可,如下:
我想這個引數也可以在工程中進行設計,但是目前我還沒有發現相關方法。
之後把相應資源的屬性改為相應的語言,例如:中文。
把資源上面的內容更改為中文,編譯,把生成的DLL放到相應的目錄下,執行軟體,應該成功了。
如果要進行其他語言的設定,例如:日文、繁體中文等,除了以上的設定外,還需要把當前Windows的系統語言進行更改,這樣才可以直接在MFC的環境中編輯資源,否則亂碼,如下:發現的問題:
1、建立過程都正確,而且大部分對話方塊都可以正常的使用,但是發現有幾個對話方塊不能正常地建立,基本上都是在CreateDlgIndirect(…) 函式中失敗,沒有成功的建立窗體,hWnd為NULL,後來經過調查這個問題由於有些自定義的控制元件的註冊時機過晚引起,例如RegisterIconButtonClass(AfxGetResourceHandle()); 用來這冊一個自定義的控制元件,如果放在Document模版建立之後就會有問題,將其提前問題解決,下面是Document建立,因為在建立過程中有些地方已經開始使用這個控制元件了。而且在由於之前我們已經將資源改為使用DLL了,所以這裡需要使用 AfxGetResourceHandle() 獲取當前的資源控制代碼。
//------------------------------------------------------
m_pDocTemplate= new CMultiDocTemplate(IDR_MAINFRAME,
RUNTIME_CLASS(CXXXDoc),
RUNTIME_CLASS(CChildFrame), // customMDI child frame
RUNTIME_CLASS(CXXXView));
//-------------------------------------------------------
2、解決了這個問題還有一些對話方塊有問題,這些對話方塊都使用了CGridCtrl控制元件,是以DLL形式使用的。由於問題1,所以自然就想到了控制元件的註冊問題,CGridCtrl是在建構函式中進行註冊的,應該不存在註冊的先後問題。後來經過試驗是由於 AfxRegisterClass()註冊過程中 wndcls.hInstance= AfxGetInstanceHandle(); 控制代碼獲取的問題,在這個專案中CGridCtrl有兩種使用方式:一種作為Custom控制元件,直接放到對話方塊中,然後定義一個關聯變數進行使用;另外一種是在執行時使用Create(…) 進行建立。使用方式不同需要使用的控制代碼也不相同,如果採用第一種方式,需要使用AfxGetResourceHandle(); 如果採用第二種方式需要使用AfxGetInstanceHandle(); ,所以針對於CGridCtrl在工程中應該只採納一種使用方式。
如果使用第一種方式可以使用static控制元件在對話方塊上定位。