模块切换——MFC的规则DLL中资源使用的问题

今天刚刚做了一个静态链接到MFC的规则dll,即“Use MFC in a static library“,该dll用来显示一个窗体。然后在一个mfc可执行程序A.exe中调用这个dll文件,可以正常的显示窗体。但后来做了一点小小的改动,即把dll改成动态连接到MFC的dll,即“Use MFC in a shared dll ”,然后在A.exe中调用该dll,结果窗体怎么都不显示。后来,经过仔细的分析,原因如下:

    动态连接到MFC的dll,可以喝使用它的可执行程序同时连接到MFC DLL和任何MFC 扩展DLL。在使用了MFC共享库的时候,默认情况下,MFC使用主应用程序(本例中是A.exe)的资源句柄来加载资源模板。这样,当dll和应用程序中存在相同的ID的资源时,系统总是默认使用应用程序的资源,故不能获得正确的资源。所以,在共享MFC DLL的规则DLL,我们必须进行模块切换,使得MFC能够找到正确的资源模板。

    共有三种方法:

1. 在dll中自动切换,在dll的显示窗体的接口函数中使用AFX_MANAGE_STATE(AfxGetStaticModuleState()),如下:

void ShowDlg(void)

{

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    CDialog1 dlg;

    dlg.DoModal();

}

 

2. 在dll中手动切换,如下:

void ShowDlg(void)

{

    HINSTANCE save_hInstance = AfxGetResourceHandle();
     AfxSetResourceHandle(theApp.m_hInstance); //切换为dll

 

    CDialog1 dlg;

    dlg.DoModal();

 

    AfxSetResourceHandle(save_hInstance); //还原为可执行程序

}

 

3. 在应用程序中自由切换

dll中的不做任何改动,如下

void ShowDlg(void)

{

    CDialog1 dlg;

    dlg.DoModal();

 }

而在应用程序中调用该dll的地方作如下改动:

 

HINSTANCE hExe=GetModuleHandle(NULL);//获取exe模块句柄

HINSTANCE hDll=GetModuleHandle("1.dll");//获取dll模块句柄

AfxSetResourceHandle(hDll); //切换为dll

ShowDlg();//调用dll中的ShowDlg()函数

AfxSetResourceHandle(hExe); //还原为可执行程序

 

### MFC 中实现国际化和多语言支持的方法 在 MFC 应用程序中实现国际化和多语言支持是一个复杂的过程,涉及资源管理、线程语言设置以及动态加载机制。以下是详细的实现方式: #### 1. 资源文件的多语言备份 为了支持多种语言,可以为每种语言创建独立的资源文件(`.rc` 文件)。这些资源文件包含了应用程序中的字符串表、菜单项和其他 UI 元素。通过这种方式,可以在运行时根据用户的语言偏好加载相应的资源。 - 使用 Visual Studio 的资源编辑器工具,为每种目标语言生成一个新的资源文件副本。 - 将新资源文件命名为类似于 `resource_ja.rc` 或 `resource_fr.rc`,分别表示日语和法语文本[^1]。 #### 2. 动态加载资源模块 当需要切换语言时,可以通过加载特定的语言 DLL 来覆盖默认资源。这种方法允许开发者将不同语言的资源分离到单独的 DLL 文件中。 ```cpp HINSTANCE LoadLanguageDll(const CString& strLangCode) { CString dllName; dllName.Format(_T("%s%s"), _T("lang_"), strLangCode); HINSTANCE hInst = ::LoadLibrary(dllName); if (!hInst) { AfxMessageBox(_T("Failed to load language resource!")); } return hInst; } ``` 此代码片段展示了如何根据指定的语言代码加载对应的资源 DLL[^3]。 #### 3. 设置线程的语言环境 为了使 FindResource 函数能够识别并返回正确的本地化资源,必须先调整当前线程的语言设置。这通常通过调用 `SetThreadLocale` 和/或 `SetThreadUILanguage` 完成。 然而需要注意的是,在较旧版本的开发环境中可能不支持某些 API。例如,VC++ 6.0 不提供对 `SetThreadUILanguage` 的原生支持;在这种情况下,应采用动态链接库的方式间接访问该功能[^2]: ```cpp typedef LANGID (WINAPI *FP_SetThreadUILanguage)(LANGID LangId); LANGID SetThreadUILanguage(LANGID lcid) { HMODULE hKernel32 = GetModuleHandle(_T("Kernel32.dll")); FARPROC pFn = GetProcAddress(hKernel32, "SetThreadUILanguage"); FP_SetThreadUILanguage pSetThreadUILanguage = reinterpret_cast<FP_SetThreadUILanguage>(pFn); if (pSetThreadUILanguage != nullptr) { return pSetThreadUILanguage(lcid); } return 0; // 返回零意味着失败或者未找到函数入口点 } ``` 以上实现了跨平台兼容性的解决方案,即使是在早期编译器环境下也能正常工作。 #### 4. 自动检测用户首选语言 最后一步是增强用户体验——即自动探测用户的操作系统区域设定,并据此预设初始界面语言。可通过如下方法获取系统安装的语言列表及其优先级顺序: ```cpp WCHAR wszLanguagesBuffer[1024]; DWORD dwSize = GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &dwNumLanguages, wszLanguagesBuffer, sizeof(wszLanguagesBuffer)/sizeof(WCHAR)); if(dwSize > 0){ PCZZWSTR pszLanguages = wszLanguagesBuffer; while(*pszLanguages){ // 对每一个语言名称执行处理逻辑... pszLanguages += wcslen(pszLanguages)+1 ; } } ``` 这段脚本利用 Windows 提供的 `GetUserPreferredUILanguages` 接口来检索用户的首选显示语言集合[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值