CREO Toolkit二次开发-使用钩子的方式实现Unicode下非模态对话框控件中文输入
使用MFC进行二次开发最大的问题就在于编码。使用的GB2312的编码虽然能保证常规的控件中文输入争取,但一些第三方控件或者新版MFC控件如ProPertyGrid等控件在GB2312中反而也会产生乱码。前文CREO Toolkit二次开发-UNICODE下非模态对话框控件中文输入提供了一种方法,但是存在如果在输入过程中弹出对话框会导致程序无法响应的严重Bug。本文尝试使用钩子的方式重新解决这个问题。
钩子的使用方式在CREO Toolkit二次开发-非模态对话框显示tooltip文中已经提及,这里不在赘述,写好钩子函数的模板:
1 | HHOOK hHook = NULL; |
1 | LRESULT CALLBACK __stdcall GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam) |
输入法对应的钩子消息有WM_IME_STARTCOMPOSITION
、WM_IME_COMPOSITION
以及WM_IME_ENDCOMPOSITION
,我们主要HookWM_IME_ENDCOMPOSITION
,在完成输入后处理:
1 | LRESULT CALLBACK __stdcall GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam) |
暂时找不到让非模态对话框自己处理消息的方法,不过在测试过程中发现,如果使用AfxMessageBox
弹出对话框之后,似乎由于模态的原因建立了消息循环,此时关掉对话框后能正常显示中文。由于AfxMessageBox
只能手动关闭,据此考虑弹出一个自定义模态对话框,弹出后瞬间在程序中关闭的方式看是否可以实现功能。尝试可行,对话框设置不可见,同时设置一个定时器,显示1毫秒后关闭,这样操作时中文输入基本无感。该模态对话框的关键设置代码如下:
1 | BOOL CDialogMessageLoop::OnInitDialog() |
项目基本完成,但仍存在如下问题:
- ComboBox这个控件会产生自动全选及输入位置错误,导致输入中文存在问题;
- 这里只Hook了WM_IME_ENDCOMPOSITION的消息,导致如果输入法选字采用的是鼠标点击的方式会无法响应,一样会产生乱码。但如果同时Hook鼠标左键点击则又会产生很多其它问题。
Unicode下非模态对话框控件中文输入确实很难解决,或许终极办法是将界面单独做成exe与dll通信,类似CREO Toolkit二次开发-利用.net程序制作界面
文中所示方法或者直接使用Creo自带的ui对话框,这里的方法聊胜于无吧。
代码公开,需要的人可以随便根据自己的环境修改编译。完整代码可在Github.com下载。代码在VS2010,Creo 2.0 M060 X64下编译通过。