📄 123.txt
字号:
这个文件包含了一组文件,它们中定义了Windows API及其用到的结构和常量。
程序的入口点是本程序和标准C程序之间最大的差别。作为C标准入口
int main (char **argv, int argc)
的替代品,Windows CE通过标准Windows入口点[注1]
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow);
构建程序环境。
Windows CE在一些方面不同于桌面版的Windows。第1个参数,hInstance为其它应用程序指明具程序实例,也为需要验证这个EXE的Windows API函数提供了程序实例。参数hPrevInstance是从旧的Win16 API(Windows 3.1及更早的系统)遗留下来的。包括Windows CE在内的所有Win32 操作系统中,hPrevInstance 始终是0,可以忽略掉。
参数lpCmdLine指向一个Unicode字符串,包含了命令行文本。从微软Windows CE浏览器启动的应用程序没有命令行参数,但在某些情况下,例如当系统自动启动一个程序时,系统包含一个命令行参数来说明程序为什么被启动。参数lpCmdLine 是Windows CE与XP出现差异的情况之一,在Windows CE里,命令行字符串是Unicode字符串,在其它版本的Windows 里,命令行字符串总是ASCII的。
最后一个参数,nCmdShow,指明了程序主窗口的初始状态。由父进程,通常是浏览器传递这个参数到程序里。它对应用程序如何配置主窗口给出了说明。该参数可能会规定窗口最初显示成图标(SW_SHOWMINIMIZE),或者显示最大化(SW_SHOWMAXIMIZED)来覆盖整个桌面,或者显示为普通(SW_RESTORE)大小来表明窗口按标准可变大小方式显示在屏幕上。其它值规定窗口初始状态对用户不可见,或者规定窗口可见但不能成为活动窗口。在Windows CE里,这个参数的值被限制成3个状态:普通(SW_SHOW)、隐藏(SW_HIDE)和非激活显示(SW_SHOWNOACTIVATE)。除非应用程序需要强制它的窗口预先确定状态,在程序主窗口被创建后,这个值是不加修改,只是简单的传递给ShowWindow函数的。
下一行是这个应用程序唯一的功能行:
printf ("Hello World\n");
Windows CE支持大部分标准C库,包括printf,getchar等等。这一行有趣的地方在于它不像Windows CE其它任何地方,这个串不是Unicode而是ANSI。下面是对这个现象的合理解释:对于用ANSI标准编译的C标准库,printf和诸如strcpy等其它字符串库函数用的是ANSI字符串。当然,Windows CE支持这些标准函数的Unicode版,例如 wprintf, getwchar,和 wcscpy。
最后,用return 0;结束程序。
其它进程可以用Win32 API函数GetExitCodeProcess获取返回值。
构建第一个应用程序
要在你的系统上从头创建Hello1,可以启动MS eVC++,在[File]菜单上选择[新建]创建一个新工程。当看到新工程的对话框,可以明显的看到WinCE编程与标准Win32编程的变化。你有机会选择在图1-1中所显示的各种平台。对于非MFC或ATL工程,首选是WCE Pocket PC应用(用于Pocket PC)和WCE应用(用于其它Windows CE系统)。您还可以选择适当的目标CPU。例如,选择Win32(WCE MIPI)来为使用MIPS CPU的Windows CE平台编译程序。无论是何种目标设备,都要确保选择WCE模拟器。这样你就可以在用XP下的模拟器中运行例子程序了。
图1-1 平台列表使eVC++能够面向不同的Windows CE平台。
接下来,eVC++会询问您是否想创建一个空的工程、一个简单程序或者一个Hello World 应用。对本书里所有的例子,都选择空工程。这样做是为了避免代码向导向例子添加任何额外的代码。在[File]菜单选择[New],Hello1.cpp创建新文件。
当为Hello 1创建或从CD复制了合适的源文件,选择Win32(WCE x86em) Debug作为目标平台,之后build这个程序。这一步会编译源代码,如果没有编译错误的话,系统自动启动模拟器,并把EXE程序放到模拟器文件系统里,接下来你可以启动Hello1。如果你在Windows 98或Me系统下,模拟器系统能够会显示一个错误信息,因为模拟器只能在Win2000或XP下运行。
如果你有Windows CE系统,比如Pocket PC(PPC),把PPC连接到PC上,方法和同步PC的内容到PPC一样。打开微软ActiveSync,建立PPC和PC的链接。为了Windows CE设备能够运行,虽然ActiveSync链接并不是必须的,但我发现让它运行可以为开发环境和Windows CE系统之间建立一个更稳定的链接。
一但PC和Windows CE设备之间的链接成功和运行,切换回eVC++,选择合适的目标设备(如适合iPaq Pocket PC的Win32 [WCE ARM] Debug)进行编译和rebuild。和为模拟器创建程序一样,如果没有错误,eVC++自动下载编译程序到远程设备上。程序要么被放到对象存储的根目录上,要么放在\windows\start菜单目中。
运行该程序
要在嵌入式Winodows CE设备H/PC上运行Hello1,单击手持式PC的My Computer图标,找到根目录下的文件,之后双击应用程序图标启动程序。
要在Pocket PC上运行程序,从设备的Start菜单选择程序就可以了。因为eVC++已经把程序下载到\windows\start菜单所在的目录了。这种方式下,下载的应用程序自动显示在Start菜单里。
有问题?
如果在Pocket PC上点击图标或开始菜单选择Hello1程序,似乎没什么反应。在手持式PC上,程序似乎只是刷新了一下屏幕。这是因为程序启动、写到控制台并结束了。除非你从一个已经创建的控制台启动程序,否则Windows CE会在Hello1执行printf语句时,创建一个控制台窗口,并且在Hello1结束的时候自动关闭控制台。
在Pocket PC上,应用程序可以运行,但Pocket PC并不为诸如printf之类的输出提供控制台显示的功能。通过把驱动程序console.dll放到Pocket PC的Windows 目录里,可以为Pocket PC增加控制台支持。驱动程序从驱动程序接口获取输入,创建屏幕窗口,打印输出字符串。控制台启动程序可以从手持式PC和嵌入式版本的Windows CE获得。
注1:虽然从技术上可以改变入口点原型来匹配C的标准入口点,但通常不值得这么麻烦的。
Hello2
既然已经有了基础,那么是时候把Hello1升级一下,至少应该让人可以看见它。因为很多Windows CE系统没有控制台驱动程序,Hello2创建一个消息框而不是用printf来显示“Hello CE”文字。Hello2的程序如下表1-2所示:
列表1-2: Hello2, 使用MessageBox函数的简单应用程序
Hello2.cpp
//======================================================================
// Hello2 - A simple application for Windows CE
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include "windows.h"
//
// Program entry point
//
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow) {
MessageBox (NULL, TEXT ("Hello World"), TEXT ("Hello2"), MB_OK);
return 0;
}
编译并运行Hello2,可以看到如图1-2所示的小窗口。
图1-2(略)
运行在Windows CE桌面的Hello2
替代printf的MessageBox函数为Hello2提供了2个特性。第一个也是最明显的一个就是它创建一个窗口,并在上面显示"Hello World"文本。第二个特性是MessageBox函数直到用户关闭消息窗口才会返回。这允许Hello2一直保持运行,直到用户关闭窗口。
MessageBox函数原型如下:
int MessageBox (HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
第1个参数是顶层窗口的句柄,它是消息窗口的父窗口。目前我们把这个参数置为NULL,因为Hello2还没有任何其它窗口。第2个参数是准备显示在窗口里的文字。注意传入的字符串是用TEXT宏包裹的,确保它能够编译成Unicode版本。第3个参数lpCaption是显示在窗口标题栏的文字。最后一个参数uType是一系列标志位,规定消息框如何显示在屏幕上。标志位规定了消息框中按扭的数量和类型,规定了图标的类型以及消息框窗口的风格设置。
表1-2列出了Windows CE下有效的标志位
表1-2: 默认标志位
Windows应用程序剖析
基于Windows的编程远不同于基于MS-DOS或Unix的编程。只要是程序需要,任何时候基于MS-DOS或Unix的程序都可以使用getc-或putc风格的函数从键盘读取字符并写到屏幕上。这是MS-DOS或Unix程序所使用的典型的"Pull"(拉)风格,这种风格是面向过程的,而一个Windows程序,则使用"Push"(推)模式。在这种模式下,必须编写程序来响应来自操作系统的通知,比如一个键被压下去了或者收到一个重绘屏幕的命令。
Windows应用程序并不从操作系统请求输入,而是由操作系统通知应用程序输入产生了。操作系统通过发送消息(messages)给应用程序窗口来完成这些通知。所有窗口都是窗口类的具体实例。在进一步深入之前,让我们先确保理解这些术语。
窗口类
窗口是屏幕上的一个区域,除了特殊情况,基本上都是矩形。窗口有一些基本参数,比如位置参数--x,y和z(窗口在屏幕其它窗口之上或者之下)--可视性以及层次关系--窗口与系统桌面形成父子窗口关系,系统桌面也是一个窗口。
每个被创建的窗口都是窗口类的一个具体实例。窗口类是一个模板,为该类的所有窗口定义了许多共同属性。换句话说,属于同一个类的窗口有同样的属性。这些共享的属性中最重要的是窗口过程。
窗口过程
窗口类里窗口过程中的代码定义了同一个类里所有窗口的行为。窗口过程处理发到窗口的所有通知和请求。这些通知,要么是操作系统发给窗口,告诉窗口有事件发生,窗口必须回应,要么是其他窗口发来的,向该窗口查询信息。
这些通知是以消息的形式发送的。消息实际就是对窗口过程的一次调用,带有参数指出通知或者查询的种类。当有事件发生,例如窗口被移动、被改变大小或有键被按下去等,就会发送消息。标识消息的值由Windows定义。应用程序使用预定义好的常量,例如WM_CREATE和 WM_MOVE,来表示消息。因为有很多消息可被发送,所以当窗口类对某个消息没有特殊处理的必要时,Windows提供了一个默认处理函数来处理传递这些消息。
消息生命周期
让我们回头一会,看一下Windows是如何协调发到系统里各个窗口的各种消息的。Windows监视系统的所有输入,例如键盘、鼠标、触摸屏以及其它可以产生影响窗口的事件的硬件。当事件发生后,消息就被构成并定向给特定的窗口。Windows没有直接调用窗口过程,而是加了一个中间步骤。消息被放到拥有该窗口的应用程序的消息队列里了。当应用程序准备接收消息的时候,它把消息从队列里取出来,并告诉Windows发送该消息到应用程序适当的窗口上。
你可能会认为这个过程中涉及许多中间步骤,那么你是对的。就让我们分解一下这个过程吧。
1、当事件发生,Windows就构成一个消息并放到拥有目的窗口的应用程序的消息队列里。和在XP里一样,在Windows CE中,每个应用程序有自己单独的消息队列[1] (这与Windows3.1及更早的Windows版本不同,那时只有唯一一个系统范围内的消息队列)。事件发生及构成一个消息都要比应用程序处理它们的速度快。虽然程序最好能快速响应或者用户希望看到应用程序快速响应,但是队列允许应用程序按自己的速率处理消息。消息队列允许Windows在运做中设置一个通知并继续完成其它任务,而不是仅仅限制在只响应收到消息的这个应用程序。
2、应用程序把消息从消息队列中移出来,并回调Windows来分派消息。似乎很奇怪应用程序从队列里获得消息却只是简单的回调Windows来处理这个消息,对这种方式,解释如下:应用程序从队列里获取消息,这使得应用程序在请求Windows把消息分派到相应窗口之前,可以预处理这些消息。许多情况下,应用程序会调用Windows里不同的函数来处理具体的各种消息。
3、Windows分发消息,更确切的说,是Windows调用相应的窗口过程。没有让应用程序直接调用窗口过程,而是间接调用,这允许Windows协调这个窗口过程的调用与系统里的其它事件。虽然此刻消息并不在另外一个队列里,但Windows在调用窗口过程之前,可能需要做一些预处理。但无论如何,这种调度方式减少了应用程序的责任,不用程序去决定适当的目的窗口,而是由Windows负责了。
4、窗口过程处理消息。所有的窗口过程都有相同的调用参数:被调用的窗口实例的句柄、消息参数、两个普通参数,包含与消息相关的数据。窗口过程用窗口句柄区分窗口的每个实例。消息参数,指明窗口必须响应的事件。两个普通包含与消息相关的数据。例如,WM_MOVE消息指出窗口将被移动,其中一个普通参数指向一个包含窗口新坐标的结构。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -