作者:胡明明
邮箱:mingming_killer@126.com
在使用MiniGUI的时候总有有些功能MiniGUI没有的,或者是MiniGUI的某些功能不太适用的。这就需要我们开发人员动手稍微改一下MiniGUI了。这次我遇到的情况就是要去掉MiniGUI ime输入法窗口的自动出现和消失功能。我使用的MiniGUI版本是GPL的1.3.3(该方法同样适用于2.0.4的ime输入法,但是可能需要稍微改一下下,不过思路是一样的),thread模式。
一、问题来源
用过MiniGUI的ime输入法的兄弟们都知道1.3.3(2.0.4)的输入法窗口只要你创建了以后,但凡遇到可编辑的控件得到输入焦点(Edit控件),就会自动出现(即便你把它手动关闭了);可编辑的控件失去输入焦点ime窗口就会自动关闭。这个功能估计本意是想让ime输入法窗口比较人性化的,但是不少用户(至少我原来这家公司的不少用户有这个要求)还是比较喜欢类似于桌边操作系统那样的输入法,需要时自己手动切换出来,不需要的时候就换回去(QQ拼音、搜狗、google等等)。
二、解决思路
要解决这个问题首先要弄清楚为什么MiniGUI的ime输入法窗口会有上述说的那些自动功能。经过我的研究1.3.3的源代码发现实现上述功能主要是MiniGUI的默认窗口处理函数(DefaultMainWinProc())和Edit控件做了些“多余”的事。
首先DefaultMainWinProc()中的DefaultPostMsgHandler()这个函数在接受到MSG_SETFOCUS和MSG_KILLFOCU这两消息后,向当前处于焦点(或是失去焦点)的控件发送MSG_DOESNEEDIME消息来确认是否是需要自动开启、关闭ime输入法的功能。如果该控件响应了MSG_DOESNEEDIME消息,并返回TRUE的话自动的开启、关闭ime输入法(目前只有Edit控件相应这个消息)。
OK我们明白了这个原理后,要想去掉这个功能就好办了,我只需要在DefaultPostMsgHandler()里再MSG_SETFOCUS和MSG_KILLFOCUS消息里不自动调用向控件发送MSG_DOESNEEDIME消息的函数就可以了(open_ime_window())。不过我的修改MiniGUI的一个基本原则就是尽量保持与原来功能的兼容性,所以我决定增加一个BOOL变量开关来让外部应用程序来控制是否关闭MiniGUI ime的自动开启、关闭功能。当外部应用程序通过消息接口设置为TRUE时,则开启ime的自动开启、关闭功能;当设置成FALSE时则关闭ime的自动开启、关闭功能(此时应用程序可以自行控制ime窗口的开启、关闭)。
三、实现方法
有了上面的思路就好办多了,好了现在就开始修改。首先是要增加相应的BOOL开关变量的应用声明和相应的设置消息接口。我把这些放在libminigui-1.3.3/include/window.h下:
// ********************************************************
// hack by mingming-killer 2010.3.22
//#define MSG_LASTWINDOWMSG 0x010F
// choose whether auto switch ime windows
// lParam = (LPARAM)bAuto;
// TRUE: auto; FALSE: manual
extern BOOL bAutoIme;
#define MSG_SETAUTOIME 0x010F
#define MSG_LASTWINDOWMSG 0x0110
// ********************************************************
注意要注释掉原来的MSG_LASTWINDOWMSG定义,然后把这个值加大些,因为我们这里多出一个消息接口了(MSG_SETAUTOIME)。
然后就是增加响应MSG_SETAUTOIME这个消息的代码。这里要找一个依托的窗口过程处理函数。这时找桌面过程处理函数我认为最适合不过啦,所以就在libminigui-1.3.3/src/kernel/desktop-comm.c里的WindowMessageHandler()函数里的switch部分增加如下代码:
// ********************************************************
// hack by mingming-killer 2010.3.22
// Provide a interface to external application that can set auto or manual switch the ime window.
case MSG_SETAUTOIME:{
bAutoIme = (BOOL)lParam;
break;
}
// ********************************************************
接下来就是在libminigui-1.3.3/src/gui/window.c里加入BOOL开关变量的定义:
// ********************************************************
// hack by mingming-killer 2010.3.22
// ime window auto switch flag
// TRUE: auto; FALSE: manual
BOOL bAutoIme = TRUE;
// ********************************************************
最后是在的DefaultPostMsgHandler()里的switch部分的MSG_SETFOCUS和MSG_KILLFOUCS那调用open_ime_window()前加上我们之前新增加的开关变量的判断:
case MSG_SETFOCUS:
case MSG_KILLFOCUS:
if (pWin->hActiveChild)
SendNotifyMessage (pWin->hActiveChild, message, 0, 0);
// ********************************************************
// hack by mingming-killer 2010.3.22
// Provide a interface to external application that can set auto or manual switch the ime window.
if ( TRUE == bAutoIme )
open_ime_window (pWin, message, (HWND)wParam);
// ********************************************************
break;
OK,改好后重新编译libminigui。然后在应用程序中的MiniGUIMain入口函数那,在开始主窗口消息循环前调用SendMessage,向桌面(HWND_DESKTOP)发送MSG_SETAUTOIME即可设置ime窗口的自动开启、状态。
由于1.3.3是GPL的,所以这里附上我修改好的1.3.3的源代码文件以及一个测试该功能的一个小例子程序。x86 redhat9 framebuffer下测试通过。
参考资料:飞漫MiniGUI 1.3.3 API手册
--
MingmingKiller - 06 Apr 2010