현재 진행중인 프로젝트가 어느 정도 끝이 보이는 시점에서 다국어 버전을 만들어 보기로 했습니다.(국내 회사에서 사용하는 것이므로 필요하지는 않겠지만...)
그러나 현실에서는 그렇게 쉽게 되지 않습니다.
2번 항목에서 InitLanguage()함수를 InitInstance()에서 가장 먼저 호출하였습니다.
- InitLanguage() 함수는 리소스 DLL을 로딩하고 리소스 핸들을 설정하는 함수
그랬더니 프로그램이 에러가 발생하고 종료되었습니다.
원인을 살펴보니 Grid Control을 폼의 초기화 부분(OnInitialUpdate)에서 Create 함수를 통해 생성하고 있었는데 생성하는데 실패되었습니다.
참고로 Grid Control은 유명한 MFC Grid Control이며 다른 DLL(컨트롤에 관련된 DLL을 만들어 사용하고 있었음)에 포함되어 있었습니다.
이 문제는 해결하지 못하고 돌아가기로 했습니다.
리소스 핸들을 설정할 곳을 3개로 구분하여 하기로 했습니다.
InitLanguage 함수에서 리소스 DLL만 로딩하고 리소스 핸들을 설정하는 부분을 삭제했습니다.
그리고 폼의 Create 함수에서 Form::Create 함수 앞서 리소스 핸들을 설정하는 부분을 추가하고 Form::Create이 끝나고 나서 기존의 리소스 핸들로 되돌리는 부분을 추가하였습니다.
그랬더니 앞에서 문제가 되던 부분이 해결이 되었습니다.
이런 방식으로 (리소스 핸들을 설정하고 되돌리는 방식) 대화 상자를 나타나는 루틴에 위의 코드를 삽입하여 대화 상자에 대한 것도 처리하였습니다.
3번째 해결 방식으로 모든 메세지 박스가 나타나는 곳 마다 앞서 하던 방식대로 할수는 없습니다. 너무 많은 곳에 분포가 되어 있으니까요.
그리서 InitInstance() 부분의 마지막 쯤에 리소스 핸들 설정하는 부분을 넣어주면 이 이후로 리소스를 사용하는 부분은 리소스 DLL의 것을 사용하게 됩니다.
- 먼저 주 프로젝트에서 resource.h , rc 파일 , 그리고 관련된 리소스 파일들을 이용해서 DLL을 만듭니다.
- InitInstance 함수에서 리소스 DLL을 로딩합니다.
- ExistInstance 함수에서 리소스 DLL을 해제시킵니다.
-
로딩한 DLL로 리소스 핸들을 설정합니다.
그러나 현실에서는 그렇게 쉽게 되지 않습니다.
2번 항목에서 InitLanguage()함수를 InitInstance()에서 가장 먼저 호출하였습니다.
- InitLanguage() 함수는 리소스 DLL을 로딩하고 리소스 핸들을 설정하는 함수
BOOL CAdminApp::InitLanguage()
{
//Set the new language
m_hMultiLangRes = LoadLibrary("Lang\\AdminKorLang.dll");
if (m_hMultiLangRes) AfxSetResourceHandle(m_hMultiLangRes);
return TRUE;
}
BOOL CAdminMain::InitInstance()
{
InitLanguage();
AfxEnableControlContainer();
FileZilla의 소스를 보고 이렇게 했습니다.그랬더니 프로그램이 에러가 발생하고 종료되었습니다.
원인을 살펴보니 Grid Control을 폼의 초기화 부분(OnInitialUpdate)에서 Create 함수를 통해 생성하고 있었는데 생성하는데 실패되었습니다.
참고로 Grid Control은 유명한 MFC Grid Control이며 다른 DLL(컨트롤에 관련된 DLL을 만들어 사용하고 있었음)에 포함되어 있었습니다.
이 문제는 해결하지 못하고 돌아가기로 했습니다.
리소스 핸들을 설정할 곳을 3개로 구분하여 하기로 했습니다.
- 프로그램에서 거의 모든 폼들은 프로그램이 초기화 될때 생성됩니다.
- 대화 상자들은 사용자 반응에 따라 나타나게 되고
- 메세지 박스의 메세지.
InitLanguage 함수에서 리소스 DLL만 로딩하고 리소스 핸들을 설정하는 부분을 삭제했습니다.
BOOL CAdminApp::InitLanguage()
{
//Set the new language
m_hMultiLangRes = LoadLibrary("Lang\\AdminKorLang.dll");
if (m_hMultiLangRes) AfxSetResourceHandle(m_hMultiLangRes);
return TRUE;
}
그리고 폼의 Create 함수에서 Form::Create 함수 앞서 리소스 핸들을 설정하는 부분을 추가하고 Form::Create이 끝나고 나서 기존의 리소스 핸들로 되돌리는 부분을 추가하였습니다.
#ifndef __RESOURCE_SWITCH_H__
#define __RESOURCE_SWITCH_H__
class CResourceSwitch
{
CResourceSwitch& operator=(const CResourceSwitch&){ return (*this); }
CResourceSwitch(const CResourceSwitch&){}
public:
CResourceSwitch(HINSTANCE hRes)
{
m_hOldRes = AfxGetResourceHandle();
if(NULL != hRes) AfxSetResourceHandle(hRes);
}
~CResourceSwitch()
{
AfxSetResourceHandle(m_hOldRes);
}
private:
HINSTANCE m_hOldRes;
};
#endif
BOOL CProjectSettingForm::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
CAdminApp* pApp = (CAdminApp*)AfxGetApp();
CResourceSwitch resSwitch(pApp->m_hMultiLangRes);
return CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}
그랬더니 앞에서 문제가 되던 부분이 해결이 되었습니다.
이런 방식으로 (리소스 핸들을 설정하고 되돌리는 방식) 대화 상자를 나타나는 루틴에 위의 코드를 삽입하여 대화 상자에 대한 것도 처리하였습니다.
3번째 해결 방식으로 모든 메세지 박스가 나타나는 곳 마다 앞서 하던 방식대로 할수는 없습니다. 너무 많은 곳에 분포가 되어 있으니까요.
그리서 InitInstance() 부분의 마지막 쯤에 리소스 핸들 설정하는 부분을 넣어주면 이 이후로 리소스를 사용하는 부분은 리소스 DLL의 것을 사용하게 됩니다.
if (m_hMultiLangRes) AfxSetResourceHandle(m_hMultiLangRes);
// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_MAXIMIZE);
m_pMainWnd->UpdateWindow();
return TRUE;
댓글
댓글 쓰기