■北京 张伟
喜欢玩软件的朋友一定经常遇到RePack的软件。所谓RePack,一般是针对原有软件不足进行优化(比如汉化、打补丁、增加插件等)并重新打包成安装程序,使用起来更加顺手。究竟RePack是如何进行呢?这次就请北京的张伟朋友给大家演示一下。此外,限于版面本文插图略有删改,完整文章电子版及最终王码五笔字型输入法安装包可在http://www.cfan.com.cn/11program/200423/tioclk.html下载。非常适合喜欢Visual
C 朋友按部就班,跟着文章一步步操作。
Windows
XP没有自带五笔字型输入法,虽然网上相关输入法很多,但一方面有些版本是共享软件,另一方面也许很多五笔字型输入法的老用户最习惯用的还是老牌的“王码五笔字型输入法86/98版”。
微软Office
XP中包含了王码五笔,但如果仅仅是为了使用它而运行Office
XP安装程序,就显得有些小题大做了,更不用说是某些临时在外面用公用电脑而又想用五笔字型输入法的情况。于是网上出现了很多简化安装方法,大体可分为三个步骤:
1.拷贝输入法文件(从Office
XP光盘中或已经安装了“王码五笔字型输入法”的电脑中提取)
2.增加注册表项
3.重启后通过控制面板添加输入法
整个过程中拷贝输入法文件和增加注册表项可以用批处理和导入注册表文件来简化操作,但必须重启电脑才能在控制面板里添加输入法,这同样让使用者觉得比较烦琐。作为编程爱好者能不能通过写个小程序实现在不重启全自动安装“王码五笔字型输入法”呢(也就是即装即用)?答案是肯定的!因为Office
XP安装程序做到了,这就表示微软肯定留有一个专门用来安装输入法的接口,一般来说应该是一系列API函数。
经过一番摸索,笔者在MSDN里找到了这个可以用来安装输入法的API:ImmInstallIME()。OK,现在就开始利用它实现自己的“王码五笔字型输入法”全自动安装程序。
一、准备素材
先试着从Office
XP光盘中提取“王码五笔字型输入法”的输入法文件。通过Windows查找功能第一张安装盘中查找与“WINWB”相关的文件,在OFFICE1.CAB中找到以下14个文件:WINWB86.CHM.*、WINWB86.CNT.*、WINWB86.HLP.*、WINWB86A.IME.*、WINWB86A.MB.*、WINWB86W.IME.*、WINWB86W.MB.*、WINWB98.CHM.*、WINWB98.CNT.*、WINWB98.HLP.*、WINWB98A.IME.*、WINWB98A.MB.*、WINWB98W.IME.*、WINWB98W.MB.*,其中*是很长的一串由字母、数字和下滑线组成的序列(个人认为应该是微软为校验文件内容正确性而加上的为该文件校验码的后缀)。去掉这个长长的后缀,可以看到5种类型的文件。很明显,*.CHM、*.CNT和*.HLP是输入法帮助文件,*.MB是码表文件,*.IME是输入法主文件。其中*.IME和*.MB有文件名部分以A结尾和以W结尾两个版本,经过试验证实了它们分别是ANSI和UNICODE两种版本的输入法文件。文件名部分以A结尾的文件适用于Windows
9x,以W结尾的文件适用于NT系列Windows。
提取了输入法文件后必须让安装程序针对不同版本操作系统将它们拷贝到正确的目录,以便调用API来进行输入法安装。笔者分别在安装了Office
XP中自带的“王码五笔字型输入法”的Windows 98SE和Windows
XP中查找以上文件,发现帮助文件都存放在\Windows\HELP目录中(这里假设系统安装在Windows目录)。而主要的输入法文件(*.IME)和码表文件(*.MB)在Windows
9x下存放于\Windows\SYSTEM目录中,在NT系列Windows系统中存放于\Windows\SYSTEM32目录中。
二、相关API函数
素材准备工作已经完成,现在来看一下代码编写过程中需要用到的4个主要的API函数。
1.DWORD
GetVersion(VOID)
该函数返回与当前使用的Windows系统版本有关的信息。可通过判断返回值最高位是否为1来判断当前是用的系统是NT/2000/XP还是9x/ME。
2.BOOL
CopyFile(LPCTSTR lpExistFileName, LPCTSTR lpNewFileName, BOOL
bFailIfExists);
该函数将以lpExistFileName指向的字符串为文件名的文件复制为以lpNewFileName指向的字符串为文件名的新文件。这里的文件名可以包含文件路径。最后的参数bFailIfExists决定当新文件已存在时是否覆盖现有文件,如果为FALSE,则覆盖。
3.HKL
ImmInstallIME(LPCTSTR lpszIMEFileName, LPCTSTR
lpszLayoutText);
这是制作“王码五笔字型输入法”全自动安装程序的关键函数。函数两个参数分别为输入法IME文件的文件名和在控制面板的是输入法选项中显示的输入法名称。函数调用后将返回一个被安装输入法的输入法标识符(或称做输入法句柄)。
4.BOOL
ImmIsIME(HKL
hKL);
该函数判断hKL指向的输入法是否有效。可以用ImmInstallIME函数的返回值作为该函数参数,通过函数返回值来判断输入法是否安装成功。
三、创建工程并添加代码
1.打开Visual C
6.0,通过菜单“File→New”新建名为“WINWB”的“Win32 Application”工程,单击“OK”。
2.在应用程序类型选择中选择“An
empty project”,单击“Finsish”。这样我们就新建好了一个空的Win32应用程序工程。
3.通过菜单“Project→Add to
Project→New”添加一个“Resource
Script”资源文件,命名为“WINWB”。
4.通过菜单“Insert→Resource”添加一个新的Dialog资源。
5.调整Dialog资源的若干属性。在Dialog的任意空白区域双击鼠标左键打开属性对话框,在属性对话框的Gerneral选项卡中更改ID为“IDD_MAIN”、
Caption属性为“王码五笔字型输入法安装程序”。单击Font按钮,更改字体为宋体9号(这是简体中文版XP的标准字体型号)。单击More
Styles选项卡,选中Center属性,使对话框能在屏幕中居中显示。
6.关闭属性对话框,回到资源编辑界面。删掉系统自动添加的“Cancel”按钮并更改“OK”按钮的Caption属性为“安装”。
7.添加一个新的Static
Text控件,打开属性对话框更改Caption属性为“请选择输入法版本:”。
8.添加一个新的List
Box控件,打开属性对话框更改ID为“IDC_LIST”,并更改它的Selection属性为“Multiple”。
9.适当调整控件的大小和位置,完成资源创建(见图1)。
10.通过菜单“Project→Add to Project→New”添加一个“C Source
File”代码文件,命名为“WINWB”。
11.在新添加“WINWB.CPP”文件中输入程序代码,代码如下:
#include
<Windows.h>
#include "resource.h"
#pragma comment(lib, "imm32.lib")
#define IME_WINWB86 0
#define IME_WINWB98 1
BOOL CALLBACK Main_DlgProc(HWND, UINT, WPARAM, LPARAM);
LPCTSTR TranslateFileName(LPCTSTR);
void InstallIME(int);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE
hPrevInstance,
LPSTR lpCmdLine,
int
nShowCmd)
{
DialogBox(hInstance, (LPCTSTR)IDD_MAIN, NULL,
Main_DlgProc);
return 0;
}
// 对话框IDD_MAIN的回调函数
BOOL CALLBACK Main_DlgProc(HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
TCHAR strWINWB86[] =
"王码五笔字型输入法86版";
TCHAR strWINWB98[] = "王码五笔字型输入法98版";
TCHAR cBuf[30]; // 存放LISTBOX中ITEM文本的缓冲区
int
nBuf[2]; // 存放LISTBOX中被选中的ITEM索引号的缓冲区
int nSel;
// LISTBOX中被选种的ITEM的数目
switch (uMsg)
{
case WM_INITDIALOG:
//
初始化LISTBOX
SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING, 0,
(LPARAM)strWINWB86);
SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING, 0,
(LPARAM)strWINWB98);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
// 响应“退出”按钮
case
IDCANCEL:
EndDialog(hDlg, 0);
return TRUE;
// 响应“添加”按钮
case IDOK:
// 获取LISTBOX中被选中的ITEM的数目及索引号
nSel =
SendDlgItemMessage(hDlg, IDC_LIST, LB_GETSELITEMS, 2, (LPARAM)nBuf);
if (nSel == 0)
{
MessageBox(hDlg, "请选择输入法版本!", "提示信息",
MB_OK);
return TRUE;
}
for (-- nSel; nSel >= 0; nSel --)
{
//
获取LISTBOX中该索引号对应的ITEM的文本
SendDlgItemMessage(hDlg, IDC_LIST, LB_GETTEXT,
nBuf[nSel], (LPARAM)cBuf);
if (lstrcmp(cBuf, strWINWB86) == 0)
{
InstallIME(IME_WINWB86); //
安装王码五笔字型输入法86版
}
else if (lstrcmp(cBuf, strWINWB98) ==
0)
{
InstallIME(IME_WINWB98); // 安装王码五笔字型输入法98版
}
}
return TRUE;
}
default:
return FALSE;
}
}
TCHAR g_strFileName[MAX_PATH]; // 函数TranslateFileName用到的字符串缓冲区
// 将以Windows目录为基准的用相对路径表示的文件名转换成用绝对路径表示的文件名
LPCTSTR
TranslateFileName(LPCTSTR lpszFileName)
{
//
获取Windows目录的路径
GetWindowsDirectory(g_strFileName, MAX_PATH);
// 如果Windows目录的路径是根目录
if (g_strFileName[lstrlen(g_strFileName)-1] ==
'\\')
{
// 去掉路径最后的“\”
g_strFileName[lstrlen(g_strFileName)-1] =
'\0';
}
// 连接Windows目录路径和用相对路径表示的文件名
lstrcat(g_strFileName, lpszFileName);
return g_strFileName;
}
// 安装指定的输入法
void InstallIME(int nIMEType)
{
TCHAR
strWINWB86A[] = "王码五笔字型86版";
TCHAR strWINWB86W[] = "中文 (简体) -
王码五笔字型86版";
TCHAR strWINWB98A[] = "王码五笔字型98版";
TCHAR strWINWB98W[] = "中文
(简体) - 王码五笔字型98版";
HKL hKL;
if (nIMEType == IME_WINWB86)
{
// 复制输入法帮助文件
CopyFile("WINWB86.HLP",
TranslateFileName("\\HELP\\WINWB86.HLP"),
FALSE);
CopyFile("WINWB86.CHM", TranslateFileName("\\HELP\\WINWB86.CHM"),
FALSE);
CopyFile("WINWB86.CNT", TranslateFileName("\\HELP\\WINWB86.CNT"), FALSE);
if (GetVersion() < 0x80000000) // NT/2000/XP系统
{
//
复制UNICODE版输入法文件
CopyFile("WINWB86W.IME", TranslateFileName("\\SYSTEM32\\WINWB86.IME"),
FALSE);
CopyFile("WINWB86W.MB", TranslateFileName("\\SYSTEM32\\WINWB86.MB"), FALSE);
// 安装UNICODE版输入法
hKL = ImmInstallIME(TranslateFileName("\\SYSTEM32\\WINWB86.IME"),
strWINWB86W);
}
else // 9X/ME系统
{
//
复制ANSI版输入法文件
CopyFile("WINWB86A.IME", TranslateFileName("\\SYSTEM\\WINWB86.IME"),
FALSE);
CopyFile("WINWB86A.MB", TranslateFileName("\\SYSTEM\\WINWB86.MB"), FALSE);
// 安装ANSI版输入法
hKL = ImmInstallIME(TranslateFileName("\\SYSTEM\\WINWB86.IME"),
strWINWB86A);
}
// 验证输入法句柄是否有效
if (ImmIsIME(hKL))
{
MessageBox(NULL,
"安装王码五笔字型输入法86版成功!", "提示信息", MB_OK);
}
else
{
MessageBox(NULL,
"安装王码五笔字型输入法86版失败!", "提示信息", MB_OK);
}
}
else if (nIMEType ==
IME_WINWB98)
{
CopyFile("WINWB98.HLP", TranslateFileName("\\HELP\\WINWB98.HLP"),
FALSE);
CopyFile("WINWB98.CHM", TranslateFileName("\\HELP\\WINWB98.CHM"),
FALSE);
CopyFile("WINWB98.CNT", TranslateFileName("\\HELP\\WINWB98.CNT"), FALSE);
if (GetVersion() < 0x80000000)
{
CopyFile("WINWB98W.IME",
TranslateFileName("\\SYSTEM32\\WINWB98.IME"),
FALSE);
CopyFile("WINWB98W.MB", TranslateFileName("\\SYSTEM32\\WINWB98.MB"), FALSE);
hKL = ImmInstallIME(TranslateFileName("\\SYSTEM32\\WINWB98.IME"),
strWINWB98W);
}
else
{
CopyFile("WINWB98A.IME",
TranslateFileName("\\SYSTEM\\WINWB98.IME"),
FALSE);
CopyFile("WINWB98A.MB", TranslateFileName("\\SYSTEM\\WINWB98.MB"), FALSE);
hKL = ImmInstallIME(TranslateFileName("\\SYSTEM\\WINWB98.IME"),
strWINWB98A);
}
if (ImmIsIME(hKL))
{
MessageBox(NULL, "安装王码五笔字型输入法98版成功!", "提示信息",
MB_OK);
}
else
{
MessageBox(NULL, "安装王码五笔字型输入法98版失败!", "提示信息",
MB_OK);
}
}
}
四、制作安装包
在菜单“Build→Set
Active Configuration”设置工程配置为“Win32