WinCE程序设计的几个关键技术

来源:百度文库 编辑:神马文学网 时间:2024/04/25 19:49:03
内存处理
WinCE设备通常没有台式机那么多的内存(通常PPC为32M),CE用户可以调整存储内存和程序使用内存的大小,当可用内存容量小于一定水平时,操作系统自己会要求程序释放内存,甚至自动关闭程序。笔者见到一些商业化WinCE测图软件调入图形文件时长达数分钟,运行缓慢,测图效率大打折扣。主要原因内存小,主频低,且PPC显示屏小,笔者认为PPC不适合作为测图硬件,或许手持PC(H/PC)更能胜任。
因此应用程序必须是满足低内存要求,采用的对策主要有:
保持小尺寸的EXE文件
主要是减少资源文件(*.RC)中位图、不用的字符串和加速键等。
集中分配所需内存
尽可能采用LocalAlloc、HeapAlloc、VirtualAlloc等内存分配函数一次性分配所需内存。一般情况采用LocalAlloc函数,当需要分配大内存时考虑使用VirtualAlloc,当需要解决内存碎片问题时采用HeapAlloc。
管理低内存状态
微软建议PPC程序不设不设关闭按纽,当系统需要额外内存是自动关闭它们。WinCE添加了WM_HIBERNATE消息,当内存很少时发送到应用程序,要求程序释放内存。测绘软件应该响应此消息,保留有用数据,提示用户进行必要的处理等。
及时查询内存状态
两个有用的API 函数可查询系统内存:GetSystemInfo和GlobalMemoryStatus函数。如GlobalMemoryStatus(LPMEMORYSTATUS lpmst)的结构MEMORYSTATUS中的两个字段dwTotalPhys表示程序内存总量和可用的空闲程序内存。
采用内存分配函数是一定要检查返回值,如分配失败作必要处理。
WinCE只支持Unicode字符集
Unicode字符集是一个世界范围内的字符编码标准,采用Unicode字符集便于全球化的应用程序,但对习惯Win9X的程序员带来的一些不便。
解决的方法主要有:
采用TCHAR或CString类声明所有字符串
采用TEXT、或_T宏表示程序中的文字:TEXT("abc")或_T("abc")
采用通用字符串函数或CString处理字符串:如wsprintf、 _tcslen等
实现ANSI和Unicode字符的转换,可采用API函数WideCharToMultiByte和MultiByteToWideChar,也可采用ATL和MFC提供的转换宏。下面提供一个函数:
LPSTR UnicodeToANSI(const CString& str,int &len)
{
len = WideCharToMultiByte(CP_ACP,0,str,-1,NULL,NULL,NULL,NULL);
LPSTR buf = (LPSTR)LocalAlloc(LMEM_ZEROINIT,len);
VERIFY(WideCharToMultiByte(CP_ACP,0,str,-1,buf,len,NULL,NULL) == len);
return (buf);
}
目标系统处理
由于WinCE支持的目标设备多样性,不同设备有不同版本的WinCE和SDK、不同的CPU、不同的显示屏、不同的外设,因此保持通用的代码几乎是不可能的。采用对策主要有:
eVC开发时需要针对不同设备编译:IDE环境提供平台选项,重新编译即可。
添加检测版本和平台代码:如#if UNDER_CE < 210 或#ifdef _PPC等。
对不同设备设计不同的用户界面:如对H/PC(多为横向显示屏)、PPC(多为纵向显示屏)分别设计对话框,检测平台后决定调用各自对话框。
运行时进行动态库版本检测区分不同目标系统:如采用GetVersionEx、SystemParametersInfo、LoadLibrary等。
当然最好是在不同设备上进行测试。
用户界面(UI)设计
WinCE的UI和Win32 UI主要区别有:不支持多文档界面、位图菜单、非客户窗口绘制管理、消息钩子、GDI中若干功能(坐标变换、MoveTo等API函数),其对输入笔、语音、输入面板、热键输入等确支持良好,在支持大多数Win32控件基础上,WinCE提供了几个特有控件。
输入笔输入消息可看作鼠标输入的子集,响应左键消息WM_L*和WM_MOUSEMOVE,编程方便。
输入面板控制技术对无键盘的PPC尤为重要,如当光标落入编辑框时,自动升起输入面板,反之收起面板;当输入面板起落时,应用软件能适时调整窗口等,这些均体现了软件用户界面的友善性。实现不复杂,主要调用API函数SHSipInfo,可查阅微软提供的帮助文档(MSDN)中的例程。
对于使用PPC的测量员更希望有一个较大按键的输入面板,WinCE系统不能满足要求,有必要编写一个,笔者在Douglas Boling(Window CE程序设计一书作者)的例程基础上制作了一个“数字键盘”。对输入方法编程主要利用了COM接口IIMCallback中两个方法:SendVirtualKey和SendCharEvents。
对于不支持多文档界面的WinCE,可以采用多种方法来模拟。笔者采用的一种方法是:在单文档视(VIEW)的客户区,采用多个无模式对话框,达到了仿真效果。主要代码如下:
class CLevelRecDlg : public CDialog
{
// Construction
public:
… …   //成员变量定义
public:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual void PostNcDestroy();
… …  //其他函数定义
};
//WindowProc函数由于取消IDOK、IDCANCEL消息,防止对话框被错误关闭
LRESULT CLevelRecDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if ((message == WM_COMMAND) && (wParam <= 2))
return 1;
return CDialog::WindowProc(message, wParam, lParam);
}
同样编写其他对话框类。
在视类中添加以下代码
class CLevelRecView : public CView
{
protected: // create from serialization only
CLevelRecView();
DECLARE_DYNCREATE(CLevelRecView)
… …
public:
CLevelRecDlg m_RecDlg;                //添加无模式对话框成员变量
CBrowseDlg m_BrowseDlg;
BOOL m_bRecView;                     //显示对话框的BOOL成员变量
BOOL m_bBrowseView;
… …
};
在视响应WM_CREATE消息的函数内创建对话框
int CLevelRecView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
m_RecDlg.Create(IDD_DIALOG_LEVELREC, this); //在此创建
… …
}
接着编写一个视成员函数显示指定对话框
void CLevelRecView::ChangeView()
{
if (m_bRecView)
{
m_RecDlg.ShowWindow(SW_SHOW);
m_BrowseDlg.ShowWindow(SW_HIDE);
m_RecDlg.UpdateWindow();
m_RecDlg.SetFocus();
}
……
}
当然,UI应考虑本地化问题,由于eVC未提供自动支持中文界面的功能,笔者采用的方法是将资源文件(*.rc)采用文本编辑器打开,将其中涉及到代码页(code page)处用中文资源文件中相应部分替换,将英文文字替换成中文即可。
WinCE下MFC编程
进行WinCE快速编程,最好的方法是采用MFC,所幸的是Microsoft将WinCE的MFC封装的十分精巧,其和台式机的MFC版本只有一些细微的差别,只要阅读帮助文档即可轻松的采用MFC进行WinCE的开发,简化了其他Win32系统下MFC程序的移植工作。WinCE的MFC对部分类作了轻微修改,如CString、CWnd、 CframeWnd等;少数类不支持,如MDI类、DAO类、ODBC类等;针对WinCE的特性增加了几个类,如:CE的数据库类CceDB*、CceSocket。值得一提的是CString类简化了大量Unicode问题。
其他主题
WinCE的API是经过仔细筛选Win32 API,保留了约1000个函数;其MFC、ATL(不支持标准模板库STL)、ADO可看作为台式机版本的子集。 WinCE独有的存储方式是对象存储,不过API和台式机类似,同样亦支持COM/DCOM(组件对象模型),不过一些C/C++运行库、C++的异常处理不支持。WinCE通信方式很多,测绘软件设计人员多关心其串行通信编程,遗憾的是Mircosoft没有提供相应的Activex控件,必须采用API实现,在《测绘通报》上已有论文详述。
笔者在开发过程中发现eVC可能存在一些Bug:如对话框中的只读编辑框不能变灰(可通过处理WM_CTLCOLOR解决),浮点型变量不能比较大小(换成整型后解决)。