在WinCE程序开发中使用软件输入面板
发布时间:2006-06-02 13:16:03 来源:天极开发 网友评论 0 条 简介
软件输入面板(Software Input Panel,简称SIP)是每个装备了WinCE系统的移动平台的一个基本功能。它提供给用户在PDA上进行数据输入的一种手段。当谈及SIP的时候,我们一般会想到两点:一是SIP本身,二是如何在程序中使用SIP。
SIP是一个实现了IInputMethod或者IInputMethod2接口的COM对象。它应该被系统调入使用,所以你不能在C#中进行SIP开发。C或者C++是很好的开发语言。因为SIP本身也只是另外一个COM对象,ATL使得开发过程变得极为简单。这里我不想讨论SIP开发,SDK包里包含了一个很好的例程ATLDvoraksip,所以你可以去学习这个例程以获取更多的信息。 这里我想讨论的是如何在你自己的程序里管理SIP。这看起来很琐碎简单,但是如果因为屏幕不太够用,而你又想使得你的程序更加聪明更加方便用户使用,那SIP的管理就变成很重要的一个方面了。另外,如果你开发了很多用于不同场合的SIP(比如多语言,数字或者其他等等),你可能想在某个场合使用某个特定的SIP。这种能力使得你可以完成很多不同的任务:当用户只需要进行数字输入的时候,你可以展示一个大的数字键盘,这样他不用笔而只需要用手指就可以输入了。当然你也可以有自己的想法,这就看程序员该作些什么了。
Win32 API
SIP的API函数很简单,从sipapi.h中只可以看到只有极少几个函数:
我把这些放在开始,是因为它同时支持Windows Mobile和CE.NET平台。如果你对Windows Mobile设备编程,那么aygshell.h文件提供给你更多的和SIP有关的函数供使用。当然选择哪个来使用就依赖于你自己的需求了,使用Windows Mobile上的SIP会使得工作更加完美一些。如果你使用了相同的OS版本,但是不同的build版本的时候,你可能会获得稍微不同的SIP行为。所以,一种方法并不一定像你所想的那样在所有的PDA上都会适用。
列举可用的SIP
第一步就是了解如何列举所有可用的SIP。可以使用如下的代码:
代码所作的就是填充一个全局的map,它包含了"SIP名"/CLSID对。这个例子和其他的都用到了MFC,当然你也可以使用熟悉的Win32 API或者其他的框架。以下是我的Dell Axim x50上的显示效果:
如何选择,显示和隐藏特定的SIP
当你知道某个SIP的CLSID,你可以选择它。同时,当前选择的SIP也可以被获得:
这里,你可以看到修改的例子(CSIPDemoDlg::OnButtonEnum()),它检测哪个SIP是被激活的并且选择listbox里相应的行。其他例子的对话框方法选择SIP并且显示或者隐藏它。注意,为了使得SipGetInfo或者SipSetInfo工作,你必须用sizeof(SIPINFO)的值初始化SIPINFO.cbSize,这样操作系统才能正常反应。这是一个很常用的Win32的解决方式。
SipGetInfo给你可视的桌面和SIP大小,这样你可以在需要的时候重新定制SIP的位置。而SipSetInfo不会改变SIP的位置。如果你需要移动SIP,使用SipSetDefaultRect。下面会给出一些例子来说明的。
软件输入面板(Software Input Panel,简称SIP)是每个装备了WinCE系统的移动平台的一个基本功能。它提供给用户在PDA上进行数据输入的一种手段。当谈及SIP的时候,我们一般会想到两点:一是SIP本身,二是如何在程序中使用SIP。
SIP是一个实现了IInputMethod或者IInputMethod2接口的COM对象。它应该被系统调入使用,所以你不能在C#中进行SIP开发。C或者C++是很好的开发语言。因为SIP本身也只是另外一个COM对象,ATL使得开发过程变得极为简单。这里我不想讨论SIP开发,SDK包里包含了一个很好的例程ATLDvoraksip,所以你可以去学习这个例程以获取更多的信息。 这里我想讨论的是如何在你自己的程序里管理SIP。这看起来很琐碎简单,但是如果因为屏幕不太够用,而你又想使得你的程序更加聪明更加方便用户使用,那SIP的管理就变成很重要的一个方面了。另外,如果你开发了很多用于不同场合的SIP(比如多语言,数字或者其他等等),你可能想在某个场合使用某个特定的SIP。这种能力使得你可以完成很多不同的任务:当用户只需要进行数字输入的时候,你可以展示一个大的数字键盘,这样他不用笔而只需要用手指就可以输入了。当然你也可以有自己的想法,这就看程序员该作些什么了。
Win32 API
SIP的API函数很简单,从sipapi.h中只可以看到只有极少几个函数:
| DWORD WINAPI SipStatus(); BOOL WINAPI SipSetDefaultRect(RECT *); BOOL WINAPI SipRegisterNotification(HWND); BOOL WINAPI SipShowIM(DWORD); BOOL WINAPI SipGetInfo(SIPINFO *); BOOL WINAPI SipSetInfo(SIPINFO *); int WINAPI SipEnumIM(IMENUMPROC); BOOL WINAPI SipGetCurrentIM(CLSID *); BOOL WINAPI SipSetCurrentIM(CLSID *); |
我把这些放在开始,是因为它同时支持Windows Mobile和CE.NET平台。如果你对Windows Mobile设备编程,那么aygshell.h文件提供给你更多的和SIP有关的函数供使用。当然选择哪个来使用就依赖于你自己的需求了,使用Windows Mobile上的SIP会使得工作更加完美一些。如果你使用了相同的OS版本,但是不同的build版本的时候,你可能会获得稍微不同的SIP行为。所以,一种方法并不一定像你所想的那样在所有的PDA上都会适用。
列举可用的SIP
第一步就是了解如何列举所有可用的SIP。可以使用如下的代码:
| CTypedPtrMap<CMapStringToPtr,CString,CLSID*> g_SipMap; int SipEnumIMProc(IMENUMINFO *pIMInfo) { CLSID* pCLSID = new CLSID; memcpy(pCLSID,&pIMInfo->clsid,sizeof(CLSID)); g_SipMap.SetAt(CString(pIMInfo->szName),pCLSID); TRACE(_T("%sn"),CString(pIMInfo->szName)); return 1; } void CSIPDemoDlg::OnButtonEnum() { SipEnumIM(SipEnumIMProc); CString sSipName; CLSID *pCLSID = NULL; for (POSITION pos = g_SipMap.GetStartPosition(); pos; ) { g_SipMap.GetNextAssoc(pos,sSipName,pCLSID); m_SipList.AddString(sSipName); } } |
代码所作的就是填充一个全局的map,它包含了"SIP名"/CLSID对。这个例子和其他的都用到了MFC,当然你也可以使用熟悉的Win32 API或者其他的框架。以下是我的Dell Axim x50上的显示效果:
![]() |
如何选择,显示和隐藏特定的SIP
当你知道某个SIP的CLSID,你可以选择它。同时,当前选择的SIP也可以被获得:
| void CSIPDemoDlg::OnButtonEnum() { SipEnumIM(SipEnumIMProc); CLSID CurrSip; SipGetCurrentIM(&CurrSip); int nCurrSip = LB_ERR, nSipCount = 0; CString sSipName, sCurrSipName; CLSID *pCLSID = NULL; for (POSITION pos = g_SipMap.GetStartPosition(); pos; ) { g_SipMap.GetNextAssoc(pos,sSipName,pCLSID); m_SipList.AddString(sSipName); if ( memcmp(&CurrSip,pCLSID,sizeof(CLSID)) == 0 ) { nCurrSip = nSipCount; sCurrSipName = sSipName; } nSipCount++; } m_SipList.SelectString(0,sCurrSipName); } void CSIPDemoDlg::OnButtonSelect() { int nSel = m_SipList.GetCurSel(); if ( LB_ERR == nSel ) return; CString sSipName; m_SipList.GetText(nSel,sSipName); CLSID *pCLSID = NULL; if ( !g_SipMap.Lookup(sSipName,pCLSID) ) return; BOOL bRes = SipSetCurrentIM(pCLSID); if ( !bRes ) TRACE(L"SipSetCurrentIM returned %lun",GetLastError()); } void CSIPDemoDlg::OnButtonShowHide() { if ( !g_bShow ) { SipShowIM(SIPF_ON); g_bShow = TRUE; } else { SipShowIM(SIPF_OFF); g_bShow = FALSE; } } void CSIPDemoDlg::OnButtonShowHide2() { SIPINFO SipInfo; memset(&SipInfo,0,sizeof(SipInfo)); SipInfo.cbSize=sizeof(SIPINFO); BOOL bRes = SipGetInfo(&SipInfo); if ( bRes ) { if ( !g_bShow ) { SipInfo.fdwFlags |= SIPF_ON; g_bShow = TRUE; } else { SipInfo.fdwFlags = SIPF_OFF; g_bShow = FALSE; } bRes = SipSetInfo(&SipInfo); } else { TRACE(L"SipGetInfo returned %lun",GetLastError()); } } |
这里,你可以看到修改的例子(CSIPDemoDlg::OnButtonEnum()),它检测哪个SIP是被激活的并且选择listbox里相应的行。其他例子的对话框方法选择SIP并且显示或者隐藏它。注意,为了使得SipGetInfo或者SipSetInfo工作,你必须用sizeof(SIPINFO)的值初始化SIPINFO.cbSize,这样操作系统才能正常反应。这是一个很常用的Win32的解决方式。
SipGetInfo给你可视的桌面和SIP大小,这样你可以在需要的时候重新定制SIP的位置。而SipSetInfo不会改变SIP的位置。如果你需要移动SIP,使用SipSetDefaultRect。下面会给出一些例子来说明的。
- 推荐阅讯
- VS2005为Windows移动程序创建安装文件
- 用Oracle并行查询发挥多CPU的威力
- J2ME内存占用详解及优化方法
- Oracle 9i 数据库WITH查询语法小议
- BEA交付WebLogic 9.2,为实施SOA铺平道路
- Hibernate二级缓存攻略
- Oracle SQL性能优化系列讲座之三
- 你的代码真的很健壮吗
- 个人门户终结WEB2.0 门户巨头优势明显
- 探讨Windows编程中句柄的本质
- 阅读排行
- 1..net页面间的参数传递简单实例
- 2.VC++与Matlab混合编程之引擎操作详解
- 3.Oracle数据库数据对象分析
- 4.Eclipse3.2+Tomcat5.5.17+Oracle9配置
- 5.Oracle数据库中索引的维护
- 6.在Oracle的网络结构中解决连接问题
- 7.Oracle数据安全面面观
- 8.Oracle数据库的ORA-00257故障解决过程
- 9.Oracle数据库备份与恢复的三种方法
- 10.Oracle与SQL Server在企业应用中的比较
- 专题教程
- Windows Server-Windows Server文档-Windows Server新闻-Windows Ser PostgreSQL-PostgreSQL文档-PostgreSQL新闻-PostgreSQL专家
- WebLogic-WebLogic文档-WebLogic新闻-WebLogic专家 FreeBSD-FreeBSD文档-FreeBSD新闻-FreeBSD专家
- Linux-内核 GUI KDE Gnome DNS FTP 安全 安装-Linux专区 Windows-AD IIS ServerCore 虚拟化 安全 HPC-Windows专区
- 大话G游 专题:手机病毒揭密
- ARP攻击防范与解决方案 路由故障处理手册

