标 题: 【原创】WIN MOBILE UI开发入门
作 者: 打小
时 间: 2009-06-06,12:17:14
链 接: http://bbs.pediy.com/showthread.php?t=90857
这是我昨天发在新人交流版块的帖子,还是放到这边比较合适。嫌麻烦,没有叫版主转移,我自己拷贝过来咯。。。。
首先感谢 『嵌入式平台安全』版块版主加百力的邀请(貌似算不上邀请,表达不好,Whatever),才有了这篇文章的诞生,
在下才识有限,接触WIN MOBILE开发时间不久,仓促整理了一些UI部分入门级的东东(内容并不系统,全面),希望能够对刚涉足MOBILE开发的朋友有帮助。         
注:由于自身局限,本文不涉及.net  
OK,废话完毕,欢迎鸡蛋和鲜花。
本文假设您已经了解SMART PHONE与POCKET PC的区别。没有特别说明,均指在POCKET PC上。
现状:IPHONE的风靡,引领了当前智能手机的系统及APP界面潮流。MS虽然发布了WINDOWS MOBILE 6.5,但在将来不短的 一段时间内,承载MOBILE 6.2及以下系统的PPC仍将是主流。手持设备的特殊性决定了其上APP界面表现的重要性,很多时候甚至项目70%的代码 都与界面有关。
一。GDI绘图基础(必须掌握的基础)
1.1  设备环境DC
“设备环境”(device context),经常简称写为DC, 是Windows 用来管理访问显示和打印设备的工具。
1)  什么是DC
一个DC是一个结构,它定义了一系列图形对象的集合以及它们相关的属性,以及影响输出效果的一些图形模式。
这些图形对象包括一个画线的笔,一个填充和painting的画刷,一个用来向屏幕拷贝的位图,一个定义了一系列颜色集合的调色板,一个用来剪裁等操作的区域。
例如:使用TextOut,DC的属性确定了文字的颜色、文字的背景色、显示文字时字体等等。
如何理解DC:
DC用于绘图输出,输出设备包括屏幕,打印机等,在WM中一般总是屏幕输出,总是与特定窗体相关。实际上是GDI内部保存的数据结构, DC中的有些值定义了GDI绘图函数工作的细节。
2)  获取设备DC
一个应用程序从不直接地访问(access)dc,常见的取得dc的方式:
HDC GetDC( HWND hWnd);
HDC GetWindowDC( HWND hWnd);
HDC GetDCEx( HWND hWnd, HRGN hrgnClip,DWORD flags);
Value   Description
DCX_WINDOW   返回与窗口矩形而不是与客户矩形相对应的设备上下文环境
DCX_CACHE   从高速缓存而不是从OWNDC或CLASSDC窗口中返回设备上下文环境。覆盖CS_OWNDC和CS_CLASSDC。
DCX_PARENTCLIP(*)   使用父窗口的可见区域,父窗口的WS_CIPCHILDREN和CS_PARENTDC风格被忽略,并把设备上下文环境的原点,设在由hWnd所标识的窗口的左上角。
DCX_CLIPSIBLINGS   排除hWnd参数所标识窗口上的所有子窗口的可见区域。
DCX_CLIPCHILDREN   排除hWnd参数所标识窗口上的所有子窗口的可见区域。
DCX_NORESETATTRS(*)   当设备上下文环境被释放时,并不重置该设备上下文环境的特性为缺省特性。
DCX_EXCLUDERGN   从返回设备上下文环境的可见区域中排除由hrgnClip指定的剪切区域。
DCX_EXCLUDEUPDATE(*)   排除窗口更新区域.
DCX_INTERSECTRGN   The clipping region identified by hrgnClip is intersected with the visible region of the returned device context.
DCX_INTERSECTUPDATE   Returns a region that includes the window's update region
DCX_VALIDATE(*)   当与DCX_INTERSECTUPDATE一起指定时,致使设备上下文环境完全有效,该函数与 DCX_INTERSECTUPDATE和DCX_VALIDATE一起使用时与使用BeginPaint函数相同。.
1.2  有效区和无效区
Windows内部为每个窗口保存一个「绘图信息结构」,这个结构包含了包围无效区域的最小矩形的坐标以及其它信息,这个矩形就叫做「无效矩形」,或者「无效区域」。当重绘窗口时(收到WM_PAINT消息),仅需重绘「无效区域」就可以 。
窗体收到WM_PAINT消息,
BeginPaint获取无效区域的dc,计算无效区域,
重绘无效区域,
EndPaint函数,将无效区域标记为有效区域。
Windows不会将多个WM_PAINT消息都放在消息队列中。WM_PAINT只会更新无效区域内信息。在处理WM_PAINT消息后,整个程序界面都变为有效区域,如果不对程序进行任何操作,它是不会产生无效区域的。引起WM_PAINT消息的事件:
用户移动窗口时,先前被覆盖的窗口显示时;
用户调整窗口大小
使用ScrollDC等函数滚动窗口时
用户模块发送WM_PAINT消息(一般在InvaladataRECT 之后发送消息)
WM_PAINT
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, g_szMessage, -1,   &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint (hwnd, &ps);
}
break;
将有效区域标记为无效区域
BOOL InvalidateRect( HWND   hWnd,const RECT *lpRect, BOOL  bErase);
InvalidateRect只是增加重绘区域,在下次WM_PAINT的时候才生效 。使无效区域立刻重绘:
InvalidateRect(…);
hWnd窗体发出WM_PAINT的消息,
lpRect:是指定要刷新的区域,此区域外的区域 不被重绘,这样防止一个局部的改动,而导致整个客户区域重绘而导致闪烁。     
BOOL  bErase的参数TRUE表示在无效区域重绘之前之前还向窗体发送WM_ERASEBKGND消息,这样将导致,用背景色将所选区域覆盖一次后再重绘,(背景色可通过设置BRUSH来改变)。
将无效区域标记为有效区域
可以通过呼叫ValidateRect函数使显示区域内的任意矩形区域变为有效。如果这呼叫具有令整个无效区域变为有效的效果,则目前队列中的任何 WM_PAINT消息都将被删除。
windows不会将多个WM_PAINT消息都放在消息队列中。
1.3  位图
BMP(Bitmap-File)图形文件是Windows采用的 图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格 式。Windows系统内部各图像绘制操作都是以BMP为基础的。 Windows 3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP图象 文件格式称为设备相关位图DDB(device-dependent bitmap)文件格式。Windows 3.0以后的BMP图象文件与显示设备无 关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independent bitmap)格式(注:Windows 3.0以 后,在系统中仍然存在DDB位图,象BitBlt()这种函数就是基于DDB位图的,只不过如果你想将图像以BMP格式保存到磁盘文件中时,微软 极力推 荐你以DIB格式保存),目的是为了让Windows能够在任何类型的显示设备上显示所存储的图象。BMP位图文件默认的文件扩展名是BMP或 者 bmp(有时它也会以.DIB或.RLE作扩展名)。
文件结构:
位图文件可看成由4个部分组成:位图文件头(bitmap-file header)、位图信息头(bitmap- information header)、彩色表(color table)和定义位图的字节阵列,它具有如下所示的形式。
位图文件的组成                     结构名称               符号
位图文件头(bitmap-file header)   BITMAPFILEHEADER       bmfh
位图信息头(information header)   BITMAPINFOHEADER       bmih
彩色表(color table)              RGBQUAD                aColors[]
图象数据阵列字节                 BYTE                   aBitmapBits[]
二:常用绘图技巧
2.1 双缓冲绘制技术:
限于手机的硬件性能,开发者经常需要解决屏幕闪烁的问题,一般都可以通过双缓冲绘制来解决。
所谓的双缓冲就是把所有内容先绘制在一个内存DC上; 之后一次性拷到屏幕DC,作为最终显示。 
内存DC,是一个虚拟的内存设备上下文,对它进行绘图等操作,不会显示在屏幕上,在内存DC绘制完成之后,再拷贝到屏幕上,这样可以避免因为操作而给屏幕带来的闪烁。
步骤:
HDC memdc = CreateCompatibleDC(hdc);//创建和目的DC一致的内DC
HBITMAP  hbmp;
hbmp= CreateCompatibleBitmap(hdc,rect.Width(),rect.Height());
SelectObject(memdc,bmp);    //创建一张屏幕DC的位图并选入内存DC
Drawmemdc (memdc) ;       //在内存DC绘图
BitBlt(hdc,0,0,rect.right,rect.bottom,memdc,0,0,SRCCOPY);//绘制到屏幕DC
DeleteObject(memdc);       //销毁资源,释放内存DC
2。2图像半透明混合:
原理:操作像素点阵,假设一幅图象是A,另一幅透明的图象是B,那么透过B去看A,看上去的图象C就是B和A的混合图象,设B图象的透明度为 alpha(取值为0-1,1为完全透明,0为完全不透明),Alpha混合公式如下:
R(C)=(1-alpha)*R(B)+alpha*R(A)
G(C)=(1-alpha)*G(B)+alpha*G(A)
B(C)=(1-alpha)*B(B)+alpha*B(A)
步骤:1:获取原图大小  2:获取原始像素点阵  3:对各像素RGB分量进行混合  
for(int i=0;i<length;i++)
{
for(int t=0; t<width; t++ )
{
pix_array[i*width+t] = Getpixel(hdc,i,t);
}
}
for(int i=0; i<length*width; i++)
{
newpix_array[i].byRed  = pix_array[i].byRed* alpha + 255*(1- alpha);
newpix_array[i].byGreen  = pix_array[i].byGreen* alpha + 255*(1- alpha);
newpix_array[i].byBlue = pix_array[i].byBlue* alpha + 255*(1- alpha);
}
或者直接调用API:AlphaBlend
2.3背景色透明
调用API:TransparentBlt
BOOL TransparentBlt(
HDC hdcDest,        //目的DC句柄
int nXOriginDest,   //目的DC左上X轴坐标
int nYOriginDest,   //目的DC左上Y轴坐标
int nWidthDest,     //绘制时的矩形宽度
int hHeightDest,    //绘制时的矩形高度
HDC hdcSrc,         //源DC句柄
int nXOriginSrc,    //源DC左上X轴坐标
int nYOriginSrc,    //源DC左上Y轴坐标
int nWidthSrc,      //源矩形宽度
int nHeightSrc,     //源矩形高度
UINT crTransparent  // 需要透明的颜色RGB值
);
三:PPC UI常见问题
3.1 手势识别
原理:捕获用户触笔点击事件,收集触笔运动轨迹,触笔离开后综合收集到的轨迹点,进行分析判断。
基本实现:捕获系统响应消息,进行处理
单击事件:WM_LBUTTONDOWN
移动事件:WM_MOUSEMOVE
弹起事件:WM_LBUTTONUP
常用技巧:
控件聚焦 : 由于手持设备屏幕有限,控件分布相对密集,对用户操作的精准性有一定要求,当用户进行滚动条的下拉或者其他移动控件的动作时,很有可能在移动过程中触笔或手指会离开控件范围,从而中断移动操作,而这并非用户所预期。
因此,有必要对控件进行聚焦,即便出现上述状况,控件仍能收到WM_MOUSEMOVE事件。
解决该问题可调用API : SetFocus( HWND hWnd);
3.2界面自适应
由于POCKET PC支持横竖屏两种模式,在竖屏,横屏间切换时,如果不对程序的控件坐标进行调整,会造成界面混乱的后果。
基本实现:捕获系统的横竖屏切换消息,判断将切换到何种模式,在OnSize()中进行相应处理。
常用方法:
另外由于PPC屏幕尺寸的繁杂,对不同屏幕尺寸的自适应也需要注意。此处不再赘述。
1):调整控件坐标
捕获WM_SIZE消息,在响应函数中获取当前屏幕模式,根据屏幕大小对控件坐标进行调整,使整个界面自适应。
2):准备两套不同UI资源
针对横竖屏各准备一套UI资源,在WM_SIZE消息的处理函数中获取当前屏幕模式,根据不同模式调用相应UI资源,达到界面自适应的目的。
3.3 屏幕输入面板(sip)
在POCKET PC上进行应用开发时,并非所有界面都需要SIP输入面板,因此经常需要对SIP输入面板的显示和隐藏处理。
下面以直观的图给出两者的对比:
在WINDOWS MOBILE中隐藏SIP的方法很多,以下简要介绍其中几种方法:
1)SHSipPreference(m_hWnd,SIP_Down);
2)SIPINFO si;
memset(&si,sizeof(si));
SHSipInfo(SPI_GETSIPINFO,0,&si,0);
si.fdwFlags&=~SIPF_ON;
SHSipInfo(SPI_SETSIPINFO,0,&si,0);
3) SHFullScreen(hDlg,SHFS_SHOWTASKBAR,SHFS_HIDESIPBUTTON);
4)SipShowIM(SIPF_DOWN);
5) 获得窗口名为menu_worker的SIP窗口句柄,进行隐藏或显示,实现:
CWnd* pWndSIP = FindWindow( _T("menu_worker"), 0 );
if ( pWndSIP )
{
pWndSIP->ShowWindow(SW_HIDE);// SW_SHOW
}
6)另外通过IMM也可以对SIP进行控制。
3.4  MenuBar定制
MOBILE底部的MenuBar在应用程序中扮演着和用户交互的关键作用,根据不同的需求,经常需要定制MenuBar,本节将介绍如何对 MenuBar资源进行更改。
基本操作:
1. SHMENUBARINFO结构体
typedef struct tagSHMENUBARINFO {
DWORD         cbSize;      // SHMENUBARINFO结构体大小
HWND          hwndParent;  //CommondBar父窗口句柄
DWORD         dwFlags;    //MenuBar类型标识
UINT            nToolBarId;  //工具栏标识
HINSTANCE      hInstRes;    //控制资源的实例句柄
int               nBmpId;     // 按钮背景bmp图片资源ID
int               cBmpImages; //bmp图片资源数量
HWND           hwndMB;    //【输出参数】控制MenuBar的窗口句柄
COLORREF  clrBk;            //MenuBar背景颜色参数,包括SIP()
} SHMENUBARINFO,*PSHMENUBARINFO;
2.MenuBar类型
可以通过对dwFlags的设置,创建不同类型的MenuBar
SHCMBF_COLORBK          设置menu bar背景颜色
SHCMBF_EMPTYBAR      创建一个空的menu bar
SHCMBF_HIDDEN          创建一个隐藏的menu bar
SHCMBF_HIDESIPBUTTON   创建一个没有sip的menu bar
SHCMBF_HMENU              通过资源定制menu bar而不通过工具栏
3.MenuBar的创建
SHMENUBARINFO mbi;
memset(&mbi, 0, sizeof(SHMENUBARINFO));
mbi.cbSize     = sizeof(SHMENUBARINFO);
mbi.hwndParent = hWnd;//窗口句柄
mbi.nToolBarId = IDR_MENU;//菜单资源号
mbi.hInstRes   = g_hInst;//实例句柄
SHCreateMenuBar(&mbi)
g_hWndMenuBar = mbi.hwndMB;
创建完MenuBar实例之后,再对资源文件进行修改,指定
IDR_MENU SHMENUBAR DISCARDABLE
BEGIN
IDR_MENU, //ID
2,//个数
I_IMAGENONE, IDM_OK/*COMMAND ID*/,
TBSTATE_ENABLED,
TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE/*按钮或弹出菜单*/,
IDS_OK/*字符*/,
0, NOMENU,
I_IMAGENONE,IDM_HELP,TBSTATE_ENABLED, TBSTYLE_DROPDOWN|TBSTYLE_AUTOSIZE,
IDS_HELP, 0, 0,
END
IDR_MENU SHMENUBAR DISCARDABLE
BEGIN
IDR_MENU,
1,
I_IMAGENONE, IDM_OK, TBSTATE_ENABLED,
TBSTYLE_BUTTON |TBSTYLE_AUTOSIZE,
IDS_OK, 0, NOMENU,
END
通过以上操作,开发者可以给自己的程序定制个性化的MenuBar。
四:定制控件
这是当前MOBILE开发很重要,也很让开发者头疼的一个问题,有很多可以说但一下子说完貌似又不现实。大体来说,主要分为控件自绘,以及“伪控件”。
所幸,大部分控件和桌面系统一致,碰到有关控件的自绘和伪控件的实现问题,相关资料网路上都能找到不少,故在此不再展开。(combobox和桌面系统不同,MOBILE上不支持自绘)
如果觉得描述的不够具体可以看看下面的链接,是一些笔者曾制作的UI:http://hi.baidu.com/%C0%B6%C9%AB%D3%...5a044df04.html
其中 “按钮GO”就是BUTTON控件自绘
另外的COMBOBOX及显示数据的表格控件,都是用STATIC控件实现的伪控件。

转载于:https://www.cnblogs.com/fromchaos/archive/2010/03/03/1677028.html

[转]WIN MOBILE UI开发入门相关推荐

  1. UI设计/GUI开发-入门界面设计

    概述 从几个概念谈起,GUI(图形用户界面).UI开发.前端.Web开发,这些个耳熟的词语,是否想过它们正真的含义!一款使用体验极好的软件,好看.好用,必然不是凭空想出来的,而是有理论依据.多方配合设 ...

  2. GMU(Global Mobile UI)是百度前端通用组开发的移动端组件库

    GMU(Global Mobile UI)是百度前端通用组开发的移动端组件库,具有代码体积小.简单.易用等特点,组件内部处理了很多移动端的bug,覆盖机型广,能大大减少开发交互型组件的工作量,非常适合 ...

  3. 【iVX 开发 - 入门】UI 组件介绍及实操详解

    本文导读 写在前面 iVX 各 UI 组件及属性面板详解 1. 图片组件 2. 图片序列组件 3. 文本组件 4. 输入框组件 5. 富文本/富文本编辑器组件 6. 地图组件 7. 二维码组件 写在前 ...

  4. 安卓开发入门教程-UI控件_EditText

    什么是EditText EditText是用于进行文本输入的UI控件. 基础样例 1.普通输入 效果图 代码 <EditTextandroid:layout_width="wrap_c ...

  5. java游戏开发入门(六) - 变量 UI

    java游戏开发入门(六) - 变量 & UI 前言 编码 首先我们创建一个变量 修改碰撞逻辑 初始化UI并将UI与变量绑定绑定 于是我们就得到了这样一个效果 完整代码 完整项目 前言   上 ...

  6. android开发入门_Android开发入门

    android开发入门 Android is an open source, Linux-based mobile operating system. Android was developed by ...

  7. HTML5plus 移动 App开发入门

    咳咳,图片复制不到文章里面来,大家去我的资源里下载吧,PDF版的. HTML5plus 移动 App开发入门 更新时间:2014年 4月 17日 HTML5 Plus 应用概述 HTML5 Plus ...

  8. iPhone开发入门(1)----程序员眼中的iPhone

    自去年 iPhone 面世以来,开创了移动设备内容服务的一种新的模式--程序商店(App Store).它极大地降低了移动设备应用程序开发的成本,即使普通人也能进入这个市场.就像在PC上开发应用程序一 ...

  9. Vue开发入门(二) | 说说Vue全家桶有哪些~

    全家桶,顾名思义,就是一个系列,可以组合开发成完整强大的Vue项目 前言: *Vue两大核心思想:组件化和数据驱动. 组件化:把整体拆分为各个可以复用的个体 数据驱动:通过数据变化直接影响bom展示, ...

最新文章

  1. python argparser模块的相关使用
  2. 给定一个数组求里面数字拼在一起组成的最小数字
  3. WordPress强制跳转https教程
  4. 安卓进阶系列-03上弹选择框(PopupDialog)的使用
  5. mysql怎么可视化连接_IDEA连接MySQL可视化工具连接操作
  6. leetcode 188. 买卖股票的最佳时机 IV(dp)
  7. cordova报错“No installed build tools found. Install the Android build tools version - ”
  8. 编程语言中,差、交、并、自然连接、选择、投影、笛卡尔积分别都是什么运算...
  9. CentOS 7 上搭建 Nacos Cluster 集群
  10. 机器人把大龙拉出来_LOL-LPL夏季赛:Wei男枪打野未换惩戒 ES让BLG拿下首胜
  11. ubuntu无法连接网络
  12. java jenkins_java调用jenkins-client实现连接jenkins服务 互联网技术圈 互联网技术圈
  13. 在Chrome上安装ie tab插件
  14. 关于struts2通配符不能用
  15. 腾讯云短信(个人记录)
  16. nasm预处理器(1)
  17. 蓝桥杯 基础练习 分解质因数 C语言
  18. 红警2你值得拥有(游戏人生)
  19. 61850(CMS)
  20. Python计算机视觉之基于BOW的图像检索

热门文章

  1. 云办公系统 skyeye v3.7.16 部分企业版开源
  2. Java项目——云R记
  3. 制作Linux的优盘(usb)启动盘
  4. 小米 13 系列新品发布会将延期举行;马斯克:和苹果的误解得到了解决;IntelliJ IDEA 2022.3 发布|极客头条
  5. PaddlePaddle课程学习第二周笔记
  6. 【iOS】设置背景渐变色
  7. 渐变背景(background)效果
  8. scheme Android
  9. 自动写故事、写字成图?5款有趣实用的AIGC工具分享
  10. laragon安装postgreSQL