实践开发
  1、开发实例准备

  鉴于本篇的定位,本文的例子是一个很简单的程序,运行后,程序主窗口会显示一行欢迎信息;程序底部会有两个菜单,一个是"关于",一个是"选项","选项"是一个弹出式菜单,上面有两个菜单项"关于"和"退出"。

  执行"关于"菜单会显示一个标准的信息对话框;执行"退出"菜单,会首先显示一个消息提示窗口,提醒你是否确认要退出,你可以选择"确定"退出本程序,也可以选择"取消"返回到程序的主界面。

  下面是软件执行时的情况:

200592192041819.jpg

  2、第一步:建立通用框架

  因为Smartphone不支持MFC,因此,我们需要建立一个基于Windows CE API的编程框架,有过桌面开发或者Pocket PC开发经验的人会很清楚这个过程,包括注册窗口类、实例初始化、消息循环及窗口过程回调处理等,在Smartphone上也是一样的。

  1) 打开eMbedded C++ 4.0 ,File -> New ,建立一个Smartphone 2003 工程:

200592192041234.jpg

  注意,选择了WCE ARMV4 和WCE emulator 使我们可以编译在模拟器和真实设备运行的程序。

  点击OK按钮进入下一步。

  2) 选择建立一个空的工程。

200592192041765.gif

  确认后此工程被建立。

  这里之所以不使用系统的标准框架是因为标准框架采用的是老式的消息处理方案,使用了很多的switch 语句来处理消息,不够灵活,也不方便程序的扩展,因此,这里从一个空的工程开始,仿照MFC消息映射的做法来构建一个结构良好,代码优美的框架,作为我们开发smartphone程序的基础。

  3、选择File->New新建一个C++源文件First.cpp和C++头文件First.h,并同时加入First工程。

  4、编写文件First.h和First.cpp如下,文件很短,关键的地方已经使用红色标注出来了,如果你有兴趣,可手工敲入下面的代码,以加深你对这个基本过程的了解。

//===============================================================
// first.h 文件

// 避免头文件的重复包含
#ifndef _CHUYUNFENG_FIRST_H_
#define _CHUYUNFENG_FIRST_H_

// 计算需要处理的消息数目
#define MSG_NUM(x) (sizeof(x) / sizeof(x[0]))

// 整个程序的消息映射结构
typedef struct tagMSG_MAP_MAIN
{
UINT nMsg;
LRESULT (*pMsgProcess)(HWND, UINT, WPARAM, LPARAM);

}MSG_MAP_MAIN_S;

// 命令消息(WM_COMMAND)的消息映射结构,因为两者处理函数
// 的参数不同,调用场合也不同,因此这里需要单独建立,类似的有
// WM_NOTOFY消息,本程序中不涉及
typedef struct tagMSG_MAP_CMD
{
UINT nMsg;
LRESULT (*pMsgProcess)(HWND, WORD, HWND, WORD);

}MSG_MAP_CMD_S;

// 声明程序中用到的全局变量
extern const TCHAR g_szAppName[];
extern HINSTANCE g_hInstance;
extern HWND g_hMainWnd;
extern const MSG_MAP_MAIN_S g_mainMsg[];
extern const MSG_MAP_CMD_S g_cmdMsg[];

// 窗口处理函数原型
LRESULT CALLBACK mainWndProc(HWND, UINT, WPARAM, LPARAM);

// 需要处理的主框架消息定义函数
LRESULT onCreate(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
LRESULT onPaint(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
LRESULT onCommand(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
LRESULT onDestroy(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);

// 需要处理的菜单命令消息定义函数
LRESULT onAbout(HWND hWnd, WORD idItem, HWND hwndCtl,WORD wNotifyCode);
LRESULT onExit(HWND hWnd, WORD idItem, HWND hwndCtl,WORD wNotifyCode);

#endif //_CHUYUNFENG_FIRST_H_

//=================================================================
// First.cpp 文件

#include
#include
#include
#include "resource.h"

#include "First.h"

// 定义程序中用到的全局变量
const TCHAR g_szAppName[] = _T("First");
HINSTANCE g_hInstance;
HWND g_hMainWnd;

// 程序中需要处理的消息映射,如果要增加,在此处增加一
// 对{msgID,onMsgProcFun},然后写对应的消息处理函数即可。
const MSG_MAP_MAIN_S g_mainMsg[] =
{
{WM_PAINT, onPaint},
{WM_COMMAND, onCommand},
{WM_CREATE, onCreate},
{WM_DESTROY, onDestroy}
};

//此处放置需要处理的命令消息
const MSG_MAP_CMD_S g_cmdMsg[] =
{
{IDM_ABOUT, onAbout},
{IDM_EXIT,onExit}
};

//=================================================================
// WinMain,入口函数,由操作系统调用
//=================================================================
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow)
{
WNDCLASS wc;
MSG msg;

// 注册窗口类
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 = g_szAppName; //窗口类的名字

if ( 0 == RegisterClass (&wc))
return 0; //注册窗口类失败

// 建立并显示程序主窗口
g_hInstance = hInstance;
g_hMainWnd = CreateWindow (g_szAppName, // 窗口类
_T("第一个演示程序"), //窗口标题
WS_VISIBLE, //样式
CW_USEDEFAULT, // x坐标
CW_USEDEFAULT, // y 坐标
CW_USEDEFAULT, // 初始宽度
CW_USEDEFAULT, // 初始高度
NULL, // 父窗口
NULL, //菜单,必须为NULL,WINCE窗口不支持菜单。
hInstance, // 实例
NULL); //建立参数的指针,用于WM_CRATE消息期间。

if ( !IsWindow (g_hMainWnd)) //建立窗口失败
return 0;

ShowWindow (g_hMainWnd, nCmdShow);
UpdateWindow (g_hMainWnd);

// 消息循环
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}

// WinMain函数成功则返回退出消息的wParam
return msg.wParam;
}

//======================================================================
// MainWndProc,窗口过程,回调函数,由操作系统调用
//======================================================================
LRESULT CALLBACK mainWndProc (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
// 处理我们需要处理的消息
int i;
for (i = 0; i < MSG_NUM(g_mainMsg); i++)
{
if (wMsg == g_mainMsg[i].nMsg)
return (*g_mainMsg[i].pMsgProcess)(hWnd, wMsg, wParam, lParam);
}

// 有编写对应的函数则调用默认的
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}

//=================================================================
// onCreate,WM_CREATE 消息的处理函数
//=================================================================
LRESULT onCreate(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
SHMENUBARINFO mbi;

// 初始化menubar结构
memset(&mbi, 0, sizeof(SHMENUBARINFO));
mbi.cbSize = sizeof(SHMENUBARINFO); // 必须填充
mbi.hwndParent = hWnd;
mbi.nToolBarId = IDR_MAIN_MENUBAR;
mbi.hInstRes = g_hInstance;

// 建立menubar控制
if (!SHCreateMenuBar(&mbi))
{
MessageBox (hWnd, _T("建立menubar失败"),
g_szAppName, MB_OK);
DestroyWindow(hWnd);
}

//
return 0;
}

//=================================================================
// onPaint,WM_PAINT 消息的处理函数
//=================================================================
LRESULT onPaint(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;

RECT rtClient;
GetClientRect (hWnd, &rtClient);

// 开始绘图
hdc = BeginPaint (hWnd, &ps);

// 在屏幕中间写一句话
DrawText (hdc, _T("Smartphone第一个程序^_^"), -1,
&rtClient, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

// 结束绘图
EndPaint (hWnd, &ps);

return 0;
}

//=================================================================
// onCommand,WM_COMMAND 消息的处理函数
//=================================================================
LRESULT onCommand(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
//处理我们需要处理的命令消息
WORD wID, wNotifyCode;
HWND hwndCtl;
int i;

// 解析出参数
wID = (WORD) LOWORD (wParam);
wNotifyCode = (WORD) HIWORD (wParam);
hwndCtl = (HWND) lParam;

// 寻找消息映射结构,调用对应的消息处理函数
for (i = 0; i < MSG_NUM(g_cmdMsg); i++)
{
if (wID == g_cmdMsg[i].nMsg)
return (*g_cmdMsg[i].pMsgProcess)( hWnd, wID, hwndCtl,wNotifyCode);
}
return 0;
}

//=================================================================
// onDestroy,WM_DESTROY 消息的处理函数
//=================================================================
LRESULT onDestroy (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
DestroyWindow(hWnd);
return 0;
}

//=================================================================
// onAbout,菜单消息IDM_ABOUT处理函数
//=================================================================
LRESULT onAbout(HWND hWnd, WORD idItem, HWND hwndCtl,WORD wNotifyCode)
{
TCHAR szAboutMsg[] = _T(" First for smartphone 2003");
MessageBox(hWnd,szAboutMsg,_T("关于First"),MB_OK);
return 0;
}

//=================================================================
// onExit,菜单消息IDM_Exit处理函数
//=================================================================
LRESULT onExit(HWND hWnd, WORD idItem, HWND hwndCtl,WORD wNotifyCode)
{
if ( IDOK == MessageBox(hWnd, _T("真的要退出这个程序?"),
_T("退出确认"),MB_OKCANCEL | MB_ICONASTERISK) )
{
PostQuitMessage(0);
}

return 0;
}

  关键代码分析:

  代码中最关键的地方就是使用消息映射的办法来处理消息,这主要体现在定义消息映射结构和在窗口处理函数以及命令消息处理函数中进行消息分发上面,实现可以参看代码中的红色部分。

  5) 在框架上的开发。

  我们构建这个基本框架,是想使用这个框架进行后续开发的,上述代码中的绿色部分标示出了增加WM_PAINT消息处理的整个过程:

  1、 在.h文件中声明消息处理函数;

  2、 在.c文件的消息映射结构中增加一个消息映射对;

  3、 然后,在.c文件中实现此函数的功能即可。

  3、第二步:建立菜单

  现在,我们来建立左右软键对应的菜单。

  1) 确认使用中文资源

  因为要使用资源,因此,首先确认我们项目所使用的是中文资源:选择菜单项 Project ->Settings…,设置资源为中文:

200592192042971.jpg

  2) 增加resource script文件并修改Evc的一个bugs

  菜单File -> new ->增加一个resource script文件,名字为first.rc。

200592192042574.jpg

  当你在IDE中打开这个RC文件时,会发现一个错误,这是eMbedded C++处理smartphone上的一个bugs,微软对此的修正方案是,提供了一个newRes.h的文件,你将First.rc中的#include "afxres.h"修改为 #include "newRes.h"即可,newRes.h文件你可以自行在程序目录下建立,下面是newRes.h文件内容:

#ifndef __NEWRES_H__
#define __NEWRES_H__

#if !defined(UNDER_CE)
#define UNDER_CE _WIN32_WCE
#endif

#if defined(_WIN32_WCE)
#if !defined(WCEOLE_ENABLE_DIALOGEX)
#define DIALOGEX DIALOG DISCARDABLE
#endif
#include
#define SHMENUBAR RCDATA
#if defined(WIN32_PLATFORM_WFSP) && (_WIN32_WCE >= 300)
#include
#define AFXCE_IDR_SCRATCH_SHMENU 28700
#else
#define I_IMAGENONE (-2)
#define NOMENU 0xFFFF
#define IDS_SHNEW 1

#define IDM_SHAREDNEW 10
#define IDM_SHAREDNEWDEFAULT 11
#endif // _WIN32_WCE_PSPC
#define AFXCE_IDD_SAVEMODIFIEDDLG 28701
#endif // _WIN32_WCE

#ifdef RC_INVOKED
#ifndef _INC_WINDOWS
#define _INC_WINDOWS
#include "winuser.h" // extract from windows header
#include "winver.h"
#endif
#endif

#ifdef IDC_STATIC
#undef IDC_STATIC
#endif
#define IDC_STATIC (-1)

#endif //__NEWRES_H__

  3、 增加menubar资源:

类型 ID Caption
Menubar IDR_MAIN_MENUBAR
Left menu IDM_ABOUT 关于
Right menu IDM_OPTION 选项
Right menu subitem 1 IDM_ABOUT 关于(和左建菜单是同一个ID)
Right menu subitem 2 IDM_EXIT 退出

  这是first.rc的内容,大家可以看到,与我们桌面windows下的资源脚本文件相差无几。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10294527/viewspace-126870/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10294527/viewspace-126870/

智能手机Smartphone开发从零起步(五)(转)相关推荐

  1. 智能手机Smartphone开发从零起步(四)(转)

    一些基本概念 因为在上面叙述中涉及了一些Smartphone的基本概念,作为入门的文章,下面,我对涉及到的一些概念进行解释. 1) Platform Manage 在安装Microsoft eMbed ...

  2. Window Mobile SmartPhone智能手机软件开发vs2005 简体中文版 设置指南!

    转自:http://blog.csdn.net/laotuguai/archive/2006/09/04/1175070.aspx 上次更新了英文版本vs2005的抓图,因为还是很多朋友加我qq咨询问 ...

  3. 五节课从零起步(无需数学和Python基础)编码实现AI人工智能框架电子书V1

    五节课从零起步  (无需数学和Python 基础)  编码实现AI 人工智能框架          王  家  林        2018/4/15                          ...

  4. Microsoft 智能手机(Smartphone)C#开发入门

    Microsoft 智能手机(Smartphone)C#开发入门 原文地址:http://www.codeproject.com/KB/mobile/SmartphoneIntroCSharp.asp ...

  5. Window Mobile SmartPhone智能手机软件开发入门篇!

    如果你采购了smartphone手机,并且是windows mobile操作系统,那么就一定要试试开发自己的软件,自己玩. 本文就是讲述如何用vs.net 2003 开发windows mobile ...

  6. 嵌入式系统开发学习如何起步、如何深入?(转)

    学习有捷径吗?俺认为是有的,正确的道路就是捷径. 就好象是爬山,如果有导游图,那就能找到一条最正确的路线:如果没有导游图,自己瞎琢磨,东问西问,也未必能找到最佳的路线. 有时候回首前尘,会谓叹,要是当 ...

  7. SAP UI5 应用开发教程之五十五 - 如何将本地 SAP UI5 应用通过 Node.js Express 部署到公网上试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  8. SAP UI5 应用开发教程之四十五 - 如何在 SAP UI5 应用里使用 jQuery 和原生的 DOM API

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  9. SAP UI5 应用开发教程之三十五 - 如何把本地开发的 SAP UI5 应用部署到 ABAP 服务器上试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

最新文章

  1. 最近发现的一些Python写程序的小技巧
  2. python任务调度框架_python任务调度框架apscheduler【转】
  3. Redis 到底是怎么实现“附近的人”这个功能的?
  4. “华为杯”中国矿业大学程序设计学科竞赛
  5. 旋钮编码器c代码_人脸合成效果媲美StyleGAN,而它是个自编码器
  6. 基于plotly数据可视化_[Plotly + Datashader]可视化大型地理空间数据集
  7. C#string与char互转
  8. 【错误记录】Ubuntu 编译 ffmpeg 报错 ( nasm/yasm not found or too old. Use --disable-x86asm for a crippled bu )
  9. 黑客泄露澳大利亚大量求职者信息,其中包含11家重要公司名单
  10. B - Silly Mistake set +思维
  11. Android距离传感器
  12. 【阅读源码系列】ThreadPoolExecutor源码
  13. 【今日分享】官方实例用python调用OpenAI tahcTPG的APIkey生成智能问答
  14. 1.Matlab 画图输出 EPS 格式文件中文出现乱码
  15. 2022-2028全球药品泡罩包装机行业调研及趋势分析报告
  16. 芯片的设计流程和流片成本
  17. Windows 10 多用户同时远程登录
  18. c语言中如何求双胞胎素数,征求好的算法:输出十万以内的双胞胎素数
  19. 百度网站抓取诊断自动提交工具
  20. 【寒假每日一题】AcWing 4510. 寻宝!大冒险!

热门文章

  1. python翻页_如何用python tkiner实现图片翻页功能
  2. 区块链产业生态发展情况-美国区块链产业生态发展
  3. vue element-ui select 多选验证不通过问题处理
  4. 如何写邮件 细节决定成败
  5. OpenSSL3.0.1中SM4算法分析
  6. 企业为什么要做CCRC认证?都有哪些好处?
  7. 使用Umami自建网站流量统计
  8. java 访问 domino_Java远程访问Domino数据库
  9. 中软实习培训记录二(0721)
  10. Coaxial Light vs Ring Light on Reflective Surfaces