`
isiqi
  • 浏览: 16489849 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

WINCE应用的UI实现方案 —— 中篇:GWES方案上几技术难点的解决

阅读更多

这里谈论的所谓技术难点,其实根本不值一提。只不过微软定了一套游戏规则,我们目前不清楚这套游戏规则,花时间去摸索而已。

1、BUTTON的动画效果

我们用了GWES里提供的BUTTON类,在WINCE PRODUCT DOCUMENT里的位置是
ms-help://MS.WindowsCE.500/wceshellui5/html/wce50grfButtonReference.htm
里面并没有给出太多的说明,在Button Messages里提到有WM_CTLCOLORBTN消息, 但简单试用后发现和预期效果不符。我乱翻乱点时注意到了eVC在画图时,对BUTTON点右键出的菜单里,打开Properties,里面的Styles页有个复选框"Owner draw", 我就抓住这根稻草,GOOGLE一把,方法就出来了。

当Owner draw属性被勾选时,轮到该BUTTON绘图时,程序就不会跑DefDlgProc去画个灰色突出的效果并把按钮名字写上去,而是给BUTTON的父窗口,也就是DIALOG的PROC发个消息WM_DRAWITEM,并且所带的lParam中有我们需要的所有东西。来个强制转换
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
然后根据 lpDIS->itemAction 和 lpDIS->itemState 判断BUTTON当前状态,以决定加载哪幅图片

DRAWITEMSTRUCT的详细说明请参考 ms-help://MS.WindowsCE.500/wceshellui5/html/wce50lrfdrawitemstruct.htm

我简单试了了一下,
(1) 初始化时
itemAction == 1; // ODA_DRAWENTIRE
itemState == 16; // ODS_FOCUS
(2) BUTTON被按下时
itemAction == 2; // ODA_SELECT
itemState == 17; // ODS_FOCUS | ODS_SELECTED
(3) BUTTON被点击后松开时
itemAction == 2; // ODA_SELECT
itemState == 16; // ODS_FOCUS

ODA和ODS宏定义数值
/*** from Winuser.h ***/
#define ODT_MENU 1
#define ODT_LISTBOX 2
#define ODT_COMBOBOX 3
#define ODT_BUTTON 4
//action
#define ODA_DRAWENTIRE 0x0001
#define ODA_SELECT 0x0002
#define ODA_FOCUS 0x0004
//state
#define ODS_SELECTED 0x0001
#define ODS_GRAYED 0x0002
#define ODS_DISABLED 0x0004
#define ODS_CHECKED 0x0008
#define ODS_FOCUS 0x0010

在WM_DRAWITEM中有两点要特别注意
(1) 不能在里面用InvalidateRect(lpDIS->hwndItem, lpDIS->rcItem, NULL),这会立即再发一个WM_DRAWITEM消息过来,接着再调InvalidateRect, 进入死循环直至把设备上的内存耗光,导致死机
(2) 对itemAction和itemState作判断时,必须把两者同时都判断了才能确定CLICK状态,单独判断action或单独判断state是不够的,会导致重绘作用在不希望发生的情况下。并且不能简单地作itemAction & ODA_SELECT这样的位与判断,还必须有排他性,我干脆就用==号了。

参考代码如下


1BOOLCALLBACKDialogProc(HWNDhDlg,UINTuMsg,WPARAMwParam,LPARAMlParam)
2{
3switch(uMsg)
4{
5caseWM_DRAWITEM:
6{
7LPDRAWITEMSTRUCTlpDIS=(LPDRAWITEMSTRUCT)lParam;
8
9if(lpDIS->CtlID==IDC_BTN_1)
10{
11
12if((lpDIS->itemAction&ODA_DRAWENTIRE)//这是初始化时的情况
13||((lpDIS->itemAction==ODA_SELECT)&&(lpDIS->itemState==ODS_FOCUS)))//这是按下后放开时的情况
14{
15//画上未被按下时的图片
16}
17elseif((lpDIS->itemAction&ODA_SELECT)&&(lpDIS->itemState==(ODS_FOCUS|ODS_SELECTED)))//被按下时的情况
18{
19//画上被按下时的图片
20MessageBeep(MB_OK);//顺便响一声,比较有手感
21}
22}
23returnTRUE;
24}
25default:
26//STUB
27break;
28}
29
30returnFALSE;
31}


2、DLU和PIXEL的单位转换

本来以为做完BUTTON效果后就OVER了,结果今天傍晚时候遇到一个很恼火的问题。在VC / eVC / VS中画的对话框、按钮等控件时,在IDE右下角显示的 XX * XX单位是DLU (Dialog Unit), 这是根据你设置的对话框字体大小而改变的。这种做法无可厚非。如果把字体改大了,那么DIALOG和BUTTON自然也被“撑”大了,比较灵活。但是我往上叠加的图片是按像素(PIXEL)来算的。最后实现出来,有两个方法。按照国际惯例,当然是先讲笨的方法,MSDN上的作风也是如此。

(1)方法一:我查了下DLU和PIXEL之间的换算关系,有个讲得比较全的网页是 http://support.microsoft.com/default.aspx?scid=kb;en-us;145994 (How to caculate dialog box units based on the current font in Visual C++) 按照文中的Method Two简单测试了一下

1BOOLCALLBACKDialogProc(HWNDhDlg,UINTuMsg,WPARAMwParam,LPARAMlParam)
2{
3switch(uMsg)
4{
5caseWM_INITDIALOG:
6{
7RECTrc={0,0,4,8};
8
9MapDialogRect(hDlg,&rc);
10printf("baseUnitX=%ld\n",rc.right);
11printf("baseUnitY=%ld\n",rc.bottom);
12
13//DLU_Weight=pixel_weight*4/baseunitX;
14//DLU_Height=pixel_height*8/baseunitY;
15
16returnTRUE;
17}
18}
19
20returnFALSE;
21}


对于我DIALOG中设置的Courier New 10pt字体,
第一步:从代码中得到baseUnitX = 7, baseUnitY = 16,
第二步:套用公式
weight_DLU = weight_pixel * 4 / baseUnitX
height_DLU = height_pixel * 8 / baseUnitY
比如我想建立一个320*240 PIXEL的对话框,那么
weight_DLU = 320 * 4 / 7 = 182.86, 取整为183
height_DLU = 240 * 8 / 16 = 120
第三步:到VC里去拖动对话框的边界,画出183*120的对话框,那么代码运行起来后,通过GetClientRect查一下,的确是得到320*240 pixel的对话框了。

但是这种方法有一个致命的缺点。比如我要画一个60*70的按钮,按照上面的baseUnitX和baseUnitY折算后应该为34.28 * 35,但是我画34*35 DLU时,运行得到59*70 PIXEL窗口;画35*35 DLU时,运行得到61*70 PIXEL窗口,无法恰到好处,这导致了往上叠加60*70 pixel的图片时,按钮边缘会出现不连续的黑点。所以这段文字只能当作DLU和PIXEL的换算关系来玩了,没有任何实际应用价值。

(2) 方法二:正确的方法
其实也很简单。晚饭后突然想到的,用SetWindowPos强制设置window的长宽和左上角坐标。我在WM_DRAWITEM消息的处理中简单试了一下:
SetWindowPos(lpDIS->hwndItem, NULL, 10, 10, 60, 70, SWP_NOZORDER);
设置前是59*70的按钮,设置后就是60*70了,并且叠加图片没有任何问题。OK,整个基于GWES的UI方案至此成型了。后面貌似没有什么大的技术障碍了。

至此,我没有发现GWES方案上还有什么路障了,可以拍板使用这套方案了,和只用GDI写UI相比,软件研发的工作量大概降低了30%左右。当然事情还没有就这样结束,这套方案对我这项目组的意义是很深远的。请看下篇:代码中的一小步,项目进度管理上的一大步

分享到:
评论

相关推荐

    Wince下的拨号程序

    6. **UI设计**:虽然GWES提供了基本的拨号界面,但根据应用需求,可能需要自定义更友好的用户界面。这涉及到Wince的图形用户界面编程,可能用到WinCE GDI库或者MFC等。 7. **权限管理**:在嵌入式设备中,安全性和...

    解决wince启动Nandflash扫描慢

    ### 解决WinCE启动Nandflash扫描慢的问题 #### 一、问题背景及原因分析 在使用基于Freescale Semiconductor的处理器(如i.MX27、i.MX31等)并搭载Windows CE(WinCE)操作系统的设备时,可能会遇到启动过程中Nand...

    基于GWES的WinCEDisplay驱动开发介绍

    在WinCE中,Display驱动由GWES模块来管理。WinCE提供了两种架构的Display驱动模型,可以满足不同的硬件需求。一种是基于WinCEDDI的Display驱动模型,另一种是基于DirectDraw的Display驱动模型。下面将对两种架构作...

    WinCE开发教程

    《WinCE开发教程》 Windows CE (Windows Embedded Compact) 是微软...通过本教程,开发者不仅可以了解WinCE的基本概念,还能掌握实际开发中的关键技术和技巧,为在嵌入式领域构建基于WinCE的解决方案打下坚实基础。

    Wince电源管理实现

    综上所述,Wince中的电源管理实现了从简单到复杂的演变过程。早期版本通过GWES提供了基础的电源管理功能,而后期版本则通过专门的电源管理模块提供了更加细致和灵活的电源管理机制。这对于延长设备电池寿命、提高...

    修改注册表实现wince开机自动运行程序.doc

    Windows CE 注册表编辑与自动运行程序 Windows CE 作为一种微软公司开发的实时操作系统,广泛应用于...注册表编辑是 Wince 开发中的一个重要技术,掌握注册表编辑技术可以让开发者更好地控制 Wince 系统的行为和性能。

    WinCE通信指南之配套光盘含全部源代码示例

    4. **GWES(Generic Windows Embedded Shell)**:GWES是WinCE的标准用户界面,源代码可能包含如何自定义GWES组件,如菜单、对话框、控件,以实现特定的用户交互功能。 5. **驱动程序开发**:WinCE支持用户模式和...

    WINCE嵌入式复习资料

    - 从下到上分为硬件层、OEM层、操作系统层和应用程序层。 - 操作系统层包括内核(NK.EXE)、图形系统(GWES.EXE)、对象存储(FILESYS.EXE)、设备管理(DEVICE.EXE)、服务(SERVICES.EXE)以及CoreDLL。 7. **...

    基于GWES的WinCE Display驱动开发介绍

    在WinCE中,Display驱动由GWES模块来管理。WinCE提供了两种架构的Display驱动模型,可以满足不同的硬件需求。一种是基于WinCE DDI的Display驱动模型,另一种是基于DirectDraw的Display驱动模型。下面将对两种架构作...

    wince 系统架构

    Windows CE(简称WinCE)是一种基于微内核的实时操作系统,设计用于嵌入式设备。它的系统架构由多个核心组件组成,对...在实际开发中,开发者可以根据项目需求选择和定制相应的组件,实现高效稳定的嵌入式解决方案。

    Android_GWES

    ### Android GWES详解 #### 一、Android GWES概述 ...通过对View和ViewGroup的理解,开发者可以更好地设计和实现应用程序的用户界面。同时,掌握UI Event的处理机制和Graphics渲染原理对于优化应用性能具有重要意义。

    WINCEWINCEWINCEWINCE

    在Windows CE的架构中,我们可以看到以下几个关键组成部分: 1. **硬件层**:这是与设备物理硬件直接交互的部分,包括CPU、内存、I/O接口等。OEM(原始设备制造商)需要根据自己的硬件设计来适配Windows CE。 2. *...

    嵌入式系统/ARM技术中的基于GWES的WinCE Display驱动开发介绍

     在WinCE中,Display驱动由GWES模块来管理。WinCE提供了两种架构的Display驱动模型,可以满足不同的硬件需求。一种是基于WinCE DDI的Display驱动模型,另一种是基于DirectDraw的Display驱动模型。下面将对两种架构...

    WinCE驱动开发 WinCE驱动开发 WinCE驱动开发

    在Windows CE (WinCE)操作系统中,驱动开发是构建嵌入式系统不可或缺的一部分。WinCE驱动程序设计有其独特之处,主要围绕两个模型展开:本机驱动程序和流接口驱动程序。 首先,WinCE中的所有驱动程序都是动态链接库...

    WINCE驱动开发分层概念

    在Windows CE(WINCE)平台中,驱动开发是一项关键任务,因为它涉及到硬件设备与操作系统的交互。WINCE驱动主要分为两种...理解这些概念对于开发和调试WINCE驱动至关重要,有助于构建高效、稳定的硬件驱动解决方案。

Global site tag (gtag.js) - Google Analytics