810 likes | 1.05k Vues
嵌入式操作系统原理 —— Windows CE. 第八章 应用程序设计. 内容概述. 独特的 Windows CE Windows CE 编程基础 Windows CE 编程技术. 1 独特的 Windows CE. 微处理器多样化 CE 不运行现有的程序 CE 有严格的内存限制 CE 硬件并不十分标准化 文件 I/O 的差别. 1.1 微处理器多样化. 其它 Windows 平台是 Intel x86 兼容的微处理器 CE 设备支持的微处理器包括: ARM ( 包括 Intel 的 XScale ) SHx MIPS x86.
E N D
嵌入式操作系统原理 ——Windows CE 第八章 应用程序设计
内容概述 • 独特的Windows CE • Windows CE编程基础 • Windows CE编程技术
1 独特的Windows CE • 微处理器多样化 • CE不运行现有的程序 • CE有严格的内存限制 • CE硬件并不十分标准化 • 文件I/O的差别
1.1 微处理器多样化 • 其它Windows平台是Intel x86兼容的微处理器 • CE设备支持的微处理器包括: • ARM(包括Intel 的XScale) • SHx • MIPS • x86
1.2 CE不运行现有的程序 • 现有Windows程序必须重新编译才能在Wince上运行 • 有些API被删除,有些被代替,还增加了一些其它的API • 字符集的区别,Windows 2000支持Unicode和ANSI, Windows 98只支持ANSI,WinCE使用Unicode • 提供了新的针对特定平台的控件,如命令栏(提供的功能类似菜单和工具栏,以减少占用屏幕的空间),而某些标准控件却减少了其功能
Wince只有4G的虚拟内存空间 2GB是为操作系统保留的 应用程序的2GB分成了33个slot(槽) 每个槽32MB 每个槽对应一个进程 1.3 CE有严格的内存限制
1.4 CE硬件并不十分标准化 • PC机组成:运算器、控制器、存储器、输入输出设备 • 各个CE设备的结构各不相同,而且通常没有鼠标、显示器(如果需要显示则大多使用触摸屏)
但是Windows CE编程仍然是Windows编程,有相同的消息循环、相同的窗口,大部分相同的资源和控件等,仍然是事件驱动的编程模型
2 Windows CE编程基础 • Windows消息处理机制 • 创建Win32应用程序 • Unicode • 诊断输出APIs • 文件I/O
Windows 产生一个消息 发送消息到拥有窗口的应用程序的消息队列中 应用程序预处 理消息 Windows发送该消息,即调用适当的窗口过程 应用程序删除该消息并回叫Windows发送该消息 窗口过程处理该消息 2.1 Windows 消息处理机制 • 操作系统发送消息给应用程序,应用程序响应相应的消息,进行消息处理
Windows消息处理机制代码示例 代码来源:Page101-108 Programming Microsoft Windowss CE.NET 3rd edition, Douglas Boling,Microsoft Press KeyTrac.h #define dim(x) sizeof(x)/sizeof(x[0]) …… //定义一个结构体,来表示消息和对应的处理函数 struct decodeUINT{ UINT Code;//消息 //处理函数 LRESULT (*Fnx)(HWND,UINT,WPARAM,LPARAM); };
…… //注册主窗口 int InitApp(HINSTANCE); //创建主窗口 HWND InitInstance(HINSTANCE,LPWSTR,int); //清理工作 int TermInstance(HINSTANCE,int); //窗口过程 LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM)
//下面几个函数是相应的消息处理函数 LRESULT DoCreateMain(HWND,UINT,WPARAM,LPARAM); LRESULT DoPaintMain(HWND,UINT,WPARAM,LPARAM); LRESULT DoKeysMain(HWND,UINT,WPARAM,LPARAM); LRESULT DoDestroyMain(HWND,UINT,WPARAM,LPARAM);
KeyTrac.cpp #include <windows.h> #include "KeyTrac.h" #include <commctrl.h> //应用程序名(使用的是Unicode/ANSI通用形式) const TCHAR szAppName[ ]=TEXT(“KeyTrac”); //程序句柄 HINSTANCE hInst; …… TCHAR szMsgTxt[64];
//消息及其处理函数结构体数组 const struct decodeUINT MainMessages[ ]={ WM_CREATE,DoCreateMain, WM_PAINT,DoPaintMain, WM_KEYUP,DoKeysMain, …… WM_KEYDOWN,DoKeysMain, WM_SYSKEYUP,DoKeysMain, WM_DESTROY,DoDestroyMain };
//程序的入口点是WinMain int WINAPI WinMain( HINSTANCE hInstance, //程序的句柄 HINSTANCE hPrevInstance, //为了兼容Win16程序而设置,总为0 LPTSTR lpCmdLine, //指向一个包含命令行文本的Unicode字符串 int nCmdShow) /*确定了该程序主窗口的初始状态 在Windows CE中,这个参数的值只允许有3种状态 正常(SW_SHOW) 隐藏//(SW_HIDE) 可见却不是活动窗口(SW_SHOWNOACTIVATE) */
{ MSG msg; //消息 int rc=0; HWND hwndMain; //主窗口 rc=InitApp(hInstance); //注册主窗口 if(rc) return rc; hwndMain=InitInstance(hInstance,lpCmdLine,nCmdShow); //创建主窗口初始化 if(hwndMain==0) return 0x10;
int InitApp(HINSTANCE hInstance) { WNDCLASS wc; wc.cbClsExtra=0; …… wc.hInstance=hInstance;//句柄 wc.lpfnWndProc=MainWndProc;//指定窗口过程函数 wc.lpszClassName=szAppName;//程序名 …… if(RegisterClass(&wc)==0) return 1;//注册窗口类 return 0; }
{ MSG msg; //消息 int rc=0; HWND hwndMain; //主窗口 rc=InitApp(hInstance); //注册主窗口 if(rc) return rc; hwndMain=InitInstance(hInstance,lpCmdLine,nCmdShow); //创建主窗口初始化 if(hwndMain==0) return 0x10;
HWND InitInstance(HINSTANCE hInstance,LPWSTR lpCmdLine,int nShowCmd) { HWND hWnd; hInst=hInstance; hWnd=CreateWindow(szAppName, TEXT("KeyTrac"), WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if(!IsWindow(hWnd)) return 0; ShowWindow(hWnd,nShowCmd); /*使窗口的属性 和主程序//指定的相同*/ UpdateWindow(hWnd); /*强制Windows发送WM_PAINT消//息给刚创建的窗口*/ return hWnd; } // InitInstance 结束
{ MSG msg; //消息 int rc=0; HWND hwndMain; //主窗口 rc=InitApp(hInstance);//注册主窗口 if(rc) return rc; hwndMain=InitInstance(hInstance,lpCmdLine,nCmdShow); //创建主窗口并初始化 if(hwndMain==0) return 0x10;
while(GetMessage(&msg,NULL,0,0)){ /*开始接收操作系统消息,直到得到消息WM_QUIT时GetMessage函数返回0,退出循环*/ TranslateMessage(&msg);/*将键盘消息转换成字符消息*/ DispatchMessage(&msg);/*通知操作系统将消息发送到应用程序适当的窗口,事实上就是操作系统调用相应的窗口过程,在此程序中就是调用MainWndProc */ } return TermInstance(hInstance,msg.wParam); /*清理工作,如释放内存等*/ }
//窗口过程,由操作系统调用 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT wMsg,WPARAM wParam,LPARAM lParam) { int i; for(i=0;i<dim(MainMessages);i++) { //调用对应的消息处理函数 if(MainMessages[i].Code==wMsg) return (*MainMessages[i].Fnx)(hWnd,wMsg,wParam,lParam); } return DefWindowProc(hWnd,wMsg,wParam,lParam); //调用系统的默认处理函数 }
int TermInstance(HINSTANCE hInstance,int nDefRC) {return nDefRC;} /*因为此程序比较简单,不需要做额外的清理工作 ;以下是消息处理函数,省略细节*/ LRESULT DoCreateMain(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam) { …… } LRESULT DoPaintMain(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam) { …… } LRESULT DoKeysMain(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam) { …… } LRESULT DoDestroyMain(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam) { …… }
2 Windows CE编程基础 • Windows消息处理机制 • 创建Win32应用程序 • Unicode • 诊断输出APIs • 文件I/O
Windows CE应用程序的类型 • 空项目 已有源代码文件时选择,仅需要将这些文件放到一起进行编译链接构造应用程序 • 简单 Windows CE 应用程序 选择简单 Windows CE应用程序可得到程序入口点WinMain。用于没有开头的 Windows CE系统, 因为最后的选项(即典型Hello World应用程序)要求有窗口管理器 • 典型 Hello World应用程序 当平台支持全部窗口和GWES的图形部分时选择典型 ‘Hello World’ 应用程序
创建Win32应用程序 • 更改BIB文件 • 最好在PROJECT.BIB文件中修改 • 通过Platform Builder修改PROJECT.BIB文件 • PROJECT.BIB文件内容 • MODULES • 通常是可执行程序,默认为XIP(就地执行) • 此部分的文件通常是非压缩的 • FILES • 包含静态数据文件 • 此部分的文件为压缩的
2 Windows CE编程基础 • Windows消息处理机制 • 创建Win32应用程序 • Unicode • 诊断输出APIs • 文件I/O
2.3 Unicode • Unicode具备的功能 • 字符和字符串的不同表示 • 编写Unicode源代码
Unicode具备的功能 • 使用Unicode进行应用程序开发可以满足产品国际化 • 可以很容易地在不同语言之间进行数据交换 • 使开发者能够分配支持所有语言的单个二进制.exe文件或DLL文件 • 提高应用程序的运行效率
字符和字符串的不同表示 • ANSI 字符和字符串 • ‘H’ • “Hello World” • 存储为char(signed)或者明确指明为unsigned • Unicode字符和字符串 • L‘H’ • L“Hello World” • 存储为w_char(unsigned short) • 双模式 • TEXT(‘H’) • TEXT(“Hello World”)
编写Unicode源代码 • C运行时库对Unicode的支持 • Windows定义的Unicode数据类型 • Windows中的Unicode函数和ANSI函数 • Windows字符串函数 • 为适应Unicode,编写应用程序的一些原则 • Unicode和ANSI之间的转换
C运行时库对Unicode的支持 • 标准的C头文件String.h中定义了一个wchar_t数据 类型来表示一个Unicode字符: typedef unsigned short wchar_t; • 但是标准的C运行时字符串函数只能对ANSI字符串进行操作。ANSI C补充了一组函数用于对 Unicode字符串进行操作。
C运行时库的转换函数 • 从Unicode转换 • 转换成Unicode
编写ANSI/Unicode通用的源代码原则 • 应该包含Tchar.h文件而非String.h文件。这样如果在源代码中有定义_UNICODE,则调用相对应的Unicode函数,否则调用ANSI函数。 • 定义字符串时应使用TCHAR数据类型。 • 在源代码如果定义了_UNICODE,则TCHAR的声明如下:typedef wchar_t TCHAR, • 否则TCHAR的声明如下:typedef char TCHAR • 应使用_TEXT(“string”)-----ANSI/Unicode这种方式,否则一旦用到不同的系统中就可能产生编译错误
Windows定义的Unicode数据类型 • WCHAR----Unicode字符 • PWSTR----指向Unicode字符串的指针 • PCWSTR----指向一个恒定的Unicode字符串的指针 • PTCHAR----ANSI/Unicode通用字符串的指针 • PCTSTR---- ANSI/Unicode通用的一个恒定字符串的指针 • 对于PTCHAR和 PCTSTR的具体数据类型,要看源代码中是否定义了UNICODE宏(注意不是_UNICODE)
Windows中的Unicode函数和ANSI函数 在Windows中很多函数都有两个版本,一个ANSI版本,一个Unicode版本。例如: HWND WINAPI CreateWindowExW(……); //Unicode版本 HWND WINAPI CreateWindowExA(……); //ANSI版本 但是代码中只需使用WINAPI CreateWindowEx就可以了,因为Windows的WinUser.h文件中有以下定义: #ifdef UNICODE #define CreateWindowEx CreateWindowExW #else #define CreateWindowEx CreateWindowExA #endif
Windows字符串函数 • 在程序中尽量使用Windows提供的字符串操作函数来代替使用C运行时字符串函数,这样可以提高应用程序的执行效率,因为这些函数常常因为大型应用程序使用而已经装入了RAM中。这些函数名同时包含了大小写字母。例如:StrCat、StrChr、StrCmp、StrCpy等等。同其它很多Windows函数一样,它们也都有Unicode和ANSI两个版本。 • 另外,Windows还提供了另一组对Unicode字符串进行操作的函数:lstrcat、 lstrcmp、 lstrcmpi、 lstrcpy、 lstrlen、CharLower、CharUpper等。
为适应Unicode,编写应用程序的一些原则 • 将文本串视为字符数组,而不是chars数组和字节数组 • 将通用数据类型(如TCHAR和PTSTR)用于文本字符和字符串 • 将显式数据类型(如BYTE和PBYTE)用于字节、字节指针和数据缓存。 • 将TEXT宏用于原义字符和字符串 • 执行全局性替换(例如用PTSTR替换PSTR) • 修改字符串运算。例如应该使用sizeof(szBuffer)/sizeof(TCHAR)而不应使用sizeof(szBuffer)来获得缓存的大小。
Windows 中Unicode和ANSI之间的转换 多字节字符串转换成Unicode字符串 int MultiByteToWideChar( UINT uCodePage,DWORD dwFlags, PCSTR pMultiByte,//要转换的字符串指针 int cchMultiByte,/*要转换的字符串长度(以字节计算)*/ PWSTR pWideCharStr,/*转换后的Unicode字符串缓存指针*/ int cchWideChar);/*转换后的Unicode字符串缓存的最大值(以字符计算)*/
Windows 中Unicode和ANSI之间的转换 Unicode字符串转换成多字节字符串 WideCharToMultiByte(UINT uCodePage, DWORD dwFlags, PWSTR pWideCharStr,/*需转换的Unicode字符串缓存指针*/ int cchWideChar,/*要转换的字符串长度(以字符数计算)*/ PCSTR pMultiByte,/*转换后的字符串指针*/ int cchMultiByte,/*转换后的字符串缓存区大小(以字节计算)*/ PCSTR pDefaultChar,/*无法转换时使用的默认字符*/ PBOOL pfUsedDefaultChar);/*是否使用默认字符*/
2 Windows CE编程基础 • Windows消息处理机制 • 创建Win32应用程序 • Unicode • 诊断输出APIs • 文件I/O
2.4 诊断输出APIs • MessageBox • 显示信息窗口 • 必须在包含GWES模块的系统中才能使用 • 例如 • NKDbgPrintfW • 在调试器中设定格式和显示格式信息 • 可以在任何地方使用 • 例如
2 Windows CE编程基础 • Windows消息处理机制 • 创建Win32应用程序 • Unicode • 诊断输出APIs • 文件I/O
2.5 文件I/O • WinCE没有当前目录的概念 • 所有的文件名都必须以“\”开始 • 文件名需是Unicode • 使用GetModuleFileName()函数得到应用程序路径 • Memory-Mapped I/O • 应用程序读写文件时使用,例如MapViewOfFile() • 在Windows CE上使用时,比传统的文件读写操作速度快 • 需要较少的内存
3 Windows CE编程技术 • Native application----使用Embedded Visual C++ • Managed application----使用Visaul Studio .NET