eMbedded VC++入门

 

 

 

 

 

你好晕倒的蜥蜴!

任何一个学过编程的朋友都对HELLO不会陌生,但这次的这个和以前的不太一样,它是一个特别的程序,不是在功能上,是在思想上。

这是一个非常经典的程序,本不想列出这个程序,但这是WINCE编程的典型框架,写出它可以让我们对WINCE的程序有一个很直观的认识。还有一个重要的原因是,这个例子程序给出了一个新的代码风格,和以前的WIN32程序有所不同,我十分欣赏这种代码的或者说程序结构,因此便再一次将这个程序写出。不过我做了一些小小的变动。主要的目的:

l         了解WINCE程序的结构和原理。

l         欣赏并学习一种非常优美的代码风格。

l         了解使用EVC编写WINCE程序的方法(介绍IDE)。

 

打开eMbedded VC++选择新建。

 

怎么样界面和VC6差不多吧。我们选择WCE Pocket PC 2002 Application,在项目名称处输入HelloCE,检查CPUS是否选中了ARMX86。这个应该根据你的开发环境有所不同。就我而言,首先要在PC机上进行调试,然后编译成适合我使的应用程序,我的PPCARM CPU所以我需要WCE X86WCE ARM,至于其它的例如MIPSSH我并没有考虑。(如果你要开发商用软件或者想让更多的人使用你的程序,你应该考虑更多种类的CPU。)好进行下一步:

 

我们选择一个空的项目。单击完成。好了我们看到EVC已经为我们建立了一个应用程序框架,当然在这个例子,它是空的。不过我们也可以在目录下找到下图显示的几个文件。

好我们向我们的项目中添加一个头文件HelloCE.h和一个HelloCE.c文件。它们被我列在下面:你可以直接拷贝,不过需要注意一些讨厌的格式(例如空格)造成的编译错误。不过最好的办法是手工的输入,它们并不算长。

//======================================================================

// Header filehelloce.h

//======================================================================

// 返回元素的数量,主要用于搜索消息列表

#define dim(x) (sizeof(x) / sizeof(x[0]))

//----------------------------------------------------------------------

//数据类型定义

//

struct decodeUINT {                            //消息和消息函数的关联结构

    UINT Code;

    LRESULT (*Fxn)(HWND, UINT, WPARAM, LPARAM); //这里用到了函数指针

};

struct decodeCMD {                             //菜单和处理函数的关联结构

    UINT Code;                                 

    LRESULT (*Fxn)(HWND, WORD, HWND, WORD); //这里用到了函数指针

};

 

//----------------------------------------------------------------------

#define  IDC_CMDBAR 1                          // 命令条ID

 

//----------------------------------------------------------------------

// 函数原型

//

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 DoHibernateMain (HWND, UINT, WPARAM, LPARAM);

LRESULT DoActivateMain (HWND, UINT, WPARAM, LPARAM);

LRESULT DoDestroyMain (HWND, UINT, WPARAM, LPARAM);

 

 

//======================================================================

// HelloCE – helloce.c

//======================================================================

#include <windows.h>                

#include <commctrl.h>

#include "helloce.h"

//----------------------------------------------------------------------

// 全局数据

//

const TCHAR szAppName[] = TEXT ("HelloCE");

HINSTANCE hInst;                     // 程序的实例句柄

//主窗口过程函数的消息映射表用到decodeUINT结构

const struct decodeUINT MainMessages[] = {

    WM_CREATE, DoCreateMain,

    WM_PAINT, DoPaintMain,

    WM_HIBERNATE, DoHibernateMain,

    WM_ACTIVATE, DoActivateMain,

    WM_DESTROY, DoDestroyMain,

};

 

//======================================================================

// 程序的入口

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

                    LPWSTR lpCmdLine, int nCmdShow) {

    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)) {

        TranslateMessage (&msg);

        DispatchMessage (&msg);

    }

    //实例清除

    return TermInstance (hInstance, msg.wParam);

}

//----------------------------------------------------------------------

// 应用程序初始化函数

//

int InitApp (HINSTANCE hInstance) {

    WNDCLASS wc;

    //注册应用程序的主窗口类

    wc.style = 0;                             // 窗口样式

    wc.lpfnWndProc = MainWndProc;             // 回调函数

    wc.cbClsExtra = 0;                        // 扩展的类数据

    wc.cbWndExtra = 0;                        // 扩展的窗口数据

    wc.hInstance = hInstance;                 //实例句柄

    wc.hIcon = NULL,                          // 图标

    wc.hCursor = NULL;                        // 鼠标

    wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);

    wc.lpszMenuName =  NULL;                  //菜单

    wc.lpszClassName = szAppName;             //窗口类的名字

 

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

 

    return 0;

}

//----------------------------------------------------------------------

//初始化实例

//

HWND InitInstance (HINSTANCE hInstance, LPWSTR lpCmdLine,

                   int nCmdShow) {

    HWND hWnd;

    // 存储程序实例句柄到全局变量

    hInst = hInstance;

    // 建立主窗口

    hWnd = CreateWindow (szAppName,           // 窗口类

                         TEXT("你好蜥蜴"),       //窗口标题

                         WS_VISIBLE,          //样式

                         CW_USEDEFAULT,       // x坐标

                         CW_USEDEFAULT,       // y 坐标

                         CW_USEDEFAULT,       // 初始宽度

                         CW_USEDEFAULT,       // 初始高度

                         NULL,                // 父窗口

                         NULL,                //菜单,必须为NULLWINCE窗口不支持菜单。

                         hInstance,           // 实例

                         NULL);               //建立参数的指针,用于WM_CRATE消息期间。

    // 如果不能建立主窗口返回失败

    if (!IsWindow (hWnd)) return 0;

    // 显示和更新窗口函数

    ShowWindow (hWnd, nCmdShow);

    UpdateWindow (hWnd);

    return hWnd;

}

//----------------------------------------------------------------------

// TermInstance –程序清除

//

int TermInstance (HINSTANCE hInstance, int nDefRC) {

 

    return nDefRC;

}

//======================================================================

// 下面是主窗口的消息处理函数

//

//----------------------------------------------------------------------

// MainWndProc – 主过程函数,这是一个回调函数

//

LRESULT CALLBACK MainWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,

                              LPARAM lParam) {

    INT i;

    //搜索消息列表,如果编写了对应的函数来处理这个消息则调用这个函数

    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);  //没有编写对应的函数则调用默认的

}

//----------------------------------------------------------------------

// DoCreateMain – 处理窗口建立(WM_CREATE)消息的函数.

//

LRESULT DoCreateMain (HWND hWnd, UINT wMsg, WPARAM wParam,

                      LPARAM lParam) {

    HWND hwndCB;

    // 建立命令条.

    hwndCB = CommandBar_Create (hInst, hWnd, IDC_CMDBAR);

    // 添加退出按钮到命令条上

    CommandBar_AddAdornments (hwndCB, 0, 0);

    return 0;

}

//----------------------------------------------------------------------

// DoPaintMain – 处理窗口重画(WM_PAINT)消息的函数

//

LRESULT DoPaintMain (HWND hWnd, UINT wMsg, WPARAM wParam,

                     LPARAM lParam) {

    PAINTSTRUCT ps;

    RECT rect;

    HDC hdc;

    // 调整客户区域的大小并考虑命令条的高度

    GetClientRect (hWnd, &rect);

    rect.top += CommandBar_Height (GetDlgItem (hWnd, IDC_CMDBAR));

    hdc = BeginPaint (hWnd, &ps);

    DrawText (hdc, TEXT ("你好晕倒的蜥蜴!"), -1, &rect,  //被改成了中文

              DT_CENTER | DT_VCENTER | DT_SINGLELINE);

    EndPaint (hWnd, &ps);

    return 0;

}

//----------------------------------------------------------------------

// DoHibernateMain – 处理窗口挂起消息(WM_HIBERNATE)的函数,这是WINCE独有的消息,目的//是将内存的使用量将到最小.

//

LRESULT DoHibernateMain (HWND hWnd, UINT wMsg, WPARAM wParam,

                         LPARAM lParam) {

    // 如果窗口不是活动的,则取消命令条,释放内存

    if (GetActiveWindow () != hWnd)

        CommandBar_Destroy (GetDlgItem (hWnd, IDC_CMDBAR));

    return 0;

}

//----------------------------------------------------------------------

// DoActivateMain – 处理窗口激活(WM_ACTIVATE)消息的函数

//

LRESULT DoActivateMain (HWND hWnd, UINT wMsg, WPARAM wParam,

                        LPARAM lParam) {

    HWND hwndCB;

    // 如果窗口正处在活动状态而没有命令条则建立它

    if ((LOWORD (wParam) != WA_INACTIVE) &&

        (GetDlgItem (hWnd, IDC_CMDBAR) == 0)) {

        // 建立命令条

        hwndCB = CommandBar_Create (hInst, hWnd, IDC_CMDBAR);

        // 添加退出按钮到命令条

        CommandBar_AddAdornments (hwndCB, 0, 0);

    }

    return 0;

}

//----------------------------------------------------------------------

// DoDestroyMain – 处理窗口销毁(WM_DESTROY)消息函数.

//

LRESULT DoDestroyMain (HWND hWnd, UINT wMsg, WPARAM wParam,

                       LPARAM lParam) {

    PostQuitMessage (0);

    return 0;

}

 

 

在编译程序之前还需要做一些工作,当然这不是完全必须的,它是需要根据你的开发环境来进行的一系列设置工作,我的环境是,我需要编译Pocket PC 2002下的,而且是中文的环境,因为我装了Pocket PC 2002 SDK的中文IMAGE。因此首先我需要改变Download directory,因为中文的默认目录已经不是/Windows/Start Menu,我个人习惯改为My Documents,当然你也可以设成其他的你愿意的目录,不过要注意的是如果不使用/Windows/Start Menu(默认的目录)你需要通过资源管理器来运行它。

另外一个需要修改的地方是修改Project Setings对话框的资源选项卡,将语言选项设为中文。如下图:

 

好了编译执行,我们便完成了第一个WINCE程序,当我把它装到我的568上时,运行成功后,心情和第一次编程序调试通过的感觉一样。不过真正的收获不再此,虽然这是一个非常简单的程序,但是我们可以学到一些好的编程思路。下面才是真正的开始,我们来“解剖”一下这个简单的程序。

 

收获一:全部程序代码均依照匈牙利命名法,我们几乎不用看注释便可以知道代码的作用。

收获二:改变了我们一直使用的窗口过程函数用大量的Switch语句来分列窗口消息的方法。而采用把窗口过程分解成单个过程,每个过程处理一个特定的消息,余下的窗口过程是一个代码片段,这段代码用来检查是否编写了对应的过程来处理消息,如果有就调用该过程,没有则将消息传递给默认的窗口过程。这种结构的优势是将消息处理分成独立的块,一是避免了所有的窗口过程的变量都混杂的出现在过程的顶部;二是便于理解,我们可以很清楚的理解处理特定消息的代码,最重要的是这样的结构便于代码移植,每一个独立的消息处理函数如果需要,都可以几乎不用修改而直接拷贝过去用。我记不清在那里看到过,如果一段代码的功能有可能被重复使用超过三次,便应该将它进行封装。函数也许是封装代码的最小形式。收获三:从头文件的消息句柄、结构定义和程序文件的全局消息映射,主窗口过程函数的消息映射表我们可以看到和一个简单的框架,也许通过这些我们对MFC的消息映射机制理解有所帮助。

 

好了这次我们看了一个非常简单的,但是我认为是非常优美的WINCE应用程序代码(好的代码读起来也是享受)。并且掌握了用eMbedded VC++编写应用程序的一般步骤。很有收获吧,不过我们还有很多的东西要学,别松劲,继续努力吧,你和我都是。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值