`
lingzantia
  • 浏览: 152679 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

[翻译]-WinCE 程序设计 (3rd 版)--1.7 HelloCE

阅读更多

HelloCE
Windows 编程中典型的SDK风格饱受责难的地方就是在窗口过程中总是使用巨大的switch语句。switch语句分析传给窗口过程的消息,这样每个消息可以被独立的处理。这种标准结果的优势之一是强制把一个类似的结构加到几乎所有Windows应用程序中,这使一个程序员可以更容易理解另一个人的代码。劣势是 整个窗口过程的所有的变量通常会比较杂乱的出现在过程的开头。

这么多年来,我为我的Windows程序探索出一个不同的风格。主要想法是将WinMain和WinProc过程分解成更易理解和更易转换到其它Windows程序中的可管理单元。WinMain被分解成几个过程,包括执行应用程序初始化、实例初始化和实例终止。作为所有Windows程序核心的消息循环也在WinMain里。

窗口过程被分解为几个独立过程,每个处理一个具体的消息。窗口过程自身是一个代码框架,只是查找传入的消息,看是否有过程来处理这个消息。如果有,则调用该过程;如果没有,则把消息传递给默认的窗口过程。

把对消息的处理划分成独立的块,使该结构更容易被理解。并且,由于将一个消息处理代码段同另一个极大的隔离开来,可以使您更容易把处理特定消息的代码从一个程序转换到另一个程序。还是在很多年前,我从Ray Duncan在《PC杂志》的“编程力量”专栏里,第一次看到对这种结构的描述。在MS-DOS和OS/2编程领域里,Ray是传奇人物之一。虽然为了适合我的需要,我对这种设计做了一些修改,但这还是应该归功于Ray。

代码
HelloCE的源代码如清单1-4所示:
清单1-4 HelloCE程序
HelloCE.h
//======================================================================
// Header file
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//================================================================
// Returns number of elements
#define dim(x) (sizeof(x) / sizeof(x[0]))

//----------------------------------------------------------------------
// Generic defines and data types
//
struct decodeUINT { // Structure associates
UINT Code; // messages
// with a function.
LRESULT (*Fxn)(HWND, UINT, WPARAM, LPARAM);
};
struct decodeCMD { // Structure associates
UINT Code; // menu IDs with a
LRESULT (*Fxn)(HWND, WORD, HWND, WORD); // function
};

//----------------------------------------------------------------------
// Function prototypes
//
HWND InitInstance (HINSTANCE, LPWSTR, int);
int TermInstance (HINSTANCE, int);

// Window procedures
LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);

// Message handlers
LRESULT DoPaintMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDestroyMain (HWND, UINT, WPARAM, LPARAM);
//======================================================================
// HelloCE - A simple application for Windows CE
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#include "helloce.h" // Program-specific stuff

//----------------------------------------------------------------------
// Global data
//
const TCHAR szAppName[] = TEXT("HelloCE");
HINSTANCE hInst; // Program instance handle

// Message dispatch table for MainWindowProc
const struct decodeUINT MainMessages[] = {
WM_PAINT, DoPaintMain,
WM_DESTROY, DoDestroyMain,
};

//======================================================================
// Program entry point
//
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow) {
MSG msg;
int rc = 0;
HWND hwndMain;

// Initialize this instance.
hwndMain = InitInstance (hInstance, lpCmdLine, nCmdShow);
if (hwndMain == 0) return 0x10;

// Application message loop
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
// Instance cleanup
return TermInstance (hInstance, msg.wParam);
}
//----------------------------------------------------------------------
// InitInstance - Instance initialization
//
HWND InitInstance (HINSTANCE hInstance, LPWSTR lpCmdLine, int nCmdShow) {
WNDCLASS wc;
HWND hWnd;

// Save program instance handle in global variable.
hInst = hInstance;

#if defined(WIN32_PLATFORM_PSPC)
// If Pocket PC, only allow one instance of the application
hWnd = FindWindow (szAppName, NULL);
if (hWnd) {
SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
return 0;
}
#endif

// Register application main window class.
wc.style = 0; // Window style
wc.lpfnWndProc = MainWndProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = 0; // Extra window data
wc.hInstance = hInstance; // Owner handle
wc.hIcon = NULL, // Application icon
wc.hCursor = LoadCursor (NULL, IDC_ARROW);// Default cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = szAppName; // Window class name

if (RegisterClass (&wc) == 0) return 0;

// Create main window.
hWnd = CreateWindow (szAppName, // Window class
TEXT("HelloCE"), // Window title
// Style flags
WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT, // x position
CW_USEDEFAULT, // y position
CW_USEDEFAULT, // Initial width
CW_USEDEFAULT, // Initial height
NULL, // Parent
NULL, // Menu, must be null
hInstance, // Application instance
NULL); // Pointer to create
// parameters
if (!IsWindow (hWnd)) return 0; // Fail code if not created.

// Standard show and update calls
ShowWindow (hWnd, nCmdShow);
UpdateWindow (hWnd);
return hWnd;
}
//----------------------------------------------------------------------
// TermInstance - Program cleanup
//
int TermInstance (HINSTANCE hInstance, int nDefRC) {
return nDefRC;
}
//======================================================================
// Message handling procedures for main window
//
//----------------------------------------------------------------------
// MainWndProc - Callback function for application window
//
LRESULT CALLBACK MainWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
INT i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for (i = 0; i < dim(MainMessages); i++) {
if (wMsg == MainMessages[i].Code)
return (*MainMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}
//----------------------------------------------------------------------
// DoPaintMain - Process WM_PAINT message for window.
//
LRESULT DoPaintMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
PAINTSTRUCT ps;
RECT rect;
HDC hdc;

// Get the size of the client rectangle
GetClientRect (hWnd, &rect);

hdc = BeginPaint (hWnd, &ps);
DrawText (hdc, TEXT ("Hello Windows CE!"), -1, &rect,
DT_CENTER | DT_VCENTER | DT_SINGLELINE);

EndPaint (hWnd, &ps);
return 0;
}
//----------------------------------------------------------------------
// DoDestroyMain - Process WM_DESTROY message for window.
//
LRESULT DoDestroyMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
PostQuitMessage (0);
return 0;
}

如果您浏览HelloCE的源代码,会从中看到本书中所有程序都使用的标准模板。在包含的头文件和宏定义之后是一些全局变量。我知道有很多好的建议劝说全局变量不应该出现在程序里,但我使用他们是为了便于简化本书中的例子,并使它们更条理清晰。每个程序都定义了一个Unicode字符串szAppName,它用在程序的很多地方。hInst 也同样用在很多地方,并且在详述InitInstance 过程时,我会提到它。最后那个全局结构是一个消息列表,包含处理相关消息的过程。窗口过程使用这个结构将消息及处理消息的过程关联到一起。

HelloCE中,WinMain有两各基本功能:调用InitInstance(放有应用程序初始化的代码),在消息循环中处理消息,当消息循环退出时调用TerminateInstance。在这个程序模版里,WinMain成为一个基本不用修改的例程。总的来说,WinMain唯一的改变之处是对消息循环处理过程的修改,涉及对键盘加速键的处理以及对无模式对话框消息及其他任务的监控。

实例初始化
InitInstance 的主要任务是注册主窗口的窗口类,创建应用程序主窗口,按传给WinMain的nCmdShow 参数指定的格式显示主窗口。如果是为Pocket PC编译,则还有一些条件编译代码,用来防止同一时刻运行一个程序的多个实例。

InitInstance做的第一个工作就是把程序实例句柄hInstance 保存在全局变量hInst中。程序的实例句柄在Windows应用程序的很多地方是很有用的。我之所以在这里保存这个值是因为此时已经知道实例句柄并且这是程序中保存实例句柄的一个很方便的地方。

当在Pocket PC上运行时,HelloCE用FindWindow来查看是否有自身的副本正在运行。该函数在顶层窗口中搜索,看是否有类名或窗口标题匹配或者两者都匹配的窗口。如果找到匹配的,用SetFroegroundWindow函数将窗口放到最前面,之后该例程退出,返回码为0,这将使WinMain退出,终止应用程序。我将花更多的时间在17章里讨Pocket PC相关的代码。

Pocket PC相关的代码包含在#if and #endif行里。这些行告诉编译器只有当#if语句的条件为真的时候才包含它们,在本例中,如果定义了常量WIN32_PLATFORM_PSPC,则条件为真。该常量定义在[项目设置]中。快速浏览一下[项目设置]中的 C/C++ 页,可以看到完整的关于预处理器定义的区域。在这个区域里,定义之一是$(CePlatform-Ce平台),$注册值占位符。在Key [HKEY_LOCAL_MACHINE]\Software\Microsoft\Windows CE Tools\Platform Manager 里,你可以找到一系列注册key,每个代表一个在eVC++中安装的目标平台。CePlatform(Ce平台)值取决于目标项目的不同。对Pocket PC 和老式Palm-size PC 项目,CePlatform定义为WIN32_PLATFORM_PSPC。

窗口类的注册和主窗口的创建过程与Hello3中的过程很相似。唯一的不同是使用了用做主窗口类类名的全局字符串szAppName。每次我用这个模板,我将szAppName 改成程序的名字即可。这可以使不同的应用程序窗口类名保持唯一,方便FindWindow工作。

到此InitInstance 算是完成了,应用程序主窗口已经创建和更新了,因为在进入消息循环之前,已经有消息发送给窗口的窗口过程了。现在是时候看看这部分程序了。

窗口过程
当你写Windows程序的时候,编程的大部分时间是花在窗口过程上的。窗口过程是程序的核心,也是窗口行为创建程序个性的地方。

同大部分不使用MFC等类库的Windows程序相比,我的编程风格明显不同的地方正是在窗口过程里。对于我的几乎所有程序,窗口过程都和前面HelloCE里的一样。在进一步深入之前,我重申:这种程序结构并不特别用在Windows CE中。我的所有Windows应用程序都使用这种风格,不管是Windows 3.1、Me、XP,还是CE。

这种风格将窗口构成简化成一个简单的表查找函数。主要思想是在早先定义在C文件里的MainMessages表里查找消息值。如果消息被找到,关联的过程就被调用,并把原始参数传递给处理该消息的过程。如果没有找到,调用默认过程DefWindowProc。DefWindowProc是Windows函数,为系统里所有消息提供默认行为,这使得Windows程序不用处理传递给窗口的每个消息。

消息表将消息值和处理消息的过程关联在一起。该表如下所示:
// Message dispatch table for MainWindowProc
const struct decodeUINT MainMessages[] = {
WM_PAINT, DoPaintMain,
WM_DESTROY, DoDestroyMain,
};
该表定义为常量,这不仅仅是好的编程习惯,而且因为这样可以帮助节约内存。因为Windows CE程序可以在ROM里执行,不变的数据应该标记为常量。这样允许Windows CE程序装载器将常量数据放在ROM里,而不是装载一个副本到RAM里,因此节约了宝贵的RAM。

表自身是一个简单的结构数组,该结构包含2个原素。第一项是消息值,第二项是指向处理消息的函数的指针。因为函数可以起任何名字,所以在整本书里我使用了一致的结构,好帮助您理解它们。名字由Do前缀(符合面向对象的经验),后跟一个消息名及一个用来指明与表相关的窗口类的后缀。例如DoPaintMain是为程序的主窗口处理Wm_PAINT消息的函数名。

DoPaintMain 和DoDestroyMain
HelloCE里两个消息处理例程是PaintMain 和DoDestroyMain。它们和Hello3里case子句的功能很类似。独立例程的好处是代码和本地局部变量是例程隔离的。而在Hello3的窗口过程里,针对绘画代码的局部变量则都集中在窗口过程的顶部。代码的封装使您很容易复制代码到您的下一个应用程序里。

运行HelloCE
当在eVC++中输入和编译本程序后,可以在VC++里选择 [Build]->[Execute] HelloCE.exe或者按Ctrl+F5远程执行本程序。程序在空白窗口的中间显示一行"Hello Windows CE"字样,图1-3和图1-4显示了HelloCE运行在PocketPC上的样子。点一下标题栏上的[Close]按钮会让Windwos CE给窗口发送WM_CLOSE消息。虽然HelloCE没有明确的处理WM_CLOSE消息,但DefWindowProc过程使用销毁主窗口作为默认的处理方式。因为窗口正在销毁,会发出WM_DESTORY消息,这又会导致对PostQuitMessage的调用。
图1-3(略)
运行在嵌入式Windows CE系统上的HelloCE窗口。

正象我说过的,HelloCE是一个非常基本的Windows CE程序,但它给您展示了一个应用程序基本框架,您可以在上面添加更多内容。如果您用浏览器看HelloCE.exe文件,会发现该程序使用的是通用图标。当HelloCE运行的时候,任务条上HelloCE对应的按钮里,文字旁边也没有图标。关于给程序增加定制图标以及DrawText函数是如何工作的,我将在后面几章作为两个主题来讲解。

图1-4(略)
运行在Pocket PC上的HelloCE窗口

图1-4显示了HelloCE在Pocket PC上运行时的问题。HelloCE窗口伸展到了屏幕底部。和程序间具体切换方式有关,SIP(输入法软键盘)按钮可能显示在HelloCE窗口的上面。为Pocket PC设计的应用程序会在屏幕底部创建一个菜单条,用来显示软键盘等事物的按钮会包含在上面。

必须人工调整窗口尺寸,避免覆盖菜单条或者被菜单条覆盖。稍后我们会讨论如何为Pocket PC的用户界面设计应用程序。可以确信的是:书中头几章关于Windows CE的内容一样适用于Pocket PC设备及其它Windows CE系统。

分享到:
评论

相关推荐

    lazarus-1.0.8-fpc-2.6.2-cross-arm-wince-win32

    lazarus-1.0.8-fpc-2.6.2-cross-arm-wince-win32 freepascal 用于开发WINCE程序

    .net-cf-wince-curve.rar_WINCE 曲线_WINCE 曲线_wince 曲线控件_曲线 wince_

    描述中的".net-cf-wince-curve.rar"是一个包含用于Windows CE平台的曲线绘制控件的压缩文件。该控件可能提供API和方法,使开发者能够轻松地在Wince设备上生成实时数据曲线,这对于需要实时监测和分析数据的科学仪器...

    Lazarus-0.9.28.2-fpc-2.2.4-cross-arm-wince-win32

    标题 "Lazarus-0.9.28.2-fpc-2.2.4-cross-arm-wince-win32" 暗示了一个用于开发针对Windows CE(掌上设备操作系统)应用程序的开源集成开发环境(IDE)——Lazarus的一个特定版本。Lazarus是Free Pascal编译器(FPC...

    hobd汉化版-wince

    标题 "hobd汉化版-wince" 指向的是一个专为Windows CE(Wince)操作系统汉化的HOBD软件版本。HOBD,全称是"Handy OBD-II",是一款用于汽车诊断的工具,它可以连接到车辆的OBD-II接口,读取并解析车载计算机的数据,...

    WINCE程序设计 WINCE程序设计

    《WINCE程序设计》深入解析 Windows CE(简称WinCE)是微软公司开发的一款嵌入式操作系统,主要用于掌上设备、工业控制、汽车电子、医疗设备等领域的应用。它的设计思路是将完整的Windows桌面系统精简,形成一个轻...

    C# 各种文件格式的转换 ----winCE试验版

    C# 各种文件格式的转换 ----winCE试验版 京华志&精华志出品 希望大家互相学习,互相进步 支持CSDN 支持微软 主要包括C# ASP.NET SQLDBA 源码 毕业设计 开题报告 答辩PPT等

    qt-wince安装.pdf

    首先,你需要下载适用于Windows CE的Qt源代码包,例如`qt-embedded-wince-opensource-src-4.4.0.zip`。 2. **安装Visual Studio 2005** 安装Visual Studio 2005是必要的,因为Qt的构建系统依赖于其编译器。在安装...

    qt-wince安装.docx

    - Qt的嵌入式开发包:qt-embedded-wince-opensource-src-4.4.0.zip - Microsoft Visual Studio 2005 (VS2005),用于编译和调试 - Windows Mobile 5.0 Pocket PC SDK,提供针对Windows CE的开发环境 - Microsoft ...

    3G-USB-WINCE驱动,支持华为部分无线网卡

    兼容wince5.0/6.0 以下列出的是调试通过的型号列表,仅供参考. 1. WCDMA/DSDPA: Hua Wei E180 Hua Wei E220 Hua Wei E1750(Modem:COM6,ATCMD:COM8,COM7 not use) Hua Wei E1550 Hua Wei E156G(Modem:COM6,ATCMD:...

    IDA教程-WinCE ARM调试器入门教程.pdf

    IDA教程-WinCE ARM调试器入门教程.pdf

    wince程序设计 wince程序设计 wince程序设计

    - .NET Compact Framework:微软提供的.NET框架的精简版,允许开发者使用C#或VB.NET开发WinCE应用程序,享受丰富的类库和垃圾回收机制。 - WinAPI:WinCE提供了一套与Windows桌面系统类似的API,使得移植Windows...

    VS2005-CoreCon-x86-WINCE600,wince开发软件安装包

    "VS2005-CoreCon-x86-WINCE600"这个安装包就是专门为Windows CE 6.00平台的开发设计的,它包含了构建、调试和测试嵌入式应用程序所需的工具和组件。 首先,"CoreCon"是Visual Studio 2005中的核心连接组件,它是...

    最新Qt-WinCE全解

    注意,WinCE可能不支持某些桌面版Qt的功能,所以需要查阅文档以确认兼容性。 3. **配置项目**: 配置项目文件(.pro),确保它指定了正确的Qt模块和WinCE特定的编译选项。 4. **编译和调试**: 在开发环境中编译项目,...

    wince程序设计中文版1

    wince程序设计中文影印版 积分要多了,不好意思,我也不知道怎么取消 一共三个压缩包,须全部下载了解压,只让传10m,没办法啊 part1 http://download.csdn.net/source/257557 part2 ...

    基于ARM-WinCE的电机监控系统设计.pdf

    "基于ARM-WinCE的电机监控系统设计" 本文将对基于ARM-WinCE的电机监控系统设计进行详细的介绍,包括系统设计、系统结构、硬件电路设计、软件设计和测试过程等方面。 系统设计 基于ARM-WinCE的电机监控系统设计是...

    Image-update--WinCE-6.0.rar_gk7000_update WINCE_wince 6.0

    标题中的“Image-update--WinCE-6.0.rar_gk7000_update WINCE_wince 6.0”指的是一个针对Windows CE 6.0操作系统进行更新的镜像文件,该更新是针对名为“gk7000”的特定硬件平台设计的。在Windows CE系统中,"image...

    博创2410开发板光盘资料----WINCE实验指导书

    - **实验目的**: 掌握使用MFC框架开发WinCE应用程序的方法。 - **实验内容**: - 设计简单的用户界面。 - 实现基本的应用逻辑。 - 测试应用程序的功能。 #### 4.3 基于WINCEDIRECTSHOW的多媒体播放机实验 - **...

    wince程序设计教程

    本教程将深入探讨Wince程序设计的基础与高级特性,帮助初学者快速掌握这一领域的核心技能。 一、Windows CE概述 Windows CE是一个可裁剪、实时的、32位的操作系统,其设计目标是满足小型设备的特定需求。它提供了...

    STL-WInCE 标准模板库EVC

    EVC(Embedded Visual C++)是微软为开发WinCE应用程序提供的集成开发环境。 STL-WinCE是针对Windows CE平台定制的STL版本,它允许开发者在WinCE系统中使用如向量(vector)、列表(list)、映射(map)、集合(set...

    S3C2442-WINCE 5.0 BSP包

    《S3C2442-WINCE 5.0 BSP包详解》 S3C2442-WINCE 5.0 BSP(板级支持包)是针对三星S3C2442处理器在Windows CE 5.0操作系统上的关键组件集合,它为开发者提供了构建嵌入式系统的基础设施。这个包包含了对多种硬件...

Global site tag (gtag.js) - Google Analytics