성공적인 프로젝트를 위한 다국어 리소스 준비-2 DarkKaiser, 2007년 7월 17일2023년 9월 6일 출처 : 데브피아 석재헌님의 글http://www.devpia.com/Forum/BoardView.aspx?no=7282&ref=7282&page=2&forumname=vc_lec&stype= 1. 리소스 라이브러리 앞서의 글에서 이야기한 다국어 리소스 대응 방식으로는, 다국어 리소스가 많아지면 관리하기도 어려워지고, 컴파일되어 나온 출력물이 커지는 단점이 있습니다. 이런 경우 각각의 언어에 대응되는 리소스들을 따로 혹은 몇 개를 묶어서 라이브러리화 하면, 유지보수 하기가 한 결 쉬어 집니다. 때때로 코드페이지의 한계로 같이 편집할 수 없는 언어들도 있습니다. 이런 경우도 분리하셔야 합니다. 2. 리소스 라이브러리 만드는 방법 1) dll 형식의 프로젝트를 하나 만듭니다. (MFC dll 이 아니어도 상관없습니다.).2) 원래의 프로젝트에서 resource.h , *.rc, 프로젝트 폴더 안에 있는 RES 폴더를 통째로 복사합니다.3) 필요한 언어 리소스들의 Copy를 아래 그림처럼 추가하고, 필요 없는 언어의 리소스는 모두 제거합니다. (링크시 Resources의 Preprocessor Definitions에 _AFXDLL을 넣어주시기 바랍니다. 쓸데 없는 MFC 리소스가 같이 따라오지 않습니다.) (다이얼로그 템플릿, 버젼 정보, 스트링 테이블을 제외한 이미지 혹은 아이콘 같은 언어 중립적인 요소들은 경우에 따라서는, 위와는 별도로 따로 관리하는 편이 훨씬 편할 수도 있습니다. ) 3. 어떻게 이용하나? 이렇게 해서 생성된 리소스 라이브러리를 이용하는 법은 아주 간단합니다. 리소스 라이브러리를 ?LoadLibary을 통해서 불러온 후, MFC의 경우는 ?AfxSetResourceHandle 함수를 통해서, 리소스 라이브러리의 핸들을 설정해 주면 됩니다. MFC를 이용하는 경우는, ?LoadResource를 통해서 특정 리소스를 가져 오지 않는다면, 이 후로는 리소스 라이브러리에 대한 생각은 반쯤은 잊어버리셔도 상관 없을 것 같습니다. HMODULE hModule = LoadLibrary( _T("resourcedll.dll")); AfxSetResourceHandle( hModule ); API의 경우는 아래와 같이 사용하시면 됩니다. HMODULE hModule = LoadLibrary( _T("resourcedll.dll")); LoadString( hModule , ... ); LoadResource( hModule ,... ); HMENU hMenu = LoadMenu( hModule, ... ); 4. 샘플 소스 샘플 소스는 첫 번째 글에서 사용하였던 소스를 그대로 응용해서, 한글 리소스와 일본어 리소스를 리소스 라이브러리로 만들어서 테스트 해 보았습니다. 이름을 바꾸지 않아서, 똑같은 이름의 리소스가 3개나 있어서 무척 헷갈리기는 하지만, 위와 같이 각각 영어, 한국어, 일본어의 3개의 언어가 준비되었다는 것을 알 수 있습니다. if( strCommandLine.Find(_T("english")) >= 0 ) { SetThreadLocale( MAKELCID( MAKELANGID(LANG_ENGLISH , SUBLANG_ENGLISH_US) , SORT_DEFAULT)); } else if( strCommandLine.Find(_T("japanese")) >= 0 ) { strAppPath += _T("\\resourcejap.dll"); HMODULE hModule = LoadLibrary( strAppPath ); AfxSetResourceHandle( hModule ); SetThreadLocale( MAKELCID( MAKELANGID(LANG_JAPANESE , SUBLANG_DEFAULT) , SORT_DEFAULT)); } else { strAppPath += _T("\\resourcedll.dll"); HMODULE hModule = LoadLibrary( _T("resourcedll.dll")); AfxSetResourceHandle( hModule ); SetThreadLocale( MAKELCID( MAKELANGID(LANG_KOREAN , SUBLANG_KOREAN) , SORT_DEFAULT)); } 위의 코드에서 볼 수 있는 것과 같이 영문의 경우는, 로케일만 영문으로, 한국어와 일본어의 경우, 로케일 뿐만 아니라 외부의 라이브러리를 통해서 리소스를 불러 오게 했습니다. 만약 위의 코드에서, 일본어나 한국어 리소스 라이브러리를 못 찾는 경우는, 응용 프로그램에 있는 영문 리소스가 올라오거나 혹은 대화 상자가 제대로 나타나지 않아야 합니다. 테스트 결과를 보면 훌륭하게 잘 동작하는 것을 알 수 있습니다. 5. 결론 정리하자면, 리소스만을 따로 분리해서 동적 라이브러리 형태로 만들 수 있고, 이러한 라이브러리를 프로그램 행 시실 동적으로 호출하여, 리소스를 찾거나 혹은 불러 들이는 것이 가능합니다. 이게 오늘의 결론이군요. 한 가지, 주의하실 점은 이러한 종류의 프로그램, 즉 지역화 대비가 잘 된 프로그램들은, 프로그램 UI 변경에 무척 신경을 쓰셔야 합니다. 이러한 프로그램에서 UI 한 군데가 변경이 된다는 것은, 지역화된 언어들의 UI또한 모두 변해야 한다는 뜻이고, 개발자는 반드시 이러한 부분에 대해서 배포 하시기 전에 반드시 확인하셔야 합니다. C/C++/VC++ 리소스다국어VC