WinCE5.0 之SIP

      项目使用的是三星2440的ARM板,跑的wince5.0,软件因功能需要必须用到software based input panel(SIP)。一开始觉得软件盘不是什么大事应该不难搞,把CE5自带的软键盘调出来不久OK了?所以就把精力主要放在其他功能的实现上。在程序中简单的#include <Sipapi.h>后用SipShowIM(SIPF_ON)和SipShowIM(SIPF_OFF)一下就了事了,当然对自带的东东,美观上我也没抱什么希望,心想先把功能实现再说如果还有时间就自己做个,至少这样功能上完整了。 可是等基本把其它的搞完后把程序拷到板子上跑时才发现,之前一直用模拟器在调程序,模拟器中显示的800X480的像素在板子上的8寸显示屏上有很大缩水,小了很多,以致原来在模拟器中看到的软件盘还基本还可以用手准确的按到的Key在这上面却缩小了很多(据说是两种显示屏点距不一样造成的),根本不能用手指按到除非用笔尖点。使用受到了影响只有改程序,产品不可能为此专门配备一只点触笔。

    无奈下把程序打开,查查MSDN,想先找到使用大键盘的方法,什么遮挡问题都先不考虑了,在板子上能用手点了再说。sip就那几个函数找来找去就找到个可能可以设子软件盘尺寸的函数-------

BOOL SipSetInfo( 
  SIPINFO* pSipInfo
);
通过
BOOL SipGetInfo(
  SIPINFO* pSipInfo
);
先得到SipInfo,然后更改尺寸后再SipSetInfo,写完代码试了下发现没反应键盘尺寸还是没变。啥情况?无奈下继续看MSDN,然后就绝
望了。。。
In Windows CE 2.10 and later, the SipSetInfo function can either set a SIPINFO structure with the current 
software-based input panel state or take a SIPINFO structure and use its values to set the current software-based
 input panel state.In Windows CE 3.0 and later, you cannot use SipSetInfo to resize the SIP window. Use an IM to 
resize the SIP window. SIPINFO is also used by an application and an IM to send and receive IM-specific information. 
The IM receives information about the SIPINFO structure through the IInputMethod::GetSipInfo method. 
In Windows CE 3.0 and later, an application that calls SipSetInfo cannot resize the software-based input panel 
window.Only an IM can resize the software-based input panel window.
看来微软也挺搞,2.10中可以直接设置键盘尺寸,3.0就不行了,要设置必须要用输入法,通过输入法设置。可自带的三星2440wince5.0bin
和SDK中貌似都没搞入微软中文输入法,况且那玩意儿网上还都说不好用。可要在短时间内自己搞个输入法那是不可能,没办法看来自
带的sip是用不成了。只有自己搞个了。还好网上资源不少可惜都是win32的,下了些源代码看了看弄清了软键盘设计的基本思路,关键
是要让接受输入窗口不失去焦点并且相应键盘消息,总结了下方法无非就下面两种:
        方法1:利用 PreTranslateMessage,在底层调用它之前,前台窗口仍然没有改变,此时是获得前一个前台窗口,获
得后保存,并且使用 AttachThreadInput将当前线程绑定活动窗口的消息队列,然后在单击虚拟键盘时使用SetFocus将保存的窗
口设为焦点(同时使用了SetForgroundWindow和SetFocus),然后发送虚拟按键。
    方法2:设置主窗口属性为WM_ES_NOACTIVATE,这样窗口就不会成为前台窗口,不管如何发送键盘消息,拥有焦点
的窗口总会收到。但此时仍然存在问题。当移动窗口时,效果不大顺畅,而且没办法响应菜单命令,那是因为该窗口始终不是前台
窗口造成的。解决方法就是在单击标题栏时,成为前台窗口,释放是归还前台。
    从复杂度和原理上两种方法都差不多,当然都必须要使用keybd_event()函数对所有你想要的key进行keydown和keyup事
件的虚拟。而这也是通常是最痛苦的事情,100多的键啊。。。还好本项目中只用到数字和字母键。少了很多。然而困难总是存在,由
于开发板的驱动只对少数几个key做了keydown和keyup的实现,而使在程序中对驱动未支持的key做keybd_event()的虚拟并无
效果,所以我采用了直接发送键盘消息的方法:
如空格space键:
  ::PostMessage(p_hwnd,WM_KEYDOWN,(WPARAM)0x000020,(LPARAM)0x006E0001); //空格space键
  ::PostMessage(p_hwnd,WM_CHAR,(WPARAM)0x000020,(LPARAM)0x006E0001);
  ::PostMessage(p_hwnd,WM_KEYUP,(WPARAM)0x000020,(LPARAM)0x00E90001);
其中WM_KEYDOWN、WM_CHAR、WM_KEYUP是一个组合,不能打乱也不能缺少。如此一来就用消息实现了keybd_event()的
功能。所有的键都可以用这三个消息虚拟了。
    于是开始改程序,可改之前又有个问题,是把sip单独做成个程序每次用的时候调用呢还是把sip做到每个会用到sip的
程序里呢?出于wceui库实现的特殊性考虑,如果用前者,不管是使用上面的方法1和方法2都还需要更多更改和尝试。如果用后
者,针对wceuilayer的focus属性在程序中只有单个dlg情况下就算产生按键点击事件也不会改变这个好处,最后决定把sip集成
到每个需要使用到sip的单个程序中,虽然看起来麻烦了很多,但实际上却简单了不少。况且对CWEMoveAbleStatic做下扩展可
已很轻松的做出可移动的效果,同样也可以做得很拉风。于是开始写代码,搞图片,重新布置xml。。。最后在模拟器中和板子上
都跑了下,貌似效果还不错,而且还可以通过MoveBefore()很轻松的避免软键盘遮挡输入框的问题。搞完收工之余回顾了下,有
点小感慨,特到此mark一下-------看似再简单的问题,在你没还搞定它之前你也不能藐视它!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值