slide1
Download
Skip this Video
Download Presentation
设备管理器和 GWES

Loading in 2 Seconds...

play fullscreen
1 / 71

设备管理器和 GWES - PowerPoint PPT Presentation


  • 217 Views
  • Uploaded on

设备管理器和 GWES. www.up-tech.com 博创科技 嵌入互动. 主要内容. 设备管理的基本概念 WinCE 的设备管理 设备管理器的具体实现 GWES 的概念和功能 从应用程序调用 GWES. 1 、设备管理的基本概念. 设备的分类. 按设备的使用特性: 存储设备 输入输出设备 终端设备 。。。 按设备的从属关系 系统设备 用户设备. 设备管理的任务. 选择和分配输入输出设备以便进行数据传输操作 控制输入输出设备和 CPU 之间交换数据

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' 设备管理器和 GWES' - adie


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

设备管理器和GWES

www.up-tech.com

博创科技 嵌入互动

slide2
主要内容
  • 设备管理的基本概念
  • WinCE的设备管理
  • 设备管理器的具体实现
  • GWES的概念和功能
  • 从应用程序调用GWES
slide4
设备的分类
  • 按设备的使用特性:
    • 存储设备
    • 输入输出设备
    • 终端设备
    • 。。。
  • 按设备的从属关系
    • 系统设备
    • 用户设备
slide5
设备管理的任务
  • 选择和分配输入输出设备以便进行数据传输操作
  • 控制输入输出设备和CPU之间交换数据
  • 为用户提供一个友好的透明接口,把用户和设备硬件特性分开,使得用户在编制应用程序时不必涉及具体设备,系统按用户要求控制设备工作。另外这个接口还为新增加的用户设备提供一个和系统核心相连接的入口,以便用户开发新的设备管理程序。
  • 提高设备和设备之间、CPU和设备之间,以及进程和进程之间的并行操作度,以使操作系统获得最佳效果。
slide6
设备管理的功能
  • 提供和进程管理系统的接口。当进程要求设备资源时,该接口将进程要求转达给设备管理程序。
  • 进行设备分配。按照设备类型和相应的分配算法把设备和其他有关的硬件分配给请求该设备的进程,并把为分配到所请求设备获取他有关硬件的进程放入到等待队列。
  • 实现设备和设备、设备和CPU等之间的并行操作。
  • 进行缓冲区管理。
slide7
对设备的控制方式
  • 程序直接控制方式
  • 中断方式
slide9
设备管理器的概念
  • 设备管理器是在 Windows CE 操作系统下运行的进程,它跟踪已加载的驱动程序和它们的接口。它连续不断地运行并且从内核中启动。
  • 设备管理器可以在设备接口变得可用和不可用时通知用户。用户或系统本身可以使设备接口变得可用或不可用。
  • 另外,设备管理器通知内核设备接口支持文件操作(例如,CreateFile)访问公开流接口的设备。
  • 设备管理器向设备驱动程序发送电源通知回调并提供电源管理服务。
slide10
设备管理器和注册表
  • 设备管理器控制注册表中的 Active 项。
  • 只有设备管理器应当访问 Active 项以获取读取或写入访问权限。
  • 可以通过设备驱动程序的初始化函数的参数间接访问 Active 项。
slide11
设备管理器和注册表
  • 设备管理器搜索 HKEY_LOCAL_MACHINE\Drivers\RootKey 注册表项,以确定用于开始驱动程序加载过程的项。
  • RootKey 的默认值是 Drivers,但是它通常等于 Drivers\BuiltIn。
  • 设备管理器调用 ActivateDeviceEx 以加载由 Dll 子项的值指定的驱动程序。Dll 子项的值默认情况下为 BusEnum.dll(也称为总线枚举器)。
  • 加载 BusEnum.dll 会使所有设备驱动程序加载。由 ActivateDeviceEx 加载的设备可以从它的 Active 注册表项中读取它的激活句柄。
slide12
驱动程序的命名
  • 设备管理器将总线名称与驱动程序相关联。未命名的设备也可以具有总线名称,因为即使应用程序可能无法访问驱动程序,驱动程序也可能被其他驱动程序或系统实体(例如,电源管理器)访问。总线名称可以具有与正规设备名称不同的 ACL。
  • 设备管理器跟踪由驱动程序公布的接口,并且支持基于全局唯一标识符 (GUID) 搜索驱动程序。IClass 接口可以将接口 GUID 与驱动程序的旧式名称、$device 名称或 $bus 名称(例如,“COM1 :”、“$device\com1”或“$bus\pci_0_3_0”)相关联。
slide13
公布驱动程序的接口
  • 驱动程序可以通过调用 DMAdvertiseInterface 以编程方式公布接口。DMAdvertiseInterface 使驱动程序能够将更多可搜索的 GUID 添加到它们的关联列表中。DMAdvertiseInterface 由 Devmgr.dll 公开,后者还实现了大多数设备管理器功能。因为只有设备管理器可以加载 Devmgr.dll,所以只有设备驱动程序可以调用 DMAdvertiseInterface。如果设备驱动程序在卸载时没有公布它的接口的不可用性,则设备管理器会自动清除接口公布通知。
slide14
设备管理器组成
  • 设备管理器由 Device.exe 和 Devmgr.dll 组成。Device.exe 包含 Devmgr.dll,后者实现了核心设备管理器功能。
  • 因为设备管理器由两个单独的模块组成,所以设备驱动程序可以直接与设备管理器链接并调用特定的函数而不会引起系统调用的开销。
slide16
设备管理器的体系结构
  • 一般操作系统的设备管理都采用分层的管理模式。WinCE在模块组成和划分方面更加具体而实用。
  • WinCE设备管理部分采取了类似Windows 2000/XP的结构,大大的简化了中断处理、I/O访问以及内部管理的机制。
  • WinCE的设备管理包括四个部分。
slide17
设备管理器的体系结构
  • 设备管理器:设备管理器是WinCE设备管理的核心机构,他主要负责跟踪、维护系统的设备信息并对设备资源进行调配。
  • I/O资源管理:I/O资源管理器是设备管理模块内部的重要组成部分,他跟踪了设备驱动程序装载前从注册表信息中初始化所需的系统资源。
  • 电源管理器:
  • 支撑和管理例程库
slide19
设备加载
  • 设备加载的代码被放入device.c的InitDevices函数中
  • 此函数已工作了以下一些工作:
    • 打开注册表
    • 读出注册表的HKEY_LOCAL_MACHINE\Drivers\RootKey键
    • 激活里面列出的设备
  • 具体实现如下:
slide20
设备加载

InitDevices(VOID)//此函数的目的是为了初始化内置的驱动程序,不需要入口函数

{

// Open HLM\Drivers key

//

status = RegOpenKeyEx(//打开指定的键

HKEY_LOCAL_MACHINE,

DEVLOAD_DRIVERS_KEY,

0,

0,

&RootKey);

// 查找root键键值,如果没找到则使用当前默认的root键,否则打开新的root键

ValLen = sizeof(RootKeyPath);

slide21
设备加载

status = RegQueryValueEx(//查询roots

RootKey,

DEVLOAD_ROOTKEY_VALNAME,

NULL,

&ValType,

(PUCHAR)RootKeyPath,

&ValLen);

// Close previous root key

RegCloseKey(RootKey);//关闭

(void) ActivateDevice(RootKeyPath, 0);//将此值传给ActiveDevice函数来加载设备

}

slide22
设备加载
  • 由上面的代码可以看出,设备加载的过程依赖于注册表,任何新的设备必须首先在注册表中声明,随后才能被加载
  • 设备加载的核心是ActiveDeviceEx,此函数没有被公开
  • 如果在应用程序中加载一个新的设备,可以调用ActiveDeviceEx,这和设备管理器加载设备的过程是相同的。
winmain
设备管理器中的WinMain
  • 设备管理器表现为device.exe,这是由源程序编译得到的可执行文件,设备管理器运行在用户模式。对于可执行文件,一般都存在一个主函数。设备管理器的主函数放在device.c中,为WinMain。
  • WinMain函数完成设备的初始化和加载过程,整个过程分为三个阶段。
winmain1
设备管理器中的WinMain
  • 第一阶段:构造基本的数据结构
  • 第二阶段:装载并初始化设备
  • 第三阶段:记录下做过的工作,整理
  • 具体代码分析见下:
winmain2
设备管理器中的WinMain

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nCmShow)

{

HINSTANCE hCeddkDll;//cdddk.dll的实例句柄,实例句柄一般都指向某一个库文件

HANDLE hevBootPhase1;//事件句柄

//开始第一阶段的启动,构造各种基本的数据结构

// PHASE 1

g_BootPhase = 1;//全局变量,表明当前启动阶段为第一阶段

InitOOMSettings();//初始化OOM设置,什么是OOM?

InitializeListHead(&g_DevChain);//常规状态的设备列表,WINCE的设备都被组织在连表中

InitializeListHead(&g_DyingDevs);//消亡状态的设备列表

InitializeListHead(&g_CandidateDevs);//正在加载的设备列表

g_hCleanEvt = CreateEvent(0,0,0,0);//此事件用于同步各个设备控制函数

g_hCleanDoneEvt = CreateEvent(0, 1, 1, 0); //manual reset, init state signalled

g_hDevApiHandle = CreateAPISet("WFLD", NUM_FDEV_APIS, FDevApiMethods, FDevApiSigs);

//创建API集合

g_hDevFileApiHandle = CreateAPISet("W32D", NUM_FAPIS, DevFileApiMethods, DevFileApiSigs);//同上

RegisterAPISet(g_hDevFileApiHandle, HT_FILE | REGISTER_APISET_TYPE);//注册API集合

winmain3
设备管理器中的WinMain

InitializeDeviceNotifications();//初始化设备通知结构,在这个结构里包含三个域,第一 //个是通知链表元素,第二个是广告(?)链表元素,第 //三个是临界区。在这个函数中分别对这三项进行了初始 //化。WINCE设备管理其中也是广泛应用了临界区,相比 //核心对象,临界区更快,大量使用临界区可以提高程序 //的速度

InitializeCriticalSection(&g_devcs);//设备临界区,全局变量

ResourceInitModule();//资源初始化模块

ResourceInitFromRegistry(TEXT("Drivers\\Resources"));//从注册表的项中初始化资源

SetPowerOffHandler((FARPROC)FS_PowerAllDevices);//设置电源处理函数为FS_PowerAllDevices

RegisterAPISet(g_hDevApiHandle, SH_DEVMGR_APIS);//不知道怎么回事

StartDeviceNotifyThread();//开启设备通知线程

winmain4
设备管理器中的WinMain

// Calibrate stall counter that is used for StallExecution

hCeddkDll = LoadLibrary (TEXT("ceddk.dll"));//加载ceddk。Dll

if (NULL != hCeddkDll) {//如果加载成功

pCalibrateStallFn fnCalibrateStall = (pCalibrateStallFn)GetProcAddress(hCeddkDll, TEXT("CalibrateStallCounter"));//得到库中函数CalibrateStallCounter的地址

if (!fnCalibrateStall) {//如果没有此地址则释放库

DEBUGMSG(ZONE_BOOTSEQ, (L"GetProcAddress failed on ceddk.dll\r\n"));

FreeLibrary(hCeddkDll);

}

else {

fnCalibrateStall();//有则执行之

}

}

// Call the power manager initialization entry point

PM_Init();//电源管理函数入口点,核心内容未公开

PM_SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);//设置当前状态,核心内容未公开

winmain5
设备管理器中的WinMain

// See if we are going to have two boot phases

hevBootPhase1 = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SYSTEM/BootPhase1"));//打开事件

if (hevBootPhase1 != NULL) {//如果已打开

HANDLE hEvent;

// Load phase 1 drivers from the boot registry

DevloadInit();//加载设备

// Signal boot phase 1 complete

SetEvent(hevBootPhase1);//第一阶段结束

CloseHandle(hevBootPhase1);

// Wait for phase 2 of the boot to begin

hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("SYSTEM/BootPhase2"));//打开第二阶段的事件

winmain6
设备管理器中的WinMain

if (hEvent) {//如果事件存在

DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: Started, waiting for boot phase 2\r\n")));

WaitForSingleObject(hEvent, INFINITE);//等待时间被释放

CloseHandle(hEvent);

}

// Load any new drivers from the persistent registry. Since the

// registry may have changed, update the power state for any devices

// that need it.

DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: Second-phase driver load\r\n")));

g_BootPhase = 2;//进入第二阶段,装载并初始化设备

PM_SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);//设置电源管理状态

InitDevices();//初始化设备

DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: Startup sequence complete\r\n")));

SignalStartedUsingReg(); // SignalStarted call with the right args

winmain7
设备管理器中的WinMain

else {//如果事件未打开

DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: No boot registry - skipping to boot phase 2\n")));

g_BootPhase = 2;//进入第二阶段

DevloadInit();//初始化设备

SignalStarted(_wtol(lpCmdLine));

}

winmain8
设备管理器中的WinMain

g_BootPhase = 3;//进入第三阶段

CELOG_DeviceFinished ();//记录

while (1) {

WaitForSingleObject(g_hCleanEvt, INFINITE);

// check for auto-deregister devs first as they may end up queuing

// themselves on the dying devs list

ProcessAutoDeregisterDevs();//处理自动取消注册的设备

ProcessDyingDevs();//处理死亡的设备

ProcessDyingOpens();//处理死亡的打开操作

DEBUGMSG(ZONE_DYING, (TEXT("DEVICE: Setting CleanDoneEvt in WinMain.\r\n")));

SetEvent(g_hCleanDoneEvt);

}

winmain9
设备管理器中的WinMain
  • 函数中用到了几个事件和链表,调用了几个函数
  • 事件
    • g_hCleanEvt
    • g_hCleanDoneEvt
  • 函数
    • InitOOMSettings()
    • ProcessAutoDeregisterDevs()
    • ProcessDyingDevs()
    • ProcessDyingOpens()
    • StartDeviceNotifyThread()
  • 链表
    • g_hDevchain
    • g_DyingDevs
    • g_lpOpenDevs
    • g_lpDydingOpens
winmain10
设备管理器中的WinMain
  • 通过WinMain函数,WinCE初始化了与设备相关的所有数据结构和函数。
  • 注册了API函数集,初始化了电源管理,声明了一些标准函数的接口。
  • 设备管理器是整个WinCE管理设备的基础,在所有的设备运行之前,必须保证设备管理器的初始化成功,任何设备想要被加载,必须在注册表里声明自己,等到设备管理器的加载,或是由应用程序代替设备管理器完成相应的功能。
  • 因为设备管理器也属于用户程序,所以应用程序可以部分代替设备管理器的功能。
slide35
GWES的概念
  • 与Microsoft的桌面操作系统不同,Windows CE将Win32 API的用户界面(USER32)和图形设备接口(GDI32)合并成一个新的模块gwes.exe,成为GWES子系统。GWE是一个缩写词,其中G代表图形,W代表窗口管理,E代表事件管理。GWE字系统是用户、应用程序和操作系统之间的图形用户界面。
slide36
GWES的概念
  • GWES支持组成WinCE图形用户界面的所有窗口、对话框、控件、菜单和资源,使用户能够通过执行菜单命令、单机按钮等操作来控制应用程序。GWE还以位图、光标、文本以及图标等形式为用户提供信息。即使不具备图形用户界面的基于WinCE的平台也使用了GWE的基本窗口和消息功能,这些功能提供了在用户、应用程序和操作系统之间进行通信的方法。
slide37
定制的GWES
  • WinCE是模块化的操作系统,OEM厂商可以针对于特定的平台选择软件模块来设计操作系统。
  • WinCE提供了几种预先测试的组建配置放案,这些配置放案可以分为三类:最小配置、中等配置和完全配置。
slide38
中等配置下的GWES包含的功能
  • 消息处理及用户输入
  • 电源管理
  • 提示性发光二极管
  • GDI,包括MS True Type字体和光栅字体,文本绘制,调色板和打印。
  • 可自定义的触摸屏和可校准的用户界面接口。
  • 网络用户界面接口。
  • 波形API管理器
  • 输入方法管理器
  • 窗口和对话框管理器
  • 可自定义的用户界面接口。
slide39
GWES的组件模型
  • 用户输入系统:接受来自键盘、鼠标和手写笔等设备的消息
  • 事件管理器:管理消息和消息队列
  • 窗口管理器:将消息相应发送到对应的窗口以实现特定的显示。
slide40
用户输入系统
  • Windows CE.NET支持下列类型的用户输入:键盘,鼠标,触摸屏,软键盘,手写输入等等
  • 每一个线程有一个特定的窗口称为活动窗口;焦点窗口能够接受来自键盘的消息;前台线程中的活动窗口是前台窗口
  • 所有这些输入设备都被用户输入子系统管理起来。输入子系统还负责处理前台窗口、活动窗口、和焦点窗口。
slide41
键盘输入
  • 键盘是许多计算机设备上的一种常用输入方法,Windows CE.NET提供了一种独立与设备的键盘模型,这使得可以由OEM自己决定Windows CE设备的键盘布局。
  • 键盘驱动程序将每个扫描码翻译或映射为虚拟键码,虚拟键码是用于识别、与硬件无关的数字。
  • 将扫描码翻译为虚键码之后,设备驱动程序创建一条包含了所有信息的键盘消息,并将这条消息放在系统的消息队列中。线程消息循环从队列中取出消息并将它发送给线程焦点窗口的窗口过程
slide42
触摸屏输入
  • 在许多WinCE设备中,用户通过手写笔和触摸屏与应用程序交互,手写比喻触摸屏提供了一中直接且直观的鼠标替代物。
  • 对应用程序而言,手写笔及触摸屏运行时所产生的时间与鼠标所产生的事件基本一致,可以说是鼠标事件的子集。当用户在屏幕上按下和松开手写笔时,应用程序像处理单击鼠标左键一样处理这些事件;当用户在屏幕上移动手写笔时,应用程序项处理鼠标移动事件一样处理它。
slide43
软键盘输入
  • 有很多的WinCE设备因位置原因均没有键盘,WinCE为这类设备提供了一种通过触摸屏模拟键盘输入的输入方法,这种输入面板结构与软件界面与键盘类似,所以对用户来说也称为软键盘。
  • 在用户访问输入面板时,WinCE创建一个专用的输入面板线程,这个线程创建输入面板窗口并初始化,然后线程进入消息循环,对来自输入面板的消息作出响应。
slide44
事件管理器
  • WinCE是事件驱动的操作系统,消息通过MSG结构传递。WinCE的MSG结构包含六个成员,不支持消息钩子。
  • 基于WinCE的编程要通过消息循环。消息循环是在Windows应用程序中的一种循环,他负责接收系统传送过来的消息,并且把它们发送到相应的窗口中,直到所有的消息都发送完毕,消息循环才结束。
slide45
显示管理
  • GWES的显示管理部分囊括了几乎所有与显示有关的组件和接口。
  • 实现了一整套GDI对象,其中包括画笔,画刷,位图、字体等
  • 采用了与桌面式Windows完全不同的调色板管理机制
  • 实现了显示驱动程序接口
slide46
GDI对象
  • 画笔和画刷
  • 位图
  • 字体
slide47
GDI对象的使用方法
  • 设备上下文
  • SelectObject
  • DeleteObject
slide49
GWES的应用
  • 消息的处理
  • 响应键盘和鼠标消息
  • 绘图函数
windows
Windows消息的处理
  • 消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。
  • 一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。
  • Windows程序是事件驱动的,对于一个窗口,它的大部分例行维护是由系统维护的。每个窗口都有一个窗口过程对传入的消息进行处理,窗口过程选择不处理某个消息,系统将使用缺省消息处理函数。
slide51
窗口过程的声明
  • LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  • 其中四个参数分别为:接受到消息的窗口句柄,消息码,消息的第一个参数,消息的第二个参数
  • 在窗口过程中首先判断消息码得到消息的主类型,随后通过后两个参数得到消息的更进一步的信息。
slide52
手动发送消息
  • SendMessage和PostMessage
    • Windows 操作系统创建的所有窗口都有一个消息队列。应用程序可以通过使用 函数 SendMessage 和 PostMessage 将消息放置到该队列中。这些函数允许应用程序传递一个标识执行操作的整数标志和两个被称为 WParam 与 LParam 的消息定义数据值。
    • 除了有一个主要的不同点,SendMessage 和 PostMessage 函数基本上是一样的。SendMessage 将消息放置到窗口消息队列中,并阻止消息直到窗口完成对它的处理。PostMessage 将消息放置到窗口消息队列中并立即返回。
  • 函数用法:
    • LRESULT SendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
    • BOOL PostMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
slide53
响应键盘和鼠标的消息
  • 几种键盘消息
    • WM_CHAR chCharCode = (TCHAR) wParam; lKeyData = lParam;
    • WM_KEYDOWN nVirtKey = (int) wParam; lKeyData = lParam;
    • WM_KEYUP nVirtKey = (int) wParam; lKeyData = lParam;
  • 几种鼠标消息
    • WM_L(R)BUTTONDBLCLK/ WM_L(R)BUTTONDOWN/ WM_L(R)BUTTONUP fwKeys = wParam; xPos = LOWORD(lParam); yPos = HIWORD(lParam);
    • WM_MOUSEMOVE fwKeys = wParam; xPos = LOWORD(lParam); yPos = HIWORD(lParam);
    • WM_MOUSEWHEEL fwKeys = LOWORD(wParam); zDelta = HIWORD(wParam); xPos = LOWORD(lParam); yPos = HIWORD(lParam);
wince
WinCE绘图
  • 创建设备上下文
  • 创建GDI设备对象
  • 选择GDI设备对象
  • 绘图操作
  • 将GDI设备对象选出
  • 删除自建的GDI对象
  • 删除设备上下文
slide55
创建设备上下文
  • 几个涉及到DC的函数:
    • HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lpPaint );
    • HDC GetDC( HWND hWnd );
    • HDCCreateCompatibleDC(HDChdc);
  • 前两个函数可以得到一个屏幕DC,BeginPaint只能用于对PAINT消息的处理中
  • 第三个函数用于创建一个与当前DC相兼容的DC
slide56
设备上下文简介
  • 当想要在图形输出设备(例如屏幕或打印机)上绘制图形时,必须首先获得设备上下文的句柄。先给出这个句柄,Windows才允许程序使用设备,在GDI函数中将句柄作为一个参数传入,向Windows标明需要使用的设备。
  • 设备上下文中包含许多属性,当GDI在不同的设备上工作时都要用到这些属性。使用这些属性可使GDI只关心起始和终止坐标的大小,而不必关心有关对象的其他属性,如颜色、背景等等,因为这些都是设备上下文的一部分。
  • 设备上下文是连接Windows应用程序、设备驱动程序以及输出设备的纽带。
slide57
GDI对象
  • GDI对象是在绘图过程中的主体,只需要操作GDI对象就可以完成常规的绘图过程。
  • GDI对象的基类名为GDIOBJ,所有的GDI类都是从此派生出来的。
  • 在WinCE下的绘图操作,实际上都是在操作相应的GDI对象,由GDI对象将所有的工作进行转化并发送给驱动程序。
slide58
画笔和画刷
  • 画笔和画刷是最基本的用来绘图的工具。这就像生活中画画一样。首先应该选择用什么样的笔(毛笔或铅笔),再选择画什么样的图形。
  • 画笔是一种GDI对象,有线宽、线型、颜色等属性。Windows GDI提供了两种使用画笔的方法:使用系统备用画笔(Stock Pens)和自定义画笔。
  • 画刷也是一种GDI对象,应用程序常使用逻辑画刷来填充Rectangle,Ellipse, Polygon等图形的内部区域。
wince1
WinCE中的画笔
  • Windows系统提供了三种备用画笔:BLACK_PEN,WHITE_PEN和NULL_PEN。如果使用备用画笔,则程序所做的事情就是用函数GetStockObject获得备用画笔的句柄,并将希望使用的备用画笔选入设备描述表(在默认情况下,设备描述表已经选入了BLACK_PEN)中。
  • hPen = GetStockObject(WHITE_PEN);
  • 上面一条语句得到备用画笔的句柄。
wince2
WinCE中的画刷
  • 一般的画刷是一个8×8的位图,利用水平和垂直的重复来填充这些图形的内部区域。有四种类型的逻辑画刷,分别为solid,stock,hatch和pattern。
  • HBRUSH CreateSolidBrush( COLORREF crColor ); 创建一个实心画刷。
  • HGDIOBJ GetStockObject( int fnObject ) 得到一个系统库存画刷。
  • HBRUSH CreateHatchBrush( int fnStyle, COLORREF clrref )创建一个带纹理的画刷。
  • HBRUSH CreatePatternBrush( HBITMAP hbmp)以为图作为标准创建一个画刷。
slide61
使用画笔和画刷
  • 首先创建一个自己的画笔或画刷
  • 随后将此对象选入设备上下文
    • HGDIOBJ SelectObject( HDC hdc, GDIOBJ hgdiobj )将指定的GDI对象选入dc中,并且返回替换出来的对象的句柄。
  • 进行相关的绘图操作
slide62
常见的绘图操作和绘图函数
  • 画点和画线
    • COLORREF SetPixel(HDC hdc, int nXPos, int nYPos, COLORREF crColor)
    • COLORRE GetPixel(HDChdc, intnXPos, intnYPos)
    • BOOL LineTo(HDC hdc, int nXEnd, int nYEnd)
    • BOOL MoveToEx (HDC hdc, int X, int Y, LPPOINT lpPoint)
  • 绘制曲线
    • BOOL Arc( HDC hdc, int nLeftRect, int nTopRect, int nRightRect,

int nBottomRect, int nXStartArc,

int nYStartArc, int nXEndArc, int nYEndArc )

slide63
常见的绘图操作和绘图函数
  • 绘制填充区域
    • BOOL Rectangle( HDC hdc, int nLeftRect, int nTopRect,int nRightRect, int nBottomRect )
    • BOOL Ellipse( HDChdc, intnLeftRect, intnTopRect,int nRightRect, int nBottomRect )
    • BOOL Pie( HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nXStartArc, int nYStartArc, int nXEndArc, int nYEndArc )
    • BOOL RoundRect(HDC hdc, int nLeftRect, int nTopRect,

int nRightRect, int nBottomRect,

int nWidth, int nHeight)

    • BOOL Polygon(HDC hdc, CONST POINT *lpPoints, int nCount)
slide64
GDI中的位图
  • 位图是一个位数组,将这个位数组映射到输出设备上的矩形像素数组时,就可以创建图像,用位图可以创建、修改和存储图像。
  • WinCE支持两种类型的位图:设备相关位图(DDB)和设备无关位图(DIB)。设备相关位图没有自己的颜色表,因而只有在与创建位图的设备具有相同的显存结构的设备上才能正确的显示,另一方面,设备无关位图通常具有自己的颜色表,因而可以在多种设备上显示。
  • 在基于WinCE应用程序中推荐使用DIB。
slide65
创建DIB的一般方法
  • HBITMAP CreateDIBSection(

HDC hdc,

const BITMAPINFO* pbmi,

UINT iUsage,

void* ppvBits,

HANDLE hSection,

DWORD dwOffset

);

  • BITMAPINFO定义了DIB的尺寸和颜色信息,这个结构包括一个BITMAPINFOHEADE结构和多个RGBQUAD结构组成
slide66
创建DDB的一般方法
  • HBITMAP CreateBitmap(

int nWidth,

int nHeight,

UINT cPlanes,

UINT cBitsPerPel,

CONST VOID* lpvBits

);

  • HBITMAP CreateCompatibleBitmap(

HDC hdc,

int nWidth,

int nHeight

);

slide67
从图像文件创建位图
  • HBITMAP SHLoadDIBitmap(

LPCTSTR szFileName

)

  • 这个函数从一个指定的文件中加载位图,文件格式可以是BMP也可以是JPEG,函数执行后会返回一个位图句柄,当你不再需要这个位图时要调用DeleteObject删除这个位图。
slide68
GDI的字体
  • 在WinCE中,字体是一组共享相同样式的图案符号,字体由他的字样、样式和大小表示。
  • 在WinCE中,字体被分为不同的族,同组内的字体共享相同的笔划宽度特征。同组内的字体有大小和样式进行区分。
slide69
在程序中使用字体
  • 调用EnumFontFamilies生成可用字体列表
  • 用字体枚举函数的返回值初始化LOGFONT结构成员
  • 用CreateFontIndirect创建逻辑字体,并将已经初始化的LOGFONT结构体指针传入
  • 用SelectObject函数将逻辑字体选入当前设备上下文
slide70
内置的六种字体
  • WinCE提供了6种标准的逻辑字体,用GetStockObject函数可以获得。
  • 六种内置的标准字体
    • ANSI_FIXED_FONT 等宽字体
    • ANSI_VAR_FONT 等比例字体
    • DEVICE_DEFAULT_FONT 设备首选字体
    • OEM_FIXED_FONT OEM等宽字体
    • SYSYTEM_FONT 系统字体
ad