为了实现应用程序的多语言显示,本人将相应语言的资源文件做成dll文件,在程序的InitInstance中通过LoadLibrary调用资源dll文件,然后用AfxSetResourceHandle();来装载资源dll文件。
但是这种方法必须重新运行应用程序,才能实现更换语言。
请问如何在程序运行过程中装卸资源文件?
但是这种方法必须重新运行应用程序,才能实现更换语言。
请问如何在程序运行过程中装卸资源文件?
调试欢乐多
资源文件在Delphi中的关键字为hinstance.下面给出具体用法
<1>光标的调用
首先在程序中定义一个值大于0的常量,因为Delphi本身用0-负
16来索引 默认的光标,所以我们制定的光标应从表面上1开始索引。然后
在窗口的Oncreat事件中添加以下代码:
screen.cursor[35]:Load cursor (hinstance,'mycur');
其中35为大于1的常量,mycur为光标在资源文件中的名字。如
果希望在 其他控件上使用定制光标,例如Panel控件,只需在程序的适当
处加入以下代码:
Panel1.cursor:=35;
<2>位图的调用
新建一项工程,添加一Timage控件,在需要显示的地方写以下代码:
Var mymap:Hbitmap;
begin
hmymap:=LoadBitmap(hinstance,'mypic');
Image1.picture.Bitmap.Handle:=mymap;
end;
其中"mypic"为位图资源文件中的名称。
〈3〉AVI文件的调用
新建一工程,添加一Animate控件,在需要的地方加入:
animater1.resname:='myAVI';
animater1.Active:=true;
其中myAVI为视频文件在资源文件中的名称。
〈4〉调用WAV文件
在uses中加入mmsystm单元,以便在程序中播放WAV文件。播放时Playsound
(pchar('mywav'),hinstance,sndsync or snd_resource);其中mywav为声音
文件在资源中的名称。
〈5〉加入光标
加入光标比较容易,只要将res文件加入单元文件中即可。但需注意,名称
最好取"W"."WW"等,使第一个字母尽量靠后,以免与主程序的图标顺序颠倒。
补充:1.资源类型除上述类型外,还可以字体文件,字符串文件等。
不知道应该如何实现呢?
eg:
var
h :integer;
begin
h := LoadLibrary('936.dll');
if (h <> 0)
begin
s := LoadString(h, 100, p);
end;
end;
在主程序中调用菜单命令,如下:void CSalesListApp::OnViewChinese()
{
//m_hLangDLL是资源句柄
::FreeLibrary(m_hLangDLL);
m_hLangDLL = ::LoadLibrary("Chinese.dll");
AfxSetResourceHandle(m_hLangDLL);
}这样程序是没有反应的。还请朋友指点。多谢了!如果解决了这个问题,我可以奉送200分。
procedure TForm1.Button1Click(Sender: TObject);
var
mdl : LongWord;
begin
While true do
begin
mdl := GetModuleHandle('Chinese.dll');
if mdl > 0 then
FreeLibrary(mdl)
else
Break;
end;
mdl := Loadlibrary('Chinese.dll');
end;
后要把m_hLangDLL置为0,如下
m_hLangDLL:= 0;
HRSRC hResource; // handle for FindResource
HGLOBAL hMem; // handle for LoadResource
LPVOID lpResource; // address of resource data // ::FreeLibrary("Chinese.dll"); // Load the file from which to copy the resource.
// 获取应用程序.EXE或dll的文件句柄,
// 该句柄用于在.EXE或dll文件中寻找资源
m_hLangDLL3 = ::LoadLibrary("English.dll"); //第一个参数是模块句柄
//第二个是要查找的资源名字,如"MYDIALOG"
//第三个是资源类型
//返回该资源句柄
//LoadResouce以该句柄为参数装入资源
//寻找具有指定资源ID和指定资源类型的资源文件中的资源位置,返回值为有名称的资源
//在动态链接库中查找资源类型为RT_MENU,资源名为128的资源
hResource = ::FindResource(m_hLangDLL3, MAKEINTRESOURCE(128), RT_MENU);
if (hResource == NULL)
AfxMessageBox("Error!");
// Load and lock the resource directory.
// first parameter: resource-module handle
// second parameter: resource handle
// 将该资源装入内存
// 返回值标识了用于接受资源数据的全局数据块
hMem = ::LoadResource(m_hLangDLL3, hResource);
if (hMem == NULL)
{
FreeResource(hResource);
AfxMessageBox("Error!");
} //锁定该资源
//锁定hg所标定的内存块,并返回所标定内存块的虚拟内存地址
//返回值指向该资源开始处的第一个字节
lpResource = ::LockResource(hMem);
if (lpResource == NULL)
{
FreeResource(hResource);
AfxMessageBox("Error!");
} //若上述四步中的任何一步发生问题,则返回并释放相应的内存。
//接下去要做的事情就是根据文件数据类型进行数据加载
//.......
//举例
//如何loadmenu并体现出来?请提示
UnlockResource(hMem);
FreeResource(hMem);
在Delphi中, 我用的是一个TMainMenu的控件(它已提供动态增减菜单的函数), 然后有运行时动态加入菜单项, 并从Resource中读出字符串来设置它的Caption, hint等的可视内容.
在VC中, 好像也有这样的菜单类...
现将学习成功共享如下:
更换菜单:
void CMainFrame::OnViewEnglish()
{ HMODULE hCurrentModule;
if (m_hLanguageDLL)
{
FreeLibrary(m_hLanguageDLL);
m_hLanguageDLL=NULL;
hCurrentModule=GetModuleHandle(NULL);
}
else
// hCurrentModule=m_hLanguageDLL=LoadLibrary(_T("scribdeu"));
hCurrentModule=m_hLanguageDLL=LoadLibrary(_T("English.dll")); ASSERT(hCurrentModule); //is the resource DLL existent?
AfxSetResourceHandle(hCurrentModule); CMenu DefaultMenu; CMenu *pMenu = GetMenu();
ASSERT(pMenu ); DefaultMenu.LoadMenu(IDR_MAINFRAME); SetMenu(&DefaultMenu); DefaultMenu.Detach();
}更换按钮的文字:
void CAboutDlg::OnEnglish()
{
// TODO: Add your control notification handler code here
HINSTANCE m_htest;
m_htest = NULL;
char* buf = NULL;
int buflen = 200;
buf = new char[buflen]; HINSTANCE m_hLangDLL3; // handle to LoadLibrary from .DLL file m_hLangDLL3 = ::LoadLibrary("English.dll");
if ( !(::LoadString(m_hLangDLL3, IDS_RESTART, buf, buflen)) )
{
AfxMessageBox("Load string error");
}
else
{
// AfxMessageBox(buf);
m_ctlChange1.SetWindowText(buf);
}
}