1. GDD概述
GDD(The Graphics decorate designer,图形装饰设计师)是建立在Djyos内核与GK(GUI Kernel)之上的一套图形支持系统。它可向用户提供图形绘制,文字显示,窗口/控件管理,窗口定时器,消息通讯机制,以及对外部输入事件(键盘,鼠标)的处理功能。
在整个系统中,它们的层次关系如图 1‑1所示:
|
图 1‑1 GDD在Djyos系统中层次示意图
# 2. 窗口系统 ## 2.1. 窗口分类及关系 ### 2.1.1. GDD窗口就是图形装饰设计师所看见的窗口。
GDD中窗口分为三大类:桌面窗口、主窗口、子窗口,其中,主窗口同时又是桌面的子窗口。
桌面窗口是在系统启动过程中加载显示器驱动时自动创建的,每个显示器对应一个桌面窗口,其中一个桌面是主桌面,通过GDD_GetDesktopWindow函数用于获得桌面窗口句柄,通过句柄可以对桌面窗口进行操作,例如直接在桌面绘制图案,往桌面放置APP图标,绘制特效图标等。
主窗口由用户调用GDD_CreateGuiApp函数创建,它包含应用程序所必须的消息队列和消息循环,该消息循环用于处理该图形APP事件的所有操作,代表一个应用程序,负责整个图形APP的消息事件收集与派发。须特别注意的是,主窗口同时也是桌面的子窗口。
子窗口是用户调用GDD_CreateWindow函数创建,子窗口下可以继续调用GDD_CreateWindow函数创建子窗口,最多可以达到255级,子窗口一般用于应用程序内部的业务实现,典型的子窗口是控件。GDD提供了一些常用标准控件给用户使用,如按钮、复选框、单选框等。
完整的多任务窗口系统一般由一个桌面窗口和若干主窗口组成,在单应用程序的情况下,例如嵌入式系统,也可以没有主窗口,而是直接使用桌面窗口。
三种不同类型窗口示例如图 2‑1所示:
图 2‑1GDD三种窗口示意图
2.1.2. GKernel窗口
所有的GDD窗口均基于一个GKernel窗口,关于GKernel窗口,参见《DJYOS图形编程(下)》。
2.2. 窗口的客户区与非客户区
窗口区域分为客户区与非客户区两部分。在一个窗口中,标题栏,边框就是窗口的非客户区,中间区域称为客户区。它们的关系如图 2‑2所示:
图 2‑2 客户区示意图
2.3. 坐标系统
GDD的所有坐标都是像素数坐标,有三种坐标系统,相互之间是可以转换的,这三种坐标系统分别是:屏幕坐标,窗口坐标,客户坐标。
屏幕坐标以屏幕左上角为坐标原点,水平方向为X值,垂直方向为Y值构成坐标系。
窗口坐标以窗口左上角为坐标原点,水平方向为X值,垂直方向为Y值构成坐标系。
客户坐标以窗口客户区左上角为坐标原点,水平方向为X值、垂直方向为Y值构成坐标系。
三种坐标关系示意图 2‑3如下:
图 2‑3 GDD三种坐标示意图
2.4. 窗口句柄与窗口ID的作用与区别
在窗口程序中,用户会经常和窗口句柄,窗口ID打交道,窗口句柄是由系统自动分配的,无需用户干预,对窗口操作访问,都只能通过句柄进行;而窗口ID,是在创建窗口时,由用户指定的一个任意16位数,一般用于对同级窗口(兄弟窗口)间的标识区分,同级窗口间,它们的ID需由用户创建窗口时保证唯一性,对于不同父窗口下的子窗口,它们的ID是可以重复的;例如一个窗口A和窗口B,它们都可以创建一个指定ID为1的子窗口,这是合法的,另外补充一点,窗口ID是针对来标识子窗口的,因此,桌面窗口及所有主窗口是没有ID标识的概念的。具体请参数 GDD_CreateWindow函数。
2.5. API说明
2.5.1. GDD_GetHwnd: 取窗口句柄
HWND GDD_GetHwnd(struct GkWinObj *gkwin);
头文件:
gdd.h
参数:
gkwin: 窗口所包含的GKernel窗口指针。
返回值:
gdd窗口句柄。
说明:
所有GDD窗口都有对应的GKernel窗口,已知GKernel窗口,可用本函数获取相应的GDD窗口的句柄。
2.5.2. GDD_ScreenToClient: 屏幕坐标转换为客户区坐标
bool_t_t GDD_ScreenToClient(HWND hwnd,POINT *pt,s32 count);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
pt: 需要转换的坐标点,该参数兼作为转换的输入和输出参数。
count: 需要转换的坐标点数量。
返回值:
TRUE:成功; FALSE:失败。
说明:
如果函数返回失败,原因可能是窗口句柄无效,参数pt指针为NULL;另外,该函数不关心需要转换的坐标是否在窗口可视范围内。
2.5.3. GDD_ClientToScreen: 客户区坐标转换为屏幕坐标
bool_t_t GDD_ClientToScreen(HWND hwnd,POINT *pt,s32 count);
头文件:
gdd.h
参数:
Hwnd: 窗口句柄。
pt: 需要转换的坐标点,该参数兼作为转换的输入和输出参数。
count: 需要转换的坐标点数量。
返回值:
TRUE:成功; FALSE:失败。
说明:
如果函数返回失败,原因可能是窗口句柄无效,参数pt指针为NULL;另外,该函数不处理需要转换的坐标是否在窗口可视范围内。
2.5.4. GDD_ScreenToWindow:屏幕坐标转换为窗口坐标
bool_t_t GDD_ScreenToWindow(HWND hwnd,POINT *pt,s32 count);
头文件:
gdd.h
参数:
hwnd: 窗口句柄.
pt: 需要转换的坐标点,该参数兼作为转换的输入和输出参数。
count: 需要转换的坐标点数量。
返回值:
TRUE:成功; FALSE: 失败。
说明:
如果函数返回失败,原因可能是窗口句柄无效,参数pt指针为NULL;另外,该函数不处理需要转换的坐标是否在窗口可视范围内。
2.5.5. GDD_WindowToScreen: 窗口坐标转换为屏幕坐标
bool_t_t GDD_WindowToScreen(HWND hwnd,POINT *pt,s32 count);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
pt: 需要转换的坐标点,该参数兼作为转换的输入和输出参数。
count: 需要转换的坐标点数量。
返回值:
TRUE:成功; FALSE:失败。
说明:
如果函数返回失败,原因可能是窗口句柄无效,参数pt指针为NULL;另外,该函数不处理需要转换的坐标是否在窗口可视范围内。
2.5.6. GDD_GetDesktopWindow: 获得桌面窗口句柄
HWND GDD_GetDesktopWindow(char *display);
头文件:
gdd.h
参数:
Display,显示器名称,NULL则取主桌面。
返回:
桌面窗口句柄。
2.5.7. GDD_GetWindowRect: 获得窗口矩形
bool_t GDD_GetWindowRect(HWND hwnd,RECT *prc);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
prc: 矩形缓冲区。
返回值:
TRUE:成功; FALSE:失败。
说明:
该函数获得窗口边界在屏幕上的矩形位置,以屏幕坐标表示。
2.5.8. GDD_GetClientRect: 获得窗口客户区矩形
bool_t GDD_GetClientRect(HWND hwnd,RECT *prc);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
prc: 矩形缓冲区。
返回值:
TRUE:成功; FALSE:失败。
说明:
该函数获得窗口客户区矩形,以客户区坐标表示,所以获得的矩形左上角坐标恒为0,0;矩形右下角坐标所指示的为客户区宽度和高度。
2.5.9. GDD_GetClientRectToScreen: 取窗口客户区矩形的屏幕坐标
bool_t GDD_GetClientRectToScreen(HWND hwnd,RECT *prc);
头文件:
gdd.h
参数:
hwnd: 窗口坐标。
prc: 矩形缓冲区。
返回值:
TRUE:成功; FALSE:失败。
说明:
该函数获得窗口客户区边界在屏幕上的矩形位置,以屏幕坐标表示。
2.5.10. GDD_GetWindowDC: 获得窗口绘图上下文
HDC GDD_GetWindowDC(HWND hwnd);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
返回值:
窗口绘图上下文句柄。
说明:
该函数获得的绘图上下文,可以在整个窗口范围内(非客户区+客户区)绘图。绘图上下文的原点坐标(0,0)为窗口边界最左上角,在结束绘图后,需调用ReleaseDC来释放该绘图上下文。
2.5.11. GDD_GetDC:获得窗口客户区绘图上下文
HDC GDD_GetDC(HWND hwnd);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
返回值:
窗口客户区绘图上下文句柄。
说明:
该函数获得的绘图上下文,只能在窗口客户区范围内绘图,绘图上下的原点坐标(0,0)为窗口客户区边界最左上角,在结束绘图后,需调用 ReleaseDC 来释放该绘图上下文。
### 2.5.12. GDD_ReleaseDC: 释放一个绘图上下文bool_t GDD_ReleaseDC(HWND hwnd,HDC hdc);
头文件:
gdd.h
参数::
hwnd: 绘图上下文所属的窗口句柄。
hdc: 需要释放的绘图上下文句柄。
返回值:
TRUE:成功; FALSE:失败。
说明:
该函数只能释放由 GetWindowDC,GetDC 所返回的绘图上下文句柄。
2.5.13. GDD_BeginPaint: 开始绘图
HDC GDD_BeginPaint(HWND hwnd);
头文件:
gdd.h
参数:
hwnd: 需要开始绘图的窗口句柄。
返回值:
绘图上下文句柄。
说明:
该函数只在窗口过程函数的 MSG_PAINT 消息中使用,指示客户区开始绘图;该函数返回的绘图上下文句柄,只能在窗口客户区范围内绘图, 原点坐标(0,0)为窗口客户区边界最左上角, 在结束绘图后,需调用 EndPaint 来释放该绘图上下文。
2.5.14. GDD_EndPaint: 结束绘图
bool_t GDD_EndPaint(HWND hwnd,HDC hdc);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
hdc: 需要结束绘图的绘图上下文句柄。
返回值:
TRUE:成功; FALSE:失败。
说明:
该函数只在窗口过程函数的 MSG_PAINT 消息中与 BeginPaint 成对使用,指示绘图结束并释放由BeginPaint所返回的绘图上下文句柄。
2.5.15. GDD_CreateWindow: 创建窗口
HWND GDD_CreateWindow(WNDPROC *pfWinProc,LPCWSTR Text,u32 Style,
s32 x, s32 y, s32 w, s32 h,HWND hParent,u32 WinId,const void *pdata);
头文件:
gdd.h
参数:
pfWinProc: 窗口过程函数地址。
Text: 窗口标题文字。
Style: 窗口风格属性标记,高16位为窗口公共风格属性标记,所有窗口适用;低16位窗口私有的风格属性标记,代表窗口的私有行为或外观,对于不同类型的窗口,私有风格属性值所代表的含义,仅作用于本身,不可以用于其它不同类型的窗口;不管是公共还是私有风格属性,系统都定义了相关的宏常量供用户使用,对于窗口公共风格属性,可以是以下值的组合:
WS_VISIBLE: 设定该标志,则窗口为可见的;
WS_DISABLE: 设定该标志,刚窗口为禁止状态,将不会响应外部的输入消息,如键盘,鼠标消息等等;
WS_BORDER: 设定该标志,则窗口会包含并显示外边框;
WS_DLGFRAME: 设定该标志,则窗口会包含并显示内边框;
WS_CAPTION: 设定该标志,刚窗口会包含并显示标题栏;
私有风格属性有以下定义,详情见gdd.h。
// 按钮风格
BS_TYPE_MASK: 类型掩码;
BS_NORMAL: 常规按钮;
BS_HOLD: 自锁按钮;
BS_RADIO: 单选按钮;
BS_SURFACE_MASK: 外观掩码;
BS_NICE: 美观风格;
BS_SIMPLE: 简朴风格;
BS_FLAT: 平面风格;
BS_PUSHED: 按钮按下;
// 复选框风格
CBS_SELECTED: 复选框选中。
x,y,w,h: 指示窗口的位置和大小,位置是相对于该窗口所属的父窗口的客户区偏移量,即使用的是客户区坐标表示。大小表示窗口的水平和垂直方向所占的像素数量。
hParent: 父窗口句柄,如果是创建主窗口(没有指定WS_CHILD属性),该参数设为NULL。
WinId: 用户指定的窗口ID,如果是主窗口,该参数会被忽略; 如果是同一级子窗口,则需要为每个指定为不同ID,如果指定了一个已有的同级窗口ID,该函数将创建窗口失败,返回NULL。
pData: 用户自定义的窗口私有数据,该参数会传入窗口过程的MSG_CREATE消息的param1中,如果不需要窗口私有数据,可以将该参数设为NULL。
返回值:
新创建的窗口句柄;如果创建失败,该函数返回NULL。
2.5.16. GDD_DestroyWindow: 销毁窗口
void GDD_DestroyWindow(HWND hwnd);
头文件:
gdd.h
参数:
hwnd: 需要销毁的窗口句柄。
说明:
该函数用来销毁一个窗口,除了销毁窗口本身,也会销毁窗口所属的所有子窗口和定时器,如果用户不调用该函数来销毁所创建的子窗口,当主窗口退出时,也会自行销毁所有子窗口和定时器,如果所销毁的窗口是焦点窗口,那么它所在的父窗口的焦点窗口对象会被设为NULL。
2.5.17. GDD_MoveWindow: 移动窗口位置
bool_t GDD_MoveWindow(HWND hwnd,s32 x, s32 y);
头文件:
gdd.h
参数:
hwnd: 需要移动的窗口句柄。
x,y: 移动后,新的坐标位置。
返回值:
TRUE:成功; FALSE:失败。
说明:
该函数使用的坐标是相对于父窗口的客户区位置,即父窗口的客户区坐标。如果移动一个窗口并超出它所属的父窗口客户区范围,那么,超出的部分是会被裁剪的(不可见).如图2‑4所示:
图2‑5 窗口裁剪示意图
2.5.18. GDD_OffsetWindow: 偏移窗口位置
bool_t GDD_OffsetWindow(HWND hwnd,s32 dx,s32 dy);
头文件:
gdd.h
参数:
hwnd: 需要偏移的窗口句柄。
dx,dy: 水平,垂直方向的偏移量。
返回值:
TRUE:成功; FALSE:失败。
说明:
当dx为负数时,窗口向左偏移,否则向右偏移;当dy为负数时,窗口向上偏移,否则向下偏移。
2.5.19. GDD_IsWindowVisible: 判断窗口是否可见
bool_t GDD_IsWindowVisible(HWND hwnd);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
返回值:
TRUE:窗口可见; FALSE:窗口不可见。
说明:
如果一个窗口为不可见,那么它所属的所以子窗口也都为不可见,即便子窗口设置了WS_VISIBLE标记。更多的内容,请参考ShowWindow函数说明。
2.5.20. GDD_InvalidateWindow: 设置窗口为无效状态
bool_t GDD_InvalidateWindow(HWND hwnd,bool_t bErase);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
bErase:是否重绘窗口背景。
返回值:
TRUE:成功; FALSE:失败。
说明:
设置窗口为无效状态,即意味着窗口需要进行重绘,该函数会给指定的窗口产生一条异步方式的窗口绘制消息:MSG_PAINT,MSG_PAINT是属于低优先级处理的消息,只有当其它消息处理完成后(MSG_TIMER除外,这个优先级更低),才会处理窗口绘制操作,如果系统因繁忙导致前面的绘制消息未能及时处理,系统将对后续重复的同一个窗口的多个绘制消息合并为一个,以减少系统负担,以过滤掉不必要的多余的绘制过程。当bErase参数为TRUE时,窗口过程将会在执行MSG_PAINT前,发送一条MSG_ERASEBKGND消息,用于窗口背景重绘,用户可以在窗口过程函数中,响应MSG_ERASEBKGND消息来实现窗口背景的绘制工作。
2.5.21. GDD_ShowWindow: 设置窗口为显示或隐藏状态
bool_t GDD_ShowWindow(HWND hwnd,bool_t bShow);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
bShow: 显示标记,当为TRUE时,设置窗口为显示状态(可见状态);为FALSE时,将设置窗口为隐藏状态。
返回值:
TRUE: 成功; FALSE:失败。
说明:
该函数为设置窗口是否显示或隐藏,即设置或清除窗口的WS_VISIBLE标记,需要注意的是:如果该窗口所属的父窗口为隐藏状态(不可见),那么它的所有子窗口都不会被显示,即便子窗口设置为显示状态(WS_VISIBLE);改变父窗口的显示状态标志时,并不会改变它所属的子窗口显示状态标志。例如,假设起先一个父窗口A和它的一个子窗口B都为隐藏状态(不可见,无WS_VISIBLE标记),这时,如果将父窗口设置为显示状态(可见,设置了WS_VISIBLE标记),那么此时,它的子窗口B仍然不会显示出来。总结来说,一个窗口真正可见,除了窗口本身具备可见属性(WS_VISIBLE)之外,还必须它的所有上级父窗口同时都具备可见属性。
2.5.22. GDD_EnableWindow: 设置窗口为使能或禁止状态
bool_t GDD_EnableWindow(HWND hwnd,bool_t bEnable);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
bEnable: 标记状态,当为TRUE时,设置窗口为使能状态;为FALSE时,设置窗口为禁止状态。
返回值:
TRUE:成功; FALSE:失败。
说明:
该函数为设置窗口是否使能或禁止,即设置或清除窗口的WS_DISABLE标记,当窗口为禁止状态(设置了WS_DISABLE标记)时,它将不能接收到外部输入事件产生的消息,如键盘,鼠标/触摸屏产生的消息,但如果用户通过SendMessage/PostMessage函数强制向窗口发送这类消息,窗口是可以正常接收到的;一个窗口只有当他的上级所有父窗口及窗口本身都使能时,该窗口才真正允许接收到外部输入事件产生的消息,这种关系与ShowWindow函数类似。需要注意的是禁止状态的窗口是可见的并且能绘制。
2.5.23. GDD_GetParent: 获得父窗口句柄
HWND GDD_GetParent(HWND hwnd);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
返回值:
父窗口句柄。
2.5.24. GDD_GetWindow: 获得与指定窗口有特定关系的窗口句柄
HWND GDD_GetWindow(HWND hwnd,s32 nCmd);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
nCmd: 说明指定窗口与要获得句柄的窗口之间的关系,该参数值可以是下列之一:
GW_CHILD: 获得z序顶端的子窗口。
GW_HWNDPREV: 获得z序上一个同级窗口。
GW_HWNDNEXT: 获得z序下一个同级窗口。
GW_HWNDFIRST: 获得z序顶层的同级窗口。
GW_HWNDLAST: 获得z序底层的同级窗口。
返回值:
特定关系的窗口句柄。
2.5.25. GDD_SetWindowText:设置窗口文字
void GDD_SetWindowText(HWND hwnd,const char *text,s32 max_len);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
text:需要设置的字符串内容。
max_len:最大字符串字节长度,如果该值是负数,则使用整个字符串实际字节长度;如果该值小于实际的字符串字节长度,且大于0,则字符串多余的部分将会被截断;如果该值大于实际的字符串字节长度,则按实际的字符串长度来处理。
返回值:
无。
2.5.26. GDD_GetWindowText:获得窗口文字
char* GDD_GetWindowText(HWND hwnd,char *text,s32 max_len);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
text:输出的字符串缓冲区。
max_len:最大字符串字节长度,如果该值是负数,则使用窗口整个字符串实际字节长度;如果该值小于实际的字符串字节长度,且大于0,则字符串多余的部分将会被截断;如果该值大于窗口实际的字符串字节长度,则按实际的字符串长度来处理。
返回值:
字符串指针。
2.5.27. GDD_GetWindowFromPoint: 获得指定屏幕坐标位置所在的窗口
HWND GDD_GetWindowFromPoint(POINT *pt);
头文件:
gdd.h
参数:
pt: 坐标位置点参数,该坐标值使用屏幕坐标。
返回值:
坐标所在的窗口句柄。
说明:
在多级窗口丛属关系中,该函数返回的窗口句柄,将会是坐标所在位置的最低级别的窗口。
2.5.28. GDD_SetFocusWindow:设置当前焦点窗口
HWND GDD_SetFocusWindow(HWND hwnd);
头文件:
gdd.h
参数:
hwnd: 新的焦点窗口句柄,如果该值为NULL,则会清除当前焦点窗口。
返回值:
旧的焦点窗口句柄,如果当前无焦点窗口,返回NULL。
说明:
调用该函数时,新的焦点窗口,将会收到MSG_SETFOCUS消息,旧的焦点窗口,将会收到MSG_KILLFOCUS消息。当一个窗口设为当前焦点窗口时,才能收到键盘产生的消息:MSG_KEY_DOWN及MSG_KEY_UP。
2.5.29. GDD_GetFocusWindow:获得当前焦点窗口
HWND GDD_SetFocusWindow(HWND hwnd);
头文件:
gdd.h
参数:
无。
返回值:
当前焦点窗口句柄,如果当前无焦点窗口,返回NULL。
2.5.30. GDD_IsFocusWindow:判断指定窗口是否为当前焦点窗口
bool_t GDD_IsFocusWindow(HWND hwnd);
头文件:
gdd.h
参数:
无。
返回值:
TURE:指定的窗口是当前焦点窗口;FALSE:指定的窗口不是当前焦点窗口。
2.5.31. GDD_DefWindowProc: 系统默认的窗口消息处理函数
u32 GDD_DefWindowProc(MSG *pMsg);
头文件:
gdd.h
参数:
pMsg: 需要处理的消息。
返回值:
消息处理结果。
说明:
在窗口过程中函数中,对于用户不感兴趣的消息,需调用该函数,交由系统默认处理。
3. 绘图系统
3.1. 概述
3.1.1. 绘图上下文
用户所有的绘图操作,都需要在一个绘图上下文上进行(以下简称DC)。DC中记录着一些绘制参数,如各类颜色值,当前使用字体等等,用户通过设置这些参数,来改变绘图行为和效果。多个绘图上下文可同时使用,通过信号量保证了线程使用绘图上下文的安全性。
3.1.2. DrawColor,FillColor,TextColor的作用与区别
绘图上下文中,使用了三种颜色参数,分别如下:
DrawColor: 绘制色(画笔),用于绘制线条,空心图形,如DrawLine,DrawCircle;
FillColor: 填充色(画刷),用于复辅音实心图形,如FillRect,FillCircle;
TextColor: 文字颜色,用于文字绘制时指定字体的颜色;
绘图上下文中的颜色值,用户可以使用RGB宏来表示,该宏的3个参数依次分别代表红,绿,蓝三基色,分量范围为0~255.比如可以用以下方式来描述:
红色:RGB(255,0,0)
绿色:RGB(0,255,0)
黄色:RGB(255,255,0)
白色:RGB(255,255,255)
黑色:RGB(0,0,0)
之所以使用3个颜色来分别作用于不同的绘图输出,好处是在用户编程时,当绘制的图形种类多样,与字体混合绘制时,可以减少用户代码反复修改/切换颜色的情况,丛用户角度来看,降低了使用上的繁琐度,增强程序的可读性。
三种颜色使用对象如图 3‑1所示:
图 3‑1三种颜色效果示意图
3.2. API说明
3.2.1. GDD_SetRopCode: 设置当前光栅码
u32 GDD_SetRopCode(HDC hdc,u32 rop_code);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
rop_code: 新的光栅码,关于光栅码含义,请参考gkernel.h。
返回值:
旧的光栅码。
3.2.2. GDD_GetRopCode: 获得当前光栅码
u32 GDD_GetRopCode(HDC hdc);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
返回值:
当前光栅码。
3.2.3. GDD_MoveTo: 设置当前坐标位置
void GDD_MoveTo(HDC hdc,s32 x,s32 y,POINT *old_pt);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
x,y: 新的坐标位置。
old_pt: 输出旧的坐标位置,如果该参数为NULL,则忽略该参数。
返回值: 无。
3.2.4. GDD_SetDrawColor: 设备当前画笔颜色
u32 GDD_SetDrawColor(HDC hdc,u32 color);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
color: 新的画笔颜色。
返回值:
旧的画笔颜色。
说明:
当前画笔颜色会被绘制类绘图函数使用,如DrawLine,DrawRect…
3.2.5. GDD_GetDrawColor: 获得当前画笔颜色
u32 GDD_GetDrawColor(HDC hdc);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
返回值:
当前画笔颜色。
3.2.6. GDD_SetFillColor: 设置当前填充颜色
u32 GDD_SetFillColor(HDC hdc,u32 color);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
color: 新的填充颜色。
返回值:
旧的填充颜色。
说明:
当前填充颜色会被填充类绘图函数使用,如FillRect,FillCircle…
3.2.7. GDD_GetFillColor: 获得当前填充颜色
u32 GDD_GetFillColor(HDC hdc);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
返回值:
当前填充颜色。
3.2.8. GDD_SetTextColor: 设置当前文字颜色
u32 GDD_SetTextColor(HDC hdc,u32 color);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
color: 新的文字颜色。
返回值:
旧的文字颜色。
说明:
当前文字颜色会被文字绘制类函数使用,如TextOut,DrawText…
3.2.9. GDD_GetTextColor: 获得当前文字颜色
u32 GDD_GetTextColor(HDC hdc);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
返回值:
当前文字颜色。
3.2.10. GDD_SetFont: 设置当前字体
HFONT GDD_SetFont(HDC hdc,HFONT hFont);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
hFont: 新的字体句柄。
返回值:
旧的字体句柄。
说明:
当前字体会被文字绘制类函数使用,如TextOut,DrawText…
3.2.11. GDD_GetFont: 获得当前字体
HFONT GDD_GetFont(HDC hdc);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
返回值:
当前字体句柄。
3.2.12. GDD_SetPixel: 绘制像素
void GDD_SetPixel(HDC hdc,s32 x,s32 y,u32 color);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
x,y: 像素点的坐标。
color: 颜色值。
返回值: 无。
3.2.13. GDD_DrawLine: 画线
void GDD_DrawLine(hdc hdc,s32 x0,s32 y0,s32 x1,s32 y1);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
x0,y0: 起始坐标。
x1,y1: 结束坐标,该点也会被绘制。
返回值: 无。
该函数只绘制单个像素宽度的任意直线,使用绘图上下文中的DrawColor作为颜色值,结束坐标点,也将会被绘制。
3.2.14. GDD_DrawLineTo: 使用当前位置画线
void GDD_DrawLineTo(HDC hdc,s32 x,s32 y);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
x,y: 结束坐标位置,该点也会被绘制。
返回值: 无。
该函数只绘制单个像素宽度的任意直线,使用绘图上下文中的DrawColor作为颜色值。
绘制完成后,该函数会将绘图上下文中的当前坐标位置更新为本次画线的结束坐标值。
3.2.15. GDD_TextOut: 在指定位置绘制字符串
bool_t GDD_TextOut(HDC hdc, s32 x, s32 y,LPCWSTR text,s32 count);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
text: 需要绘制的字符串。
count: 需要绘制的字符数量,该参数小于0时,将绘制整个字符串。
x,y两个参数没说明,是字符串的左上角坐标还是左下角坐标?
返回值:
TRUE:成功; FALSE:失败。
说明:
输出的字符串,使用绘图上下文中的TextColor作为颜色值,支持回车和换行符格式,当字符串超出屏幕范围时,不会自动换行,而是直接裁剪掉。
3.2.16. GDD_DrawText: 在指定矩形内绘制字符串
bool_t GDD_DrawText(HDC hdc,LPWSTR text,s32 count,const RECT *prc,u32 flag);
头文件::
gdd.h
参数:
hdc: 绘图上下文句柄。
text: 需要绘制的字符串。
count: 需要绘制的字符数量,该参数小于0时,将绘制整个字符串。
prc: 字符串输出的矩形。
flag: 绘制标记,指定字符串在竖直方向位置有以下三种情形:
DT_VCENTER: 文字在矩形内垂直居中对齐;
DT_TOP: 文字在矩形内顶部对齐;
DT_BOTTOM: 文字在矩形内底部对齐。
指定字符串在水平方向位置也有以下三种情形:
DT_CENTER: 文字在矩形内水平居中对齐;
DT_LEFT: 文字在矩形内左对齐;
DT_RIGHT: 文字在矩形内右对齐;
其他情形有:
DT_BORDER: 绘制矩形边框。
DT_BKGND: 绘制矩形背景。
绘制标记flag从竖直方向及水平方向位置三种情形中各选取其一与其他情形中两个任意组合。
返回值:
TRUE:成功; FALSE:失败。
说明:
输出的字符串,使用绘图上下文中的TextColor作为颜色值,支持回车和换行符格式。;绘制矩形边框,使用绘图上下文中的DrawColor作为颜色值;填充矩形背景,使用绘图上下文中的FillColor作为颜色值。
3.2.17. GDD_DrawRect: 绘制矩形
void GDD_DrawRect(HDC hdc,const RECT *prc);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
prc: 需要绘制的矩形参数。
返回值: 无
说明:
该函数使用绘图上下文中的DrawColor作为颜色值,绘制一个空心矩形。
3.2.18. GDD_FillRect: 填充矩形
void GDD_FillRect(HDC hdc,const RECT *prc);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
prc: 需要填充的矩形参数。
返回值: 无
说明:
该函数使用绘图上下文中的FillColor作为颜色值,填充一个实心矩形。
3.2.19. GDD_FillRectEx: 使用指定颜色填充矩形
void GDD_FillRectEx(HDC hdc,const RECT *prc,u32 color);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
prc: 需要填充的矩形参数。
color: 填充颜色。
返回值: 无
说明:
该函数使用指定的颜色值,填充一个实心矩形。
3.2.20. GDD_GradientFillRect: 渐变填充矩形
void GDD_GradientFillRect(HDC hdc,const RECT *prc,u32 color1,u32 color2,u32 mode);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
prc: 需要绘制的矩形参数。
color1: 起始颜色值。
color2: 结束颜色值。
mode: 填充模式,可以是以下值之一:
CN_FILLRECT_MODE_H: 水平填充,Color0表示左边颜色,Color1右边;
CN_FILLRECT_MODE_V: 垂直填充,Color0表示上边颜色,Color1下边;
CN_FILLRECT_MODE_SP: 倾斜填充,Color0表示左上角颜色,Color1右下角;
CN_FILLRECT_MODE_SN: 倾斜填充,Color0表示右上角颜色,Color1左下角。
返回值: 无。
3.2.21. GDD_DrawCircle: 绘制空心圆
void GDD_DrawCircle(HDC hdc,s32 cx,s32 cy,s32 r);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
cx,cy: 需要绘制的圆形的中心坐标。
r: 需要绘制的圆形的半径值(像素单位)
返回值: 无
说明:
该函数使用绘图上下文中的DrawColor作为颜色值,绘制一个空心圆。
3.2.22. GDD_FillCircle: 填充实心圆
void GDD_DrawCircle(HDC hdc,s32 cx,s32 cy,s32 r);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
cx,cy: 需要绘制的圆形的中心坐标。
r: 需要绘制的圆形的半径值(像素单位)
返回值: 无
说明:
该函数使用绘图上下文中的FillColor作为颜色值,填充一个实心圆。
3.2.23. GDD_DrawEllipse: 绘制空心椭圆
void GDD_DrawEllipse(HDC hdc,s32 cx,s32 cy,s32 rx,s32 ry);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
cx,cy: 需要绘制的椭圆的中心坐标。
rx,ry:需要绘制的椭圆的水平和垂直方向半径值(像素单位)
返回值: 无
说明:
该函数使用绘图上下文中的DrawColor作为颜色值,绘制一个空心椭圆。
3.2.24. GDD_FillEllipse: 填充实心椭圆
void GDD_FillEllipse(HDC hdc,s32 cx,s32 cy,s32 rx,s32 ry);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
cx,cy: 需要填充的椭圆的中心坐标。
rx,ry:需要填充的椭圆的水平和垂直方向半径值(像素单位)
返回值: 无
说明:
该函数使用绘图上下文中的FillColor作为颜色值,绘制一个实心椭圆。
3.2.25. GDD_DrawSector: 绘制空心扇形
void GDD_DrawSector(HDC hdc,s32 cx,s32 cy,s32 r,s32 a1,s32 a2);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
cx,cy: 需要绘制的扇形的中心坐标。
r:需要绘制的扇形的值(像素单位) 。
a1,a2:需要绘制的扇形的起始和结束角度。
返回值: 无
说明:
该函数使用绘图上下文中的DrawColor作为颜色值,绘制一个空心扇形。
3.2.26. GDD_FillSector: 填充实心扇形
void GDD_FillSector(HDC hdc,s32 cx,s32 cy,s32 r,s32 a1,s32 a2);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
cx,cy: 需要填充的扇形的中心坐标。
r:需要填充的扇形的值(像素单位) 。
a1,a2:需要填充的扇形的起始和结束角度。
返回值: 无
说明:
该函数使用绘图上下文中的FillColor作为颜色值,填充一个实心扇形。
3.2.27. GDD_DrawBezier3: 绘制连续3阶贝塞尔线
void GDD_DrawBezier3(HDC hdc,const POINT *pt,s32 count);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
pt: 需要绘制的贝塞尔线的坐标点。
count: 需要绘制的贝塞尔线的坐标点数量。
返回值: 无。
说明:
该函数使用绘图上下文中的DrawColor作为颜色值。
3.2.28. GDD_DrawPolyLine: 绘制折线
void GDD_DrawPolyLine(HDC hdc,const POINT *pt,s32 count);
头文件:
gdd.h
参数:
hdc: 绘图上下文句柄。
pt: 需要绘制的曲线的坐标点。
count: 需要绘制的曲线的坐标点数量。
返回值: 无。
说明:
该函数使用绘图上下文中的DrawColor作为颜色值。
3.2.29. GDD_DrawGroupBox: 绘制组合框
void GDD_DrawGroupBox(HDC hdc,const RECT *prc,const WCHAR *text);
头文件::
gdd.h
参数:
hdc: 绘图上下文句柄。
prc: 需要绘制的组合框的矩形参数。
text: 组合框文字内容。
返回值: 无。
说明:
组合框是将文本框和列表框的功能融合在一起的一种控件。用户既可以在文本框中输入,也可以从列表框中选择一个列表项来完成输入。
该函数使用设备上下文中的TextColor作为组合框的文字颜色值;使用DrawColor作为组合框边框颜色值。 组合框可用于对用户绘制的内容进行分组标识,这使得界面在视觉效果上更加整洁美观;界面内容也更加直观明了。
3.2.30. GDD_DrawBMP:绘制BMP格式图片
void GDD_DrawBMP(HDC hdc,s32 x,s32 y, const void *bmp_data);
头文件::
gdd.h
参数:
hdc: 绘图上下文句柄。
x,y: 绘制到hdc中的坐标位置。
bmp_data: bmp格式图片的数据源。
返回值: 无。
说明:bmp格式图片的数据源必须是完整的BMP文件原始数据,包含有BMP的文件头信息。
3.2.31. GDD_AlphaBlendColor: 计算两个颜色按Alpha混合后的颜色值
u32 GDD_AlphaBlendColor(u32 bk_c,u32 fr_c,u8 alpha);
头文件:
gdd.h
参数:
bk_c: 背景色(XRGB8888格式)。
fr_c: 前景色(XRGB8888格式)。
apha: Alpha分量值(0~255范围)。
返回值:
混合后的颜色值(XRGB8888格式)。
说明:
Alpha颜色混合公式为: 显示颜色=源颜色×alpha/255+背景颜色×(255-alpha)/255;
3.2.32. GDD_SyncShow: 更新显示到屏幕
void GDD_SyncShow(HWND hwnd);
头文件:
gdd.h
参数:
hwnd:所属窗口。
返回值: 无。
更新整个显示器,而不仅仅是hwnd所在的窗口。hwnd的意义是什么呢?每个主窗口(含桌面窗口)都有自己的消息队列,调用GDD_SyncShow,在更新显示前,将先把hwnd对应主窗口的消息队列中的消息全部执行。为什么是更新整个显示器呢?因为从上次更新到本次更新之间,hwnd所在主窗口的绘制操作可能导致其他主窗口可视域改变,如不刷新,可能出现显示错乱的情况。
4. 消息系统
4.1. 概述
消息系统是建立在事件调度系统和窗口系统之上的、用于处理复杂的图形应用程序的业务逻辑的系统,业务逻辑的不同环节之间,用消息传递来简化应用程序业务之间错综复杂的关系,简化编程。图形应用程序只需要处理收到的消息,再把产生的业务请求抽象成消息发送出去。
在整个系统中的关系层次如所示:
|
图 4‑1 消息系统在GDD中层次示意图
程序运行过程中产生的消息,将保存在消息队列中,每个主窗口(桌面窗口)有一个消息队列,往一个窗口发送消息,实际上是把消息发到该窗口对应的主窗口(桌面窗口)的消息队列。
每个主窗口有一个事件处理函数,该函数处理所有发到该窗口的消息。
4.2. 同步消息与异步消息
消息发送方式分为同步发送与异步发送两种,系统提供两个API函数:GDD_SendMessage,GDD_PostMessage,分别用于两种不同的消息发送方式,它们的区别如下:
GDD_SendMessage: 用于同步消息发送,消息直接发送到目标窗口的窗口过程函数中,直到该条消息被窗口过程函数处理完成后,该函数才会返回。
GDD_PostMessage: 用于异步消息发送,消息发送到目标窗口所属的消息队列中后,不等待处理完成,便立即返回。
4.3. 消息队列及消息循环与窗口的关系
因为异步消息不需要立即处理,所有主窗口和桌面窗口,都有自己的消息队列,用于缓存异步消息。对子窗口发送异步消息时,实际是将消息发送到了它所属的主窗口消息队列中。在窗口入口函数中,调用GDD_GetMessage函数从主窗口消息队列中取出一条消息,若成功取出一条消息,则调用GDD_DispatchMessage函数派发该消息,所谓派发消息其实就是间接调用主窗口的窗口过程函数处理该消息。在窗口入口函数中获取消息及派发消息实例代码如下:
if( (msg.Code == MSG_CLOSE) && (msg.hwnd == MyHwnd) ) { result = GDD_DispatchMessage(&msg); break; } else result = GDD_DispatchMessage(&msg);
if(SyncMsg) //若是同步消息,则要返回处理结果,并释放信号量。 { MyHwnd->pMsgQ->sync_msg.Param1 = result; Lock_SempPost(MyHwnd->pMsgQ->sem_sync_send); } |
4.4. 窗口过程函数及消息数据结构
所有的成功发送出来的消息,无论是同步还异步方式发送,最终都会调用到该窗口提供的对应的消息处理函数中,用户在这里可以对接收到的各类消息进行响应处理。有部分消息,窗口系统提供了默认处理函数,可以将该消息交给系统默认处理。消息处理函数被调用时会传入当前接收到的消息数据结构。该数据结构如下:
typedef struct tagMSG
{
HWND hwnd;
u32 Code;
u32 Param1;
u32 Param2;
const void* ExData;
}MSG;
该结构各成员作用如下:
hwnd: 该条消息所属的目标窗口句柄;
Code: 消息代码值;
Param1: 消息参数1,不同消息代码,该参数意义不同;
Param1: 消息参数2,不同消息代码,该参数意义不同;
ExData: 消息扩展数据,不同消息代码,该参数意义不同。
4.5. 消息代码及参数说明
系统为用户定义了一系列通用消息代码,以下是这些消息的详细说明。
4.5.1. 窗口系统消息参数说明
消息名 |
消息说明 |
消息参数说明 |
MSG_CREATE |
创建窗口 |
Param1:由GDD_CreateWindow 的pdata传入,可用于多个窗口 共用一个消息处理函数时区分窗口。 Param2:忽略 |
MSG_CLOSE |
窗口关闭 |
|
MSG_ERASEBKGND |
窗口背景擦除 |
Param1:绘图上下文; Param2:用户定义 |
MSG_NCPAINT |
窗口非客户区绘制 |
Param1:用户定义; Param2:用户定义 |
MSG_PAINT |
窗口客户区绘制 |
Param1:用户定义; Param2:用户定义 |
MSG_TIMER |
定时器定时时间到 |
Param1:定时Id; Param2:定时器对象. |
MSG_TIMER_START |
启动定时器命令 |
Param1:定时Id; Param2:定时器对象. |
MSG_TIMER_STOP |
停止定时器命令 |
Param1:定时Id; Param2:定时器对象. |
MSG_SETTEXT |
设置窗口标题 |
无 |
MSG_GETTEXT |
获得窗口标题 |
无 |
MSG_GETTEXTLEN |
获得窗口标题长度 |
无 |
MSG_SETFOCUS |
窗口获得焦点,键盘输入将送到本窗口 |
|
MSG_KILLFOCUS |
窗口失去焦点 |
|
MSG_SYNC_DISPLAY |
刷新显示 |
无 |
特别说明:
MSG_ERASEBKGND消息:
如果创建窗口时指定了要擦除窗口客户区(调用GDD_CreateWindow没有设定WS_UNFILL风格),或者调用GDD_InvalidateWindow函数bErase参数为true之后,首次次调用调用GDD_BeginPaint函数时,GDD_BeginPaint函数内部将会先以同步方式发送该消息,先擦除窗口背景;具体参考: GDD_InvalidateWindow: 设置窗口为无效状态
MSG_TIMER
当一个定时器定时时间到来时,便会发送该消息到定时器所属的窗口,如果该定时器产生的消息未被窗口处理完成,那么该定时器将不会再重复产生MSG_TIMER消息。
4.5.2. input设备消息参数说明
消息名 |
消息说明 |
消息参数(L16表示低16位,H16类推) |
MSG_LBUTTON_DOWN |
鼠标左键按下 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_LBUTTON_UP |
鼠标左键弹起 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_RBUTTON_DOWN |
鼠标右键按下 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_RBUTTON_UP |
鼠标右键弹起 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_MBUTTON_DOWN |
鼠标中键按下 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_MBUTTON_UP |
鼠标中键弹起 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_MOUSE_MOVE |
鼠标移动 |
Param1:L16:X方向滑动速度μm/mS H16:Y方向滑动速度μm/mS Param2::x坐标(L16),y坐标(H16) |
MSG_NCLBUTTON_DOWN |
非客户区鼠标左键按下 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_NCLBUTTON_UP |
非客户区鼠标左键弹起 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_NCRBUTTON_DOWN |
非客户区鼠标右键按下 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_NCRBUTTON_UP |
非客户区鼠标右键弹起 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_NCMBUTTON_DOWN |
非客户区鼠标中键按下 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_NCMBUTTON_UP |
非客户区鼠标中键弹起 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_NCMOUSE_MOVE |
非客户区鼠标移动 |
Param1:L16:X方向滑动速度μm/mS H16:Y方向滑动速度μm/mS Param2::x坐标(L16),y坐标(H16) |
MSG_KEY_DOWN |
键盘按下 |
Param1: 按键值; Param2:事件产生的时间(毫秒) |
MSG_KEY_UP |
键盘弹起 |
Param1: 按键值; Param2:事件产生的时间(毫秒) |
MSG_TOUCH_DOWN |
窗口客户区域接触触摸屏 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_TOUCH_UP |
窗口客户区域离开触摸屏 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_TOUCH_MOVE |
手指在屏上窗口客户区域滑动 |
Param1:L16:X方向滑动速度μm/mS H16:Y方向滑动速度μm/mS Param2::x坐标(L16),y坐标(H16) |
MSG_NCTOUCH_DOWN |
窗口非客户区域接触触摸屏 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_NCTOUCH_UP |
窗口非客户区域离开触摸屏 |
Param1:忽略; Param2:x坐标(L16),y坐标(H16) |
MSG_NCTOUCH_MOVE |
手指在屏上窗口非客户区域滑动 |
Param1:L16:X方向滑动速度μm/mS H16:Y方向滑动速度μm/mS Param2::x坐标(L16),y坐标(H16) |
4.6. API说明
4.6.1. DispatchMessage: 派发消息
u32 DispatchMessage(MSG *pMsg);
头文件:
gdd.h
参数:
pMsg: 需要派发的消息。
返回值:
消息处理结果。
说明:
该函数只在主窗口消息循环中使用。
4.6.2. SendMessage: 以同步方式发送消息
u32 SendMessage(HWND hwnd,u32 msg,u32 param1,u32 param2);
头文件::
gdd.h
参数:
hwnd: 消息发送的目的窗口句柄。
msg: 消息代码。
param1: 消息参数1,不同消息,该参数意义不同。
param2: 消息参数2,不同消息,该参数意义不同。
说明:
该函数以同步方式发送消息,支持跨线程发送消息到指定窗口,直到该消息被窗口处理完成后,该函数才会返回。
4.6.3. PostMessage: 以异步方式发送消息
bool_t PostMessage(HWND hwnd,u32 msg,u32 param1,u32 param2);
头文件::
gdd.h
参数:
hwnd: 消息发送的目的窗口句柄。
msg: 消息代码。
param1: 消息参数1,不同消息,该参数意义不同。
param2: 消息参数2,不同消息,该参数意义不同。
返回值:
TRUE: 成功; FALSE: 失败。
说明:
该函数以异步该方式发送消息,支持跨线程发送消息到指定窗口,用该函数发送一条消息后,便立即返回,不会等待窗口是否处理完成。
4.6.4. PostQuitMessage: 异步方式发送退出消息
bool_t PostQuitMessage(HWND hwnd,u32 exit_code);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
exit_code: 用户自定义的窗口退出码。
返回值:
TRUE: 成功; FALSE: 失败。
说明:
该函数会产生一条MSG_QUIT消息,当主窗口消息循环接收到MSG_QUIT消息时,便会自动销毁主窗口,并退出消息循环,这意味着一个主窗口过程的结束。 该函数只在主窗口过程函数的MSG_DESTROY消息中使用,在其它地方使用,将可能产生不可预知的后果;详细内容可参考窗口的关闭、销毁、退出过程
4.6.5. PeekMessage: 以非阻塞方式获取一条消息
bool_t PeekMessage(MSG *pMsg, HWND hwnd);
头文件:
gdd.h
参数:
pMsg: 存放一条所获得的消息缓冲区。
hwnd: 主窗口句柄。
返回值:
TRUE: 成功获得了一条消息; FALSE: 没有获得消息。
说明:
从消息队列头取出一条消息,该消息将会从消息队列中删除,该函数只在主窗口入口函数中获取消息时使用。
4.6.6. GetMessage: 以阻塞方式获取一条消息
bool_t GetMessage(MSG *pMsg,HWND hwnd);
头文件:
gdd.h
参数:
pMsg: 存放一条所获得的消息缓冲区。
hwnd: 主窗口句柄。
返回值:
TRUE: 成功获得了一条消息; FALSE: 获得了一条MSG_QUIT消息。
说明:
该函数只在主窗口消息循环中使用。
5. 定时器
5.1. 概述
GDD 的定时器是以系统TICK为基准进行计时,是属于一种软件模拟性质的虚拟定时器,这些特性使得定时器不会有很高的精度和准确度,适用于一些对时间要求不是很严格的场合。定时器是作为窗口的资源形式存在,它的服务对象是直接面向窗口。每个窗口都可以由用户创建最多65536个独立的定时器,在窗口运行过程中,用户可以动态去创建和删除定时器,也可以动态去修改已有的定时器运行参数。当一个定时器超时发生后,定时器所属的窗口过程将会收到一条MSG_TIMER消息,MSG_TIMER参数会附带产生该消息的定时器ID,以便用户对多个定时器产生的超时消息加以识别。用户需要注意的是: MSG_TIMER消息是优先级最低的一类,只有当窗口所属的消息队列中没有其它消息时,系统才会将MSG_TIMER派发到它的目标窗口过程函数。
5.2. API说明
5.2.1. GDD_CreateTimer: 创建定时器
TIMER* GDD_CreateTimer(HWND hwnd,u16 Id,u32 IntervalMS,u16 Flag);
头文件::
gdd.h
参数:
hwnd: 定时器所属窗口。
Id: 定时器ID,由用户指定一个0~65535之间的数,所以理论上,每个窗口都可以创建65536个定时器,用户在创建定时器时,必须保证同一窗口下的定时器ID是唯一的,否则该函数会创建失败。
IntervalMS: 定时间隔,单位:毫秒。
Flag: 定时器标志属性,可以是以下值组合:
TMR_START: 创建成功后,便立即启动定时器。
TMR_SINGLE: 如果指定了该标记,则为单次定时模式,否则为循环定时模式。
返回值:
成功则返回新创建的定时器对象指针;失败则返回NULL。
说明:
当定时器定时时间到来时,将为所属的窗口产生一条异步处理的定时器超时消息MSG_TIMER,在所有的消息类型中,MSG_TIMER属于优先级最低的,只有当所有其它消息处理完成后,系统才会真正将MSG_TIMER消息发送到窗口过程函数,交由用户处理响应,当因系统繁忙导致未能及时处理MSG_TIMER消息时,同一定时器将不会重复产生MSG_TIMER消息,以避免这些没有意义冗余操作影响系统响应性能。
5.2.2. GDD_FindTimer: 查找窗口指定ID的定时器
TIMER* GDD_FindTimer(HWND hwnd,u16 Id);
头文件:
gdd.h
参数:
hwnd: 定时器所属窗口。
Id: 需要查找的定时器Id。
返回值:
查找到的定时器对象指针;如果窗口不存在指定Id的定时器,则返回NULL。
5.2.3. GDD_ResetTimer: 重新设置定时器参数
bool_t GDD_ResetTimer(TIMER *ptmr,u32 IntervalMS,u32 Flag);
头文件:
gdd.h
参数:
ptmr: 需要重新设置的定时器对象指针。
IntervalMS: 定时间隔,单位:毫秒。
Flag: 定时器标志属性,可以是以下值组合:
TMR_START: 创建成功后,便立即启动定时器。
TMR_SINGLE: 如果指定了该标记,则为单次定时模式,否则为循环定时模式。
返回值:
TRUE:成功; FALSE:失败。
说明:
当指定的定时器被重置时,如果计时器正在运行中,那么它的计时时间将会强制重新丛0开始计数,如果之前产生了定时器消息未被及时处理,也将会被移除。
5.2.4. GDD_DeleteTimer: 删除定时器
bool_t GDD_DeleteTimer(TIMER *ptmr);
头文件:
gdd.h
参数:
ptmr: 需要删除的定时器对象指针。
返回值:
TRUE:成功; FLASE:失败。
说明:
当一个定时器不需要再使用时,用户可以使用该函数来删除指定的定时器;当然,定时器属于窗口的私有资源对象,即便用户不调用该函数来删除那些不再使用的定时器,那么,在窗口退出(销毁)前,系统也将会自动删除这些定时器,以避免因资源泄漏而产生系统崩溃。另外,定时器已产生但还未及时处理的消息在删除定时器时也会将该消息从消息队列中删除。
6. 矩形区域运算
说明下矩形的位置基准。
6.1. API说明
6.1.1. GDD_RectW: 获得矩形宽度
s32 GDD_RectW(const RECT *prc);
头文件:
gdd.h
参数:
prc: 矩形对象指针。
返回值:
矩形宽度。
6.1.2. GDD_RectH: 获得矩形高度
s32 GDD_RectH(const RECT *prc);
头文件:
gdd.h
参数:
prc: 矩形对象指针。
返回值:
矩形高度。
6.1.3. GDD_SetRect: 设置矩形参数
void GDD_SetRect(RECT *prc,s32 x, s32 y, s32 w, s32 h);
头文件::
gdd.h
参数:
prc: 需要设置的矩形对象指针。
x,y: 矩形起始位置(左上角坐标)。
w,h: 矩形宽度和高度。
返回值: 无。
6.1.4. GDD_SetRectEmpty: 设置一个矩形为空矩形
void GDD_SetRectEmpty(RECT *prc);
头文件:
gdd.h
参数:
prc: 需要设置的矩形对象指针。
返回值: 无。
说明:
当一个矩形的宽度或高度等于0时, 即表示这个矩形为空矩形。
6.1.5. GDD_IsRectEmpty: 判断一个矩形是否为空矩形
bool_t GDD_IsRectEmpty(const RECT *prc);
头文件:
gdd.h
参数:
prc: 需要判断的矩形对象指针。
返回值:
TRUE: 该矩形为空矩形; FALSE: 该矩形为非空矩形。
6.1.6. GDD_CopyRect: 复制矩形参数
bool_t GDD_CopyRect(RECT *dst,const RECT *src);
头文件:
gdd.h
参数:
dst: 目标矩形对象。
src: 源矩形对象。
返回值:
TRUE: 成功; FALSE:失败。
说明:
该函数将源矩形对象的参数复制到目标矩形对象中。
6.1.7. GDD_OffsetRect: 偏移矩形位置
bool_t GDD_OffsetRect(RECT *prc,s32 dx,s32 dy);
头文件:
gdd.h
参数:
prc: 需要偏移的矩形对象指针。
dx: 水平方向的偏移值,当为负值时,向左偏移,否则向右偏移。
dy: 垂直方向的偏移值,当为负值时,向上偏移,否则向下偏移。
返回值: TRUE: 成功; FALSE:失败。
6.1.8. GDD_InflateRect: 扩大或缩小矩形
bool_t GDD_InflateRect(RECT *prc, s32 dx, s32 dy);
头文件:
gdd.h
参数:
prc: 矩形对象指针。
dx: 矩形左边和右边,分别扩大或缩小的值,当该参数为负值时,为减小,否则为增大。
dy: 矩形上边和下边,分别扩大或缩小的值,当该参数为负值时,为减小,否则为增大。
返回值:
TRUE:成功; FALSE:失败.
6.1.9. GDD_InflateRectEx: 扩大或缩小矩形
bool_t GDD_InflateRectEx(RECT *prc, s32 l, s32 t, s32 r, s32 b);
头文件:
gdd.h
参数:
prc: 矩形对象指针。
l: 矩形左边扩大或缩小的值,当该参数为负值时,为减小,否则为增大。
t: 矩形上边扩大或缩小的值,当该参数为负值时,为减小,否则为增大。
r: 矩形右边扩大或缩小的值,当该参数为负值时,为减小,否则为增大。
b: 矩形下边扩大或缩小的值,当该参数为负值时,为减小,否则为增大。
返回值:
TRUE:成功; FALSE:失败。
6.1.10. GDD_PtInRect: 判断坐标点是否在矩形范围内
bool_t GDD_PtInRect(const RECT *prc,const POINT *pt);
头文件:
gdd.h
参数:
prc: 矩形对象指针。
pt: 坐标点对象指针。
返回值:
TRUE:坐标点在矩形范围内;FALSE:坐标点不在矩形范围内。
7. 输入设备
Djygui支持广泛的输入设备,例如键盘、鼠标、触摸屏、体感输入设备等。输入设备的接口已经被系统封装,用户无须关注,只需要响应输入设备的消息即可。在gdd.h文件中,定义了一系列跟输入设备相关的消息。参见第4.5.2节。
APP无须主动去查询、读取各输入设备的状态,只需要响应表中的消息,在消息处理函数中执行所需要的操作即可。
8. 概述
DJYGUI是运行在DJYOS的一个图形系统,包括GK(图形内核)、GKLIB(GK函数库)和GDD(图形装饰平台)三大组件。GK(GUI KERNEL,即图形内核)是DJYGUI多窗口支持的底层核心,大部分的图形操作如剪切域、多窗口层叠、基本显示等都是在这里完成,它不是一堆显示函数的集合,而是一套比较完善的图形支持系统。
GK提供图形操作的大部分功能,如多窗口管理、多显示器、镜像显示、色彩管理、窗口ROP属性和多种缓冲方式等,同时支持基本的图形绘制,如点、直线、圆、曲线、矩形填充和位图等。因此,GK和GKLIB相结合,形成了一个精致而强大的图形支持系统,特别适合于资源紧张的嵌入式系统,能够为应用程序提供完成中等复杂程度的图形编程。如果系统资源比较丰富,要实现复杂的图形功能,建议再把GDD模块加上。
在DJYGUI系统中,总体架构及层次关系如图 1‑1所示。
图 1‑1 DJYGUI总体架构
9. 窗口管理
9.1. 概述
GK所指的窗口是一块矩形显示区域,它没有装饰、控件、输入焦点、菜单等窗口常见组件和属性,它是复杂窗口的原始雏形。因此,GK中所述的窗口与GDD中的窗口应该区别对待,GDD中的窗口是在原始窗口为基础上,增加了各种装饰、控件、输入焦点的窗口,由GDD管理。说明:本文档中所述的窗口,如无特殊说明,一概是指GK管理的原始窗口。
9.2. Z序
在GK中,窗口在桌面上的排列顺序是按Z序方式排列。窗口的Z序,指明了窗口在重叠窗口堆中的位置,窗口堆沿着“Z”轴方向,从屏幕上垂直向屏幕外延伸。Z序顶部的窗口覆盖Z序底部的窗口。
在DJYGUI中,窗口是按资源的形式组织。在系统资源树中,有一个名为“gkwindow”的根节点,该节点是所有窗口的共同祖先,由ModuleInstall_GK函数创建。每台显示器的桌面,是“gkwindow”资源的子节点。每个桌面窗口有一套Z序系统。
窗口在资源树中的组织和它在Z序中的位置关系如图 2‑1所示。
图 2‑1窗口组织和Z序
对窗口有关的资源结点的规则作如下说明:
1、同级窗口只使用前后结点,结点前一个为previous,后一个为next。
2、窗口存在父子关系,除桌面外其他窗口都有父窗口。
3、同级窗口中位于最前端的为父窗口指向的第一个窗口,其next指向同级的最后端窗口。
如图 2‑1所示,从窗口的资源视图中可得出,桌面包含多个子结点,这些子结点是桌面的子窗口,而子窗口也可包含子窗口,即桌面的孙窗口。窗口的Z序视图中,Win6是窗口堆中Z序的最前端窗口,它会覆盖Z序中靠后的窗口。
注意,子窗口有可能覆盖父窗口,也有可能被父窗口覆盖。例如,Win6是桌面的子窗口,覆盖桌面,而窗口win7~9是桌面的子窗口,但却被桌面遮盖。DJYGUI的这种特性,可用于特殊的显示效果,如利用子窗口来做背景或利用子窗口来实现异形窗口等。
9.2.1. 优先级与坐标归属
HMI设计中,touch和mouse相关应用,必须查找点击/触摸笔位置属于哪个窗口,用户还可能会有些特别用途的窗口,不要求相应touch和mouse的操作。Djygui设定,优先级范围是-64(含)~-127之间的窗口,作为控制窗口,调用GK_ApiGetWinFromPt函数时,忽略这些窗口。
#define CN_ZPRIO_CTRL (-64)
#define CN_ZPRIO_CTRL_LIMIT (-127)
9.3. 优先级
窗口的优先级决定窗口在Z序中的排列位置。
窗口的优先级可通过GKLIB提供的API设置,窗口优先级的设定规则如下:
1、 同辈分的窗口中,优先级数值越小,优先级越高,在Z序中越靠前。
2、 桌面的优先级为0,不可改变。优先级≤0的窗口,优先级高于父窗口,在Z序中排列在父窗口前面;优先级<0的窗口,优先级低于父窗口,在Z序中排列在父窗口后面。例如,11H图 2‑1中win1优先级为0,覆盖桌面,win9优先级为1,被桌面覆盖。
3、 任何一个窗口,连同其子孙窗口在Z轴中占据连续的区间,比如win22的优先级数小于win3,但其在Z轴中却被win3覆盖,因为其父窗口win2是被win3覆盖的。同样的道理,也可以解释win23能够优先于win1。
9.4. ROP属性
DJYGUI支持的光栅操作,包括二元光栅操作、alpha、透明色。
二元光栅操作是指在使用GK在窗口画点、线和填充区域时,GK使用二元光栅操作码ROP2组合画笔或画刷像素和目标像素混合以得到新的目标像素。目前,GK支持16种二元光栅操作,与Windows二元光栅操作兼容。二元光栅详细介绍见3.3。
窗口的透明度用Alpha表示,在DJYGUI中,其值范围定义在0 - 255之间。Alpha的取值表示窗口的不透明属性,窗口alpha取值为0,表示窗口完全透明,alpha取值为255,表示窗口完全不透明,alpha值越大,越不透明。GK支持双Alpha混合运算,如表 2‑1所示,S和D分别表示混合的两种颜色,As和Ad表示混合的两个alpha值,dst是最终计算的alpha值。
表 2‑1 alpha混合运算
混合模式 |
计算公式 |
说明 |
CN_ALPHA_MODE_AsN |
dst = S*As+D*(1-As) |
|
CN_ALPHA_MODE_AsAdN |
dst= S*As+D*(1-As)*Ad |
|
CN_ALPHA_MODE_AsAd |
dst = S*As+D*Ad |
|
CN_ALPHA_MODE_As |
dst = S*As |
|
CN_ALPHA_MODE_NEED_DST |
无 |
bit7=1,需要dst像素参与运算 |
CN_ALPHA_MODE_NEED_AD |
无 |
bit6=1,需要dst alpha参与运算 |
窗口透明色是指当窗口内需要填充的颜色与透明色相同时,窗口显示背景色。透明色是GK对Windows定义的Rop2Code的一个扩展。绘制光栅位图也可以执行设置透明色的操作,待绘制的位图中是透明色的像素在绘制过程中不显示,只显示背景色。
光栅属性RopMode是一个32位无符号数,各比特的含义如图 2‑2所示。
作为窗口的属性时,忽略Rop2使能位,也不支持需要背景alpha参与的alpha码(CN_ALPHA_MODE_AsAdN和CN_ALPHA_MODE_AsAd)。
图 2‑2 光栅属性设置
9.5. 边界模式
窗口的边界模式是窗口显示边界受限制的属性,它影响窗口的受限边界和显示效果。窗口的边界模式分为受限和不受限两种。如果窗口边界模式为受限,则其边界受限于父窗口的边界限制;如果窗口模式为不受限,窗口将受限于祖先窗口中第一个边界模式为受限窗口的父窗口。
9.6. API说明
9.6.1. GK_ApiCreateDesktop:创建桌面
bool_t GK_ApiCreateDesktop(struct tagDisplayRsc *Display,
struct gkwin_rsc *Desktop,
s32 Width,s32 Height,u32 Color,
u32 BufMode)
头文件:
gkernel.h
参数:
Display:桌面的宿主显示器。
Desktop:新创建的桌面,保存数据结构所需,内存由调用者提供。
Width:桌面的宽度,小于显示器宽度则调整为显示器宽度。
Height:桌面的高度,小于显示器高度则调整为显示器高度。
Color:创建桌面时填充的颜色,要求颜色格式是真彩色。
BufMode:缓冲模式,见表 3‑2。
返回值:
true:创建成功;false:创建失败
说明:
桌面是所有显示器的第一个窗口。每个显示器有且只有一个桌面,display的成员desktop指针指向其桌面。所有的显示器,必须先初始化,成功创建桌面后才能创建窗口,桌面的尺寸不能小于显示器的尺寸,但可以大于显示器尺寸。桌面在刷新screen的过程中和普通窗口是等同的。桌面的优先级只能是0。
9.6.2. GK_ApiGetDesktop:获取桌面
struct tagGkWinRsc *GK_ApiGetDesktop(char *DisplayName)
头文件:
gkernel.h
参数:
DisplayName:桌面所在显示器的名字。
返回值:
桌面指针,为NULL时表示未找到该名称桌面。
说明:
在djygui中,桌面也是普通窗口,它是第一个建立的窗口,只有建立desktop窗口后,才能创建其他窗口。同一个显示器上的所有其他窗口都是桌面的子孙窗口。
9.6.3. GK_ApiCreateGkwin:创建窗口
bool_t Gk_ApiCreateGkwin(struct tagGkWinRsc *Parent,
struct tagGkWinRsc *NewWin,
s32 Left,s32 Top,s32 Right,s32 Bottom,
u32 Color,u32 BufMode,
char *Name,u16 PixelFormat,u32 KeyColor
u32 BaseColor, u32 RopMode)
头文件:
gkernel.h
参数:
Parent:父窗口指针。
NewWin:新创建的窗口,保存数据结构所需内存,由调用者提供。
Left:新创建的窗口左边界,相对于父窗口。
Top:新创建的窗口上边界,相对于父窗口。
Right:新创建的窗口右边界,相对于父窗口。
Bottom:新创建的窗口下边界,相对于父窗口。
Color:创建窗口时填充的颜色,要求颜色格式是真彩色。
BufMode:缓冲模式,见表 3‑2。
Name:新建窗口名称。
PixelFormat:像素格式,CN_SYS_PF_DISPLAY表示与显示器相同。
KeyColor:设定窗口透明色,要求颜色格式为真彩色。
BaseColor:灰度基色,(仅在PixelFormat == CN_SYS_PF_GRAY1 ~8时有用)。
RopMode:光栅操作码,即二元光栅操作、alpha和透明色属性。
返回值:
true:窗口创建成功;false:窗口创建失败。
说明:
新创建的窗口只是一个矩形区域,没有填充,也没有边框等一切装饰。新建窗口创建时默认优先级为0,其优先级可以调整。窗口的尺寸不受限制。新建窗口遗传父窗口的一些属性,如宿主显示器、直接写屏。窗口的像素格式可调,设置为CN_SYS_PF_DISPLAY表示与显示器相同。窗口的RopMode属性可设置为0,表示无光栅操作属性,同时可根据alpha、透明色设置相应属性,但窗口不支持二元光栅。
示例:
static struct tagGkWinRsc *desktop,gkwin1; desktop = GK_ApiGetDesktop("ili9325"); GK_ApiCreateGkwin(desktop,&gkwin1,0,0,200,200,CN_COLOR_RED, CN_WINBUF_NONE,"window1", CN_SYS_PF_DISPLAY, CN_COLOR_BLACK, CN_COLOR_BLACK , 0 ); |
代码中,ili9325是显示器的名字。
上面的一段程序,在桌面上创建了一个名为window1的窗口,填充颜色为红色CN_COLOR_RED(0xff0000),缓冲模式是没有缓冲区(CN_WINBUF_NONE),只能进行直接写屏操作,窗口左上角、右下角坐标分别是(0,0)、(200,200),给定坐标是相对于父窗口的,窗口像素格式与显示器一致,窗口透明色和灰度基色为黑色(CN_COLOR_BLACK),窗口RopMode属性为0(无特殊效果)。
9.6.4. GK_ApiDestroyWin:销毁窗口
void GK_ApiDestroyWin(struct tagGkWinRsc *Gkwin)
头文件:
gkernel.h
参数:
Gkwin:目标窗口。
返回值:
无。
说明:
销毁窗口,同时销毁窗口的子孙窗口。
9.6.5. GK_ApiMoveWin:移动窗口
void gk_api_move_win(struct tagGkWinRsc *Gkwin,s32 Left,s32 Top,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:显示的目标窗口。
Left:窗口移动后的左上角坐标的横坐标,相对于父窗口。
Top:窗口移动后的左上角坐标的纵坐标,相对于父窗口。
SyncTime:见3.2章节。
返回值:
无。
说明:
改变窗口在父窗口内的相对位置,由于子窗口的坐标是相对于父窗口的,故移动窗口时,连子窗口一起移动。
9.6.6. GK_ApiSetBoundMode:设置边界模式
void GK_ApiSetBoundMode (struct tagGkWinRsc *Gkwin, bool_t Mode)
头文件:
gkernel.h
参数:
Gkwin:目标窗口。
Mode:窗口的边界模式,true为受限,false为不受限。
返回值:
无。
说明:
设定窗口的显示边界是否受父窗口限制,限制后,子窗口超出父窗口的部分将不予显示,桌面的直接子窗口默认受限,不能更改。
9.6.7. GK_ApiSetPrio:设置窗口显示优先级
void GK_ApiSetPrio(struct tagGkWinRsc *Gkwin, sfast_t Prio,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:目标窗口。
Prio:新优先级。
SyncTime:见3.2章节。
返回值:
无。
说明:
设置一个窗口的优先级,优先级决定当前窗口在同级窗口中z轴相对位置,数字越小,在z轴中越靠前,优先级<=0将覆盖父窗口,反之被父窗口覆盖。窗口改变优先级后,它在Z轴中的顺序可能会改变,屏幕内容也可能会改变。由于被改变优先级的窗口可能还有子窗口,所以,在z轴中被移动的,不是一个窗口,而是连续的一组窗口。桌面的优先级为0,不可改变。窗口设置的新优先级可以和原优先级相同,即便如此,显示效果也可能会改变。新设置的优先级需在合法范围里(-128 - 127)。
9.6.8. GK_ApiSetRopMode:设置光栅属性
bool_t GK_ApiSetRopMode(struct tagGkWinRsc *Gkwin,
u32 RopCode,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:目标窗口。
RopCode:光栅操作码,可以是扩展的光栅操作码,参见图 2‑2。
SyncTime:见3.2章节。
返回值:
true:设置成功;false:设置失败。
说明:
非缓冲窗口和桌面不可修改光栅操作码。
9.6.9. GK_ApiSetTransparentColor:设置窗口透明色
bool_t GK_ApiSetTransparentColor(struct tagGkWinRsc *Gkwin, u32 KeyColor)
头文件:
gkernel.h
参数:
Gkwin:目标窗口。
KeyColor:要设置的透明色。
返回值:
true:设置成功;false:设置失败。
说明:
桌面不需要设置透明色。
10. 窗口绘制
10.1. 概述
GK支持的窗口绘制包括单个像素、直线(含/不含端点)、圆、曲线、文本和矩形填充。
同步异步操作是影响了绘图的调用返回方式,而缓冲模式则决定了绘制的过程,像素颜色、二元光栅操作和渐变填充直接影响绘图效果,本章将作详细介绍。
10.2. 同步与异步操作
窗口绘制同步操作是指应用程序调用绘制函数,绘制完成或超时才返回,异步操作是指调用函数后立刻返回,此时绘制操作可能未完成。
绝大多数绘制函数中,都有一个参数SyncTime,如果该参数为0,上层应用程序调用绘制函数后,绘制消息发送到消息管道后直接返回,此时,绘制操作可能未完成。若连续多次调用绘制函数,可能导致消息队列拥塞。如果SyncTime是一个非零的值,调用线程将被阻塞,直到执行完绘制命令,或者超时才解除阻塞。超时时间由SyncTime(us)设置。
10.3. 二元光栅操作
二元光栅操作是指通过二元光栅操作码ROP2,组合画笔或画刷像素和目标像素以得到新的目标像素。
二元光栅操作的本质是位逻辑运算。位逻辑运算将独立的位以参数D、P的形式进行配对,同时对位进行布尔逻辑运算。进行二元光栅操作用到的布尔逻辑操作有AND(&)、OR(|)、NOT(~)、XOR(^)。二元的布尔逻辑运算,有16中可能的组合,如表 3‑1所示。
表 3‑1 二元光栅操作
二元光栅操作 |
公式 |
说明 |
CN_R2_BLACK |
dest = 0 |
RGB模式下是黑色 |
CN_R2_NOTMERGEPEN |
dest = ~(dest | pen) |
CN_R2_MERGEPEN取反 |
CN_R2_MASKNOTPEN |
dest = ~pen & dest |
画笔颜色取反与目标颜色的逻辑乘 |
CN_R2_NOTCOPYEN |
dest = ~pen |
画笔颜色取反 |
CN_R2_MASKPENNOT |
dest = ~dest & pen |
目标颜色取反与画笔颜色的逻辑乘 |
CN_R2_NOT |
dest = ~dest |
目标颜色取反 |
CN_R2_XORPEN |
dest = dest ^ pen |
目标颜色与画笔颜色的逻辑异或 |
CN_R2_NOTMASKPEN |
dest = ~(dest & pen) |
CN_R2_MASKPEN取反 |
CN_R2_MASKPEN |
dest = dest & pen |
目标颜色与画笔颜色的逻辑乘 |
CN_R2_NOTXORPEN |
dest = ~(dest ^ pen) |
CN_R2_XORPEN取反 |
CN_R2_NOP |
dest = dest |
颜色不变 |
CN_R2_MERGENOTPEN |
dest = ~pen | dest |
画笔颜色取反与目标颜色的逻辑和 |
CN_R2_COPYPEN |
dest = pen |
画笔的颜色 |
CN_R2_MERGEPENNOT |
dest = ~dest | pen |
目标颜色取反与画笔颜色的逻辑和 |
CN_R2_MERGEPEN |
dest = dest | pen |
目标颜色与画笔颜色的逻辑和 |
CN_R2_WHITE |
dest = 1 |
RGB模式下是白色,不一定是一位 |
注:表 3‑1中dest(也写作D)、pen(也写作P)分别为二元光栅操作的目标颜色和画笔颜色。
在GK中,二元光栅操作码用Rop2Code表示,缩写为R2。一般默认的二元光栅操作码是CN_R2_COPYPEN,它把目标像素绘制为画笔的颜色。绘制像素、直线、曲线的情况都使用画笔,用到了二元光栅操作。
二元光栅操作在计算机图形学中起很重要的作用。使用CN_R2_BLACK把目标像素绘制为黑色,使用CN_R2_WHITE把目标像素绘制为白色,使用CN_R2_NOP则目标像素颜色不变。由于二元光栅操作是对位进行操作,可以实现有选择的屏蔽目标颜色中的某些位。
10.4. 像素颜色
10.4.1. 像素颜色格式
颜色是人产生的一种对光的视觉效应,通常是由几个颜色属性进行描述。RGB就是一种对颜色进行描述的模式。
RGB代表红色(red)、绿色(green)、蓝色(blue)三种颜色,即通常所说的三原色。RGB图像只使用红、绿、蓝三种颜色,将它们以不同的比例混合,可以得到各式各样的颜色。红、绿、蓝三种颜色,从暗到亮划分为等阶亮度,以255阶为例,在0时颜色最弱,而在255时颜色最亮;当三种颜色都为255时,混合显示为白色,当三种颜色都为0时,混合显示为黑色,当三种颜色阶数相等且不等于0、255时,显示灰色,颜色介于白色与黑色之间;三种颜色阶数不等时,会得到彩色。特殊情况下,单色,即1位有两种颜色,0代表黑色,1代表白色。灰色,每一位均为1,则为纯白色,全为0,则为纯黑色,中间为灰色,且由0-1渐变,越来越白。
GK支持多种像素颜色格式,例如,当前比较流行的16位色RGB565和24位色RGB888等。Djygui支持的颜色格式在gkernel.h中定义,参见CN_SYS_PF_RGB565族常数。
10.4.2. 像素颜色格式转换
GK提供的所有接口统一要求绘图颜色格式为真彩色,因此,针对不同的显示器,GK提供像素颜色格式转化接口,通过颜色格式转换接口,可将真彩色转化为本地颜色格式,或将本地颜色格式转化为真彩色。
10.5. 缓冲模式
GK窗口支持三种缓冲模式,分别为继承缓冲、有窗口缓冲和无缓冲(即直接写屏)。
在高性能富内存的系统中,比如智能手机有数百M甚至上G的内存,GK使用窗口缓冲来提高GUI性能,降低应用程序复杂度。在内存资源非常紧张的嵌入式系统中,GK支持支持直接写屏的方式,降低内存消耗。
帧缓冲是显示器的属性,显示的数据可存储在帧缓冲区,缓冲区大小由显示器大小和像素格式决定。窗口缓冲是窗口显示的缓冲区,它的大小由窗口大小和像素格式决定。只有包含帧缓冲区的情况下,才可以创建带窗口缓冲区的窗口。有窗口缓冲区时一定存在帧缓冲区,有帧缓冲区时不一定存在窗口缓冲区。
GK创建窗口时可指定窗口缓冲模式,用于指定创建的窗口是否带缓冲区。缓冲模式只能在创建窗口时设定,不能修改。窗口缓冲模式如表 3‑2所示。
表 3‑2 窗口缓冲模式
缓冲模式 |
宏定义 |
意义 |
CN_WINBUF_PARENT |
0 |
继承父窗口,若为桌面,则继承帧缓冲 |
CN_WINBUF_NONE |
1 |
无有缓冲区 |
CN_WINBUF_BUF |
2 |
有缓冲区 |
根据窗口的缓冲模式,窗口的绘制过程如图 3‑1所示。
图 3‑1 窗口绘制过程
## 10.6. 渐变填充GK渐变填充功能是在指定的矩形区域内,按照一定的填充方式,填充效果由Color0到Color1渐变的一种特殊的填充方式。按照填充的方式,渐变填充模式如表 3‑3所示。其中Color0是渐变填充颜色0,Color1是渐变填充颜色1。
渐变填充过程中,首先求出Color0和Color1的alpha和R、G、B分量,然后将Color0和Color1的分量线性整合,最后将alpha值和R、G、B合成Color的ARGB值。
表 3‑3 渐变填充模式
模式 |
数值 |
说明 |
CN_FILLRECT_MODE_N |
0 |
直接填充,只有Color0有效 |
CN_FILLRECT_MODE_H |
1 |
水平填充,Color0表示左边颜色,Color1右边 |
CN_FILLRECT_MODE_V |
2 |
垂直填充,Color0表示上边颜色,Color1下边 |
CN_FILLRECT_MODE_SP |
3 |
倾斜填充,Color0表示左上角颜色,Color1右下角 |
CN_FILLRECT_MODE_SN |
4 |
倾斜填充,Color0表示右上角颜色,Color1左下角 |
10.7. API说明
10.7.1. GK_ApiSetPixel:绘制像素
void GK_ApiSetPixel(struct tagGkWinRsc *Gkwin,s32 x,s32 y,
u32 Color,u32 Rop2Code,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:绘制的目标窗口。
x:绘制位置的横坐标,相对于窗口。
y:绘制位置的纵坐标,相对于窗口。
Color:画点使用的颜色,要求颜色格式是真彩色。
Rop2Code:二元光栅操作码。
SyncTime:见3.2章节。
返回值:
无。
10.7.2. GK_ApiLineto:绘制直线
void GK_ApiLineto(struct tagGkWinRsc *Gkwin, s32 x1,s32 y1,
s32 x2,s32 y2,u32 Color,u32 Rop2Code,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:显示的目标窗口。
x1:待绘制直线起点的横坐标,相对于窗口。
y1:待绘制直线起点的纵坐标,相对于窗口。
x2:待绘制直线终点的横坐标,相对于窗口。
y2:待绘制直线终点的纵坐标,相对于窗口。
Color:画线使用的颜色,要求颜色格式是真彩色。
Rop2Code:二元光栅操作码。
SyncTime:见3.2章节。
返回值:
无。
说明:
绘制单像素先宽的直线,结束端点不绘制。此外,函数GK_ApiLinetoIe也是绘制单像素宽直线,区别在于后者绘制直线的终点。
示例:
画点是画直线的基础,直线是由多个点构成的。下面以画点、画直线的实例介绍画点和画直线的函数的使用方法。
static struct tagGkWinRsc *desktop; desktop = GK_ApiGetDesktop("ili9325"); GK_ApiSetPixel (desktop,0,0,CN_COLOR_RED,CN_R2_COPYEN,,CN_GK_SYNC); GK_ApiLineto (desktop,0,2,5,2,CN_COLOR_BLUE,CN_R2_CYPYEN, CN_GK_SYNC); GK_ApiLinetoIe (desktop,0,3,5,3,CN_COLOR_BLACK, CN_R2_CYPYEN,CN_GK_SYNC); |
在桌面上进行画点、画线操作。上面的程序实现的是在桌面的前四行,第一行是画一个像素,第二行画一条不包含终点的直线,第三行是画一条包含终点的直线。
10.7.3. GK_ApiDrawCircle:绘制圆形
void GK_ApiDrawCircle(struct tagGkWinRsc *Gkwin,s32 x0,s32 y0,
u32 r,u32 Color,u32 Rop2Code,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:绘制的目标窗口。
x0:圆心点的横坐标,相对于窗口。
y0:圆心点的纵坐标,相对于窗口。
r:待绘制圆的半径。
Color:画圆使用的颜色,要求颜色格式是真彩色。
Rop2Code:二元光栅操作码。
SyncTime:见3.2章节。
返回值:
无。
说明:
画一个单像素线宽的圆。
10.7.4. GK_ApiDrawTextGK_ApiDrawText:绘制文本
void GK_ApiDrawText(struct tagGkWinRsc *Gkwin,s32 x,s32 y,
const char *Text,u32 Count,u32 Color,
u32 Rop2Code,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:显示的目标窗口。
x:显示位置的横坐标,相对于窗口。
y:显示位置的纵坐标,相对于窗口。
Text:待显示的字符串。
Count:字符串长度,含串结束符。
Color:显示颜色,要求颜色格式是真彩色。
Rop2Code:二元光栅操作码。
SyncTime:见3.2章节。
返回值:
无。
说明:
文本串是由默认字体和默认字符集显示的,调用此函数显示的是单色的字,一个汉字为两个字符。
10.7.5. GK_ApiBezier:绘制贝塞尔曲线
void gk_api_Bezier(struct tagGkWinRsc *Gkwin,float x1,float y1,
float x2,float y2,float x3,float y3,float x4,float y4,
u32 Color,u32 Rop2Code,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:显示的目标窗口。
x1:贝塞尔曲线第一个控制点的横坐标,相对于窗口。
y1:贝塞尔曲线第一个控制点的纵坐标,相对于窗口。
x2:贝塞尔曲线第二个控制点的横坐标,相对于窗口。
y2:贝塞尔曲线第二个控制点的纵坐标,相对于窗口。
x3:贝塞尔曲线第三个控制点的横坐标,相对于窗口。
y3:贝塞尔曲线第三个控制点的纵坐标,相对于窗口。
x4:贝塞尔曲线第四个控制点的横坐标,相对于窗口。
y4:贝塞尔曲线第四个控制点的纵坐标,相对于窗口。
Color:画贝塞尔曲线使用的颜色,要求颜色格式是真彩色。
Rop2Code:二元光栅操作码。
SyncTime:见3.2章节。
返回值:
无。
说明:
画单像素宽的三次Bezier曲线。贝塞尔曲线是电脑图形学中相当重要的参数曲线,可以用来绘制各种形状的曲线,djygui提供绘制3次贝塞尔曲线的api函数。
示例:
以特殊情况,圆和贝塞尔曲线都在窗口内的实例来说明画圆与画贝塞尔曲线函数的使用。
static struct tagGkWinRsc *desktop; desktop = GK_ApiGetDesktop("ili9325"); GK_ApiDrawCircle(desktop,100,100,50,CN_COLOR_RED, CN_R2_COPYPEN,CN_GK_SYNC); GK_ApiBezier(desktop,0,200,50,50,150,20,300,200, CN_COLOR_RED,CN_R2_COPYPEN,CN_GK_SYNC); |
实例显示的效果是在桌面上有一个圆心在(100,100),半径为50,红色的圆,同时有一条起点为(0,200),终点为(300,200)的红色抛物线。
10.7.6. GK_ApiFillWin:填充窗口
void GK_ApiFillWin(struct tagGkWinRsc *Gkwin,u32 Color,u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:待填充的窗口。
Color:给定的颜色,要求颜色格式是真彩色。
SyncTime:见3.2章节。
返回值:
无。
说明:
填充窗口是用给定颜色填充整个窗口,颜色格式要求为真彩色。
10.7.7. GK_ApiFillRect:填充矩形
void GK_ApiFillRect(struct tagGkWinRsc *Gkwin, struct tagRectangle *Rect,
u32 Color0, u32 Color1, u32 Mode, u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:待填充的窗口。
Rect:待填充的位置,坐标相对于待填充的窗口。
Color0:颜色0,要求颜色格式是真彩色。
Color1:颜色1,要求颜色格式是真彩色。
Mode:渐变模式,见表 3‑3。
SyncTime:见3.2章节。
返回值:
无。
说明:
填充窗口一部分,一部分是指窗口中的任一矩形域,只会填充到可视域内。填充模式是指可填充渐变效果。
示例:
GK_ApiFillRect填充指定矩形范围,支持渐变填充。下面举例说明这个函数的使用方法。
static struct tagGkWinRsc gkwin1; GK_ApiFillRect (&gkwin1,rect,CN_COLOR_GREEN, CN_COLOR_BLUE, ,CN_FILLRECT_MODE_H,CN_GK_SYNC); |
这段程序对桌面上窗口进行矩形渐变填充,填充颜色0为绿色,填充颜色1为蓝色,采用的渐变模式为水平填充,填充效果为窗口的矩形区域rect内,从左到右的内容由绿色变为蓝色。
10.7.8. GK_ApiSyncShow:刷新窗口
void GK_ApiSyncShow(u32 SyncTime)
头文件:
gkernel.h
参数:
SyncTime:见3.2章节。
返回值:
无。
说明:
执行该命令,所有输出数据将输出到显示器。
10.7.9. GK_ConvertColorToRGB24:将本地颜色转化为真彩色
u32 GK_ConvertColorToRGB24(u16 PixelFormat,u32 Color,ptu32_t ExColor)
头文件:
gk_draw.h
参数:
PixelFormat:本地颜色格式。
Color:源色彩。
ExColor:扩展颜色。
返回值:
真彩色格式的颜色。
说明:
颜色格式转换,把一个本地格式颜色转换成ERGB8888,如果位图格式如果包含alpha通道,则先计算alpha。ExColor为双功能参数,如果PixelFormat=CN_SYS_PF_GRAY1~8,或者PixelFormat=CN_SYS_PF_ALPHA1~8,则ExColor表示基色。如果PixelFormat=CN_SYS_PF_PALETTE1,则ExColor表示调色板指针。如果PixelFormat不需要此参数,可给0或NULL。
10.7.10. GK_ApiSetDirectScreen:设置窗口直接写屏
void GK_ApiSetDirectScreen(struct tagGkWinRsc *gkwin, u32 SyncTime)
头文件:
gkernel.h
参数:
gkwin:目标窗口。
SyncTime:见3.2章节。
返回值:
无。
说明:
设置窗口直接写屏属性,当窗口直接写屏属性被设置为true时,无论窗口是否有缓冲,所有绘制操作都是直接绘制到显示器上面。
10.7.11. GK_ApiCancelDirectScreen:撤销窗口直接写屏
void GK_ApiCancelDirectScreen(struct tagGkWinRsc *Gkwin, u32 SyncTime)
头文件:
gkernel.h
参数:
Gkwin:目标窗口。
SyncTime:见3.2章节。
返回值:
无。
说明:
撤销窗口直接写屏属性。
10.7.12. GK_ConvertRGB24ToPF:将真彩色转化为本地颜色
u32 GK_ConvertRGB24ToPF(u16 PixelFormat,u32 Color)
头文件:
gk_draw.h
参数:
PixelFormat:目标颜色格式。
Color:源色彩,颜色格式为真彩色。
返回值:
目标颜色格式的色彩。
说明:
把一个ERGB8888格式的颜色转换成本地格式,本地格式不允许有alpha通道,也不允许是调色板位图。
11. 文本显示
11.1. 概述
计算机使用二进制语言,而使用计算机的人则用各自的自然语言,这些自然语言的文字,需要编码才能在计算机中标识。为了让计算机“理解”人类的语言,人们设计了许多字符集和字符编码方式,主要分以下两大类。
1. ansi系
ansi系是一种兼容ascii编码的多字节字符集,其显著特点是:
兼容编码值为0x00~0x7f的单字节ascii编码,任何ascii编码的文本,都是合法的字符串。正常字符流中不会出现值为0x00的字节,这点很重要,因为c语言把0x00看成字符串结束符。
字符是变长的,一个字符可能是1字节、2字节、3字节甚至4字节,多字节字符的首字节最高位必为0。
一个字符集只能表示一种语言,不同的ansi系的字符集,可能有冲突,即不同语言的不同字符,编码可能相同。
2. unicode系
unicode是一种收录了以及打算收录世界上所有字符的单一编码字符集,因此,它跟ansi系不一样,unicode只有一种字符集。unicode把字符分为17个页面,每个页面65536个编码,页面0也叫BMP页面,我们常用的绝大多数字符都在BMP页面上。unicode的字符集和字符编码是分开的,主要字符编码有:
ucs-2:只能实现unicode的一个子集的编码,只能表示BMP页面上的字符,所有字符都编码成2字节,在正常字符流中有0x00这个字符,需特别注意。
ucs-4:能实现所有unicode字符,所有字符都编码成2字节,同样在正常字符流中有0x00这个字符,需特别注意。
utf-8:能实现所有unicode字符,是一种变长字符编码,最长者可达6字节,但按照目前unicode的实际标准,表示unicode定义的所有17个页面的字符,只需要4个字节,5、6字节编码其实要等猴年马月才能用上。utf-8的好处是,正常字符流中间不会出现0x00
utf-16:同样是一种变长编码,用2字节或4字节来表示一个字符,绝大多数BMP页面上的字符可以用2字节编码来表示,超出2字节的部分用4字节来表示。同样,其正常字符流中有0x00这个字符,需特别注意。
DJYOS的语言支持是多方面的,这里只描述与图形界面输出相关的部分。
djygui提供多语言支持,允许用户设计多语言支持界面。djygui中,字符集和字体都作为一种资源存在,应用程序通过选择相应的资源来支持多国语言。应用程序也可以创建资源来实现自己的“小语言”,例如,某应用程序只需要使用100个汉字,且存储空间紧张,就可以创建一个小语言,该语言只包含100个汉字。
语言属性由字符集和字体资源组成,字符集资源决定本字符集能表示多少种字符和字符如何编码;字体资源决定本字体有多少种字符和每个字符的字形。目前DJYOS提供了ascii6x12字体、ascii8x16字体、ascii8x8字体、gb2312 16点阵字体等字体可供选择使用。同时DJYOS支持ASCII、Unicode、GB2312等字符编码。
11.2. 字符集说明
字符集资源是用来映射一个字符集合中的字符与二进制代码之间的转换关系的,一个字符集可以表示一种语言、多种语言,或者是一种语言的一个子集,甚至是所有unicode字符,视字符集的定义而定。在DJYOS中,字符集资源并非只为gui服务,这里只介绍跟gui有关的部分。
正如上文提及DJYOS支持ASCII、utf8、GB2312等字符编码,但是DJYOS将ucs4作为桥梁,ASCII、utf8、GB2312等字符编码首先转换成ucs4,进而进行编码显示。要想将一个字符编码转换成ucs4,需要完成以下工作:
字符解析函数,把给定的字符转化成ucs-4编码;
字符串解析函数,从一个字符串中取出一个字符并转化为ucs-4编码,并给出这个字符的长度(字节数);
逆字符解析函数,把一个ucs-4编码的字符转换成本字符集的字符,并给出这个字符的长度(字节数)。
字符编码结构体tagCharEncodingRsc用于表征某个字符编码,其定义如下:
struct tagCharEncodingRsc { struct tagRscNode node; /* 单个字符的最大字节数 */ u32 max_len; //----多字节字符转为ucs4字符 //功能: 把一个多字节字符转换为ucs4字符。 //参数: pwc,保存转换结果的指针,调用方确保不为NULL,不判断,gui将确保本函数不会被其他模//块调用; // mbs, 指向待转换的多字节字符字节序列的指针(由调用函数判断s的合法性); // n,最大检测长度。 //返回: 0: pwc,mbs是NULL指针或者mbs指向空串。 // -1:mbs指向的不是合法多字节字符,或者长度n内未能检测到完整多字节字符 // 其他:mbs缓冲区内第一个完整多字节字符的长度。 //说明: // 此函数是C Run-time库的mblen及mbtowc服务函数。 // 传入的s指针必须非NULL s32 (*mb_to_ucs4)(u32* pwc, const char* mbs, s32 n); //----ucs4字符转为多字节字符 //功能: 把一个ucs4字符转换为多字节字符。 //参数: mb,保存转换结果的指针(由调用函数判断s的合法性) // wc,待转换的字符 //返回:-1,如果wc不能对应一个有效的多字节字符, // 字节数,返回对应的多字节字符的字节数。 //说明: // 此函数是C Run-time库的wctomb服务函数。 s32 (*ucs4_to_mb)(char* mb, s32 wc); //----多字节字符串转为ucs4串 //功能: 把一个多字节字符串转换为ucs4字符串 //参数: pwcs,保存转换结果的指针,缓冲区由调用方提供,若空,则本函数转变为只计算 // 保存转换结果所需的字节数 // mbs,保存多字节字符的缓冲区指针 // n,最大检测长度, //返回: 0: mbs是NULL指针 // -1:结束条件到达前,有不能转换的字符 // 其他:得到的字符数,=n表示源串是不包含串结束符'\0'。 s32 (*mbs_to_ucs4s)(u32* pwcs, const char* mbs, s32 n); //----ucs4字符串转为多字节字符串----------------------------------------------- //功能: 把一个ucs4字符串转换为多字节字符串。 //参数: mbs,保存转换结果的指针,缓冲区由调用方提供,若空,则本函数转变为只计算保存转换结//果所需的字节数 // pwcs,待转换的字符 // n,最大检测长度,遇串结束符或长度达到n结束转换,注意ucs4的结束符是连续4个0x00. //返回: 0: pwcs是NULL指针 // -1:结束条件到达前,有不能转换的字符 // 其他:写入mbs缓冲区的字节数,含串结束符'\0' //------------------------------------------------------------------------- s32 (*ucs4s_to_mbs)(char* mbs, const u32* pwcs, s32 n); }; |
要想在DJYOS上使用某个特定字符编码,其实就是实现该字符编码结构体中4个钩子函数,使其能与ucs4进行转换。如果实现了相应的转换函数,将其挂接到其字符编码结构体中,然后将其安装到系统字符编码资源树下,即可实现支持该字符编码。例如DJYOS支持gb2312,需要首先调用系统函数Charset_CharEncodingModuleInit创建字符编码树资源节点(如果已创建则不必调用),然后调用系统函数Charset_Gb2312EncodeModuleInit将该字符编码安装到字符编码树节点下即可。Charset_Gb2312EncodeModuleInit函数源代码如下:
ptu32_t Charset_Gb2312EncodeModuleInit(ptu32_t para) { static struct tagCharEncodingRsc encoding;
encoding.max_len = 2; encoding.mb_to_ucs4 = __Gk_Gb2312MbToUcs4; //多字节字符转为ucs4字符 encoding.ucs4_to_mb = __Gk_Gb2312Ucs4ToMb; // ucs4字符转为多字节字符 encoding.mbs_to_ucs4s = __Gk_Gb2312MbsToUcs4s;// 多字节字符串转为ucs4串 encoding.ucs4s_to_mbs = __Gk_Gb2312Ucs4sToMbs;// ucs4字符串转为多字节字符串 if(Charset_NlsInstallCharEncoding(&encoding, CN_NLS_CHARSET_GB2312)) { printf("gb2312 encoding install sucess\n\r"); return 1; }else { Djy_SaveLastError(EN_GK_CHARSET_INSTALL_ERROR); printf("gb2312 encoding install fail\n\r"); return 0; } } |
除了标准字符集外,应用程序也可以方便地安装自己定义的字符集,例如某项目只用到100个汉字和50个日文字符,如果要节省存储空间,完全可以自己创建一个名字为cnjp的字符集,包含100个汉字和50个日文字符。只需将该字符编码安装到DJYOS字符编码根资源树下即可,安装过程同上述Gb23123,在此不赘述。
11.3. 字符集API说明
11.3.1. ModuleInstall_Charset:字符编码模块初始化
ptu32_t ModuleInstall_Charset(ptu32_t para)
头文件:
charset.h
参数:
无。
返回值:
成功初始化则返回1;失败则返回0。
说明:
字符编码模块初始化,其实就是在资源链中添加字符编码资源根节点。
11.3.2. Charset_NlsInstallCharset:安装字符编码
bool_t Charset_NlsInstallCharset(struct tagCharset *encoding, char* name)
头文件:
charset.h
参数:
encoding,新增的字符编码指针;
name,新增字符编码名。
返回值:
成功安装字符编码则返回true;失败则返回false。
说明:
将新字符编码安装到系统字符编码资源根节点下。
11.3.3. Charset_NlsGetCurCharset:获取当前字符编码
struct tagCharset* Charset_NlsGetCurCharset (void)
头文件:
charset.h
参数:
空。
返回值:
当前使用的字符编码结构体指针。
说明:
获取当前使用的字符编码。
11.3.4. Charset_NlsSetCurCharset:设定当前字符编码
struct tagCharset* Charset_NlsSetCurCharset(struct tagCharset* encoding)
头文件:
charset.h
参数:
encoding,设定的字符编码结构体指针。
返回值:
设定后当前字符编码结构体指针。
说明:
把新字符编码设为当前使用的字符编码,新字符编码必须事先安装到系统中。
11.3.5. Charset_NlsSearchCharset:搜索字符编码资源
struct tagCharset* Charset_NlsSearchCharset(const char* name)
头文件:
charset.h
参数:
name,指定的字符编码。
返回值:
如果成功搜到指定字符编码则返回该字符编码结构体指针;否则返回NULL。
说明:
从字体资源根节点下搜索指定名称的字符编码资源。
11.3.6. ModuleInstall_CharsetNls:初始化Nls模块
ptu32_t ModuleInstall_CharsetNls(const char * para)
头文件:
nls.h
参数:
无。
返回值:
成功初始化则返回1;失败则返回0。
说明:
Nls模块初始化,其实就是找到本地字符编码资源并将其设定为当前字符编码。
11.3.7. Charset_NlsGetLocCharset:获取区域字符编码
struct tagCharset* Charset_NlsGetLocCharset(const char* loc)
头文件:
nls.h
参数:
loc,区域名称编码。
返回值:
返回匹配的字符编码结构体指针,若未有匹配编码,使用默认的ASCII编码。
说明:
根据区域名称获取字符编码,"C"是默认编码的代号。
11.3.8. ModuleInstall_CharsetAscii:安装ASCII字符集
ptu32_t ModuleInstall_CharsetAscii(ptu32_t para)
头文件:
ascii.h
参数:
para,无实际意义。
返回值:
1=成功,0=失败。
说明:
安装ascii字符集,当系统使用西方字符界面时,使用这个字符集。特别注意,gb2312已经包含了英文字符集,使用中文或中英文混合界面的,不需要安装ascii字符集。但是,由于GB2312的字库只包含了全角的英文字符,故还需要安装ascii 的字体资源,尺寸(8*8、8*16)可选。
11.3.9. ModuleInstall_CharsetGb2312:安装Gb2312字符集
ptu32_t ModuleInstall_CharsetGb2312(ptu32_t para)
头文件:
gb2312.h
参数:
para,无实际意义。
返回值:
1=成功,0=失败。
说明:
安装gb2312字符集,当系统使用西方字符界面时,使用这个字符集。特别注意,gb2312已经包含了英文字符集,使用中文或中英文混合界面的,不需要安装ascii字符集。
11.3.10. ModuleInstall_CharsetUtf8:安装utf8字符集
ptu32_t ModuleInstall_CharsetUtf8(ptu32_t para)
头文件:
utf8.h
参数:
para,无实际意义。
返回值:
1=成功,0=失败。
说明:
安装utf8字符编码解析器,执行ucs4和编码和utf8编码之间转换。
11.4. 字体说明
字体资源其实叫字形资源更加贴切,该资源描述了一个集合的字符的图形表示,与字符集一样,字体资源可以包含一种语言、多种语言,或者是一种语言的一个子集,甚至是所有unicode字符。一般来说,一个系统使用的字体资源与字符集资源保持一致即可。在djyos中,字体资源并非只为gui服务,这里只介绍跟gui有关的部分。
字体结构体tagFontRsc定义如下:
struct tagFontRsc { struct tagRscNode node; s32 MaxWidth; //最宽字符的宽度,纵向显示时可用作为竖行宽 s32 MaxHeight; //最高字符的高度 u32 Attr; bool_t (*LoadFont)(void *zk_addr); //加载字体 void (*UnloadFont)(void); //卸载字体 // 获取ucs4编码为charcode字符的显示点阵,把点阵填充到font_bitmap中,调用者应该提 // 供font_bitmap所需内存。 // 如果font_bitmap参数中的bm_bits参数为NULL,则本函数退化为查询函数。在 // font_bitmap参数中返回图像参数,利用它可以计算bm_bits所需内存尺寸,这在一个文 // 档中使用多种尺寸的文字时,特别有用。 // resv,保留参数。 // 返回: true = 成功执行,false=不支持字符 bool_t (*GetBitmap)(u32 charcode, u32 size, u32 resv, struct tagRectBitmap *font_bitmap); s32 (*GetCharWidth)(u32 Charcode); //获取某字符宽度 s32 (*GetCharHeight)(u32 CharCode); //获取某字符高度 }; |
DJYOS目前支持提供了ascii6x12、ascii8x16、ascii8x8、gb2312 16点阵等字体可供选择使用,要想使用某个具体字体只需调用改字体的初始化函如(如ModuleInstall_FontAscii8x12Font),该初始化函数将该字体安装到系统字体资源树节点下。
如果想使用自己创建的字体,那么过程同创建自己的字符编码过程类似,首先要实现字体数据结构中load_font、unload_font、get_char_bitmap、GetCharWidth、GetCharHeight5个钩子函数,其中load_font、unload_font两个函数可以置空。然后将该字体安装到系统字体资源树节点下即可。
11.5. 字体API说明
11.5.1. ModuleInstall_Font:字体模块初始化
ptu32_t ModuleInstall_Font(ptu32_t para)
头文件:
font.h
参数:
无。
返回值:
成功初始化则返回true;失败则返回false。
说明:
字体模块初始化,其实就是在资源链中添加字体资源根节点。
11.5.2. Font_InstallFont:安装字体
bool_t Font_InstallFont(struct tagFontRsc *font, char* name)
头文件:
font.h
参数:
font,新增的字体资源指针;
name,新增字体名。
返回值:
成功安装字体则返回true;失败则返回false。
说明:
将新字体安装到系统字体资源根节点下。
11.5.3. Font_GetCurFont:获取当前字符编码
struct tagFontRsc* Font_GetCurFont(void)
头文件:
font.h
参数:
空。
返回值:
当前字体结构体指针。
说明:
获取当前使用的字体。
11.5.4. Font_SetCurFont :设定当前字体
struct tagFontRsc* Font_SetCurFont(struct tagFontRsc* font)
头文件:
font.h
参数:
font,设定的字体结构体指针。
返回值:
设定后当前字体结构体指针。
说明:
把新字体设为当前使用的字体,新字体必须事先安装到系统中。
11.5.5. Font_SearchFont:搜索字体资源
struct tagFontRsc* Font_SearchFont(const char* name)
头文件:
font.h
参数:
name,指定的字体名称。
返回值:
如果成功搜到指定字体则返回该字体结构体指针;否则返回NULL。
说明:
从字体资源根节点下搜索指定名称的字体资源。
11.5.6. Font_GetFontLineHeight:取字体点阵行高
s32 Font_GetFontLineHeight(struct tagFontRsc* font)
头文件:
font.h
参数:
font,被查询的字体。
返回值:
该字库竖式排版时的行宽(像素值)。
说明:
获取字体中竖行排版行宽,一般是该字体中最宽的那个字符的允许宽度。
11.5.7. Font_GetFontLineWidth:取字体点阵竖行宽
s32 Font_GetFontLineWidth(struct tagFontRsc* font)
头文件:
font.h
参数:
font,被查询的字体。
返回值:
该字库最高的那个字符的宽度(像素值)。
说明:
获取字体中字符的点阵竖行宽度,即该字体中最宽的那个字符的宽度。
11.5.8. Font_GetFontAttr:取字体属性字
s32 Font_GetFontAttr(struct tagFontRsc* font)
头文件:
font.h
参数:
font,被查询的字体。
返回值:
字体属性字,font.c模块并不解析该属性字。
说明:
获取字体的属性字。
11.5.9. ModuleInstall_FontAscii6x12Font:安装ascii6x12字体
ptu32_t ModuleInstall_FontAscii6x12Font(ptu32_t para)
头文件:
ascii6x12.h
参数:
空。
返回值:
1=成功,0=失败。
说明:
安装ascii字体,当系统使用西方字符界面时,使用这个字符集。特别注意,gb2312已经包含了英文字体,在使用中文的界面中可以不安装ascii字体。
11.5.10. ModuleInstall_FontAscii8x12Font:安装ascii8x16字体
ptu32_t ModuleInstall_FontAscii8x12Font(ptu32_t para)
头文件:
ascii8x16.h
参数:
空。
返回值:
1=成功,0=失败。
说明:
安装ascii字体,当系统使用西方字符界面时,使用这个字符集。特别注意,gb2312已经包含了英文字体,在使用中文的界面中可以不安装ascii字体。
11.5.11. ModuleInstall_FontAscii8x8Font:安装ascii8x8字体
ptu32_t ModuleInstall_FontAscii8x8Font(ptu32_t para)
头文件:
ascii8x8.h
参数:
空。
返回值:
1=成功,0=失败。
说明:
安装ascii字体,当系统使用西方字符界面时,使用这个字符集。特别注意,gb2312已经包含了英文字体,在使用中文的界面中可以不安装ascii字体。
11.5.12. ModuleInstall_FontGb2312_816_1616_Array:安装ascii8x8字体
ptu32_t ModuleInstall_FontGb2312_816_1616_Array(ptu32_t para)
头文件:
gb2312_16.h
参数:
文件名。
返回值:
1=成功,0=失败。
说明:
安装gb2312 16点阵,字模保存在文件中,文件名由参数传入。
12. 显示器接口
12.1. 概述
显示器是图形显示的终端,图形的所有操作都会直接或间接的体现在显示器上面。DJYGUI支持多显示器、虚显示器和镜像显示器的功能。应用程序在调用API函数绘图前,需安装显示器,按照GK显示器标接口实现驱动函数。
GK的底层硬件标准接口函数大体分为三类,第一类是在位图中绘图,第二类是在屏幕上绘图,第三类是显示器的控制函数。安装显示器时,将这三类接口函数注册到图形系统,当用户调用GUI Kernel API时,这些驱动函数将以回调函数的方式被调用。
12.2. 镜像显示
镜像显示就是在远端计算机上显示一个与本地显示器完全一样的画面,可用于实现远程协助和远程维护。远程操作多是通过通信口进行的,主要有网络、USB、串口等。
要使用远程显示功能,必须在本地先安装一个显示器,然后把远程显示器当作该显示器的镜像显示器,GK提供API函数用于添加镜像显示器。
值得注意的是,本地显示器可以是实际存在的,也可以是虚拟的。对于实际存在的显示器,需要编写完整的显示driver,对于虚拟的,则只需要提供一个框架,driver接口中要求的接口函数,均可以不实现。与本地显示器一样,镜像显示器同样需要在本地实现一个display驱动,但不必实现所有接口函数,只需要实现显示器接口函数集中的四个函数:
l set_pixel_screen:在屏幕上绘制一个像素
l fill_rect_screen:填充一块矩形屏幕区域
l bm_to_screen:把bitmap输出到屏幕
l line_screnn:在屏幕上面画一根线
所有的绘制操作,最后都会在GK中变成对screen的输出操作,GK在执行对screen操作的同时,调用上述四个函数之一,把绘制命令传送到远端显示器,远端计算机在自己的本地显示器上实现这几个函数的功能。
镜像显示器驱动还需要图像传输协议的配合,典型的是VNCServer,该协议在DJYOS上有移植。使用VNCServer的话,远端显示器只需要安装一个VNC客户端就可以了。
12.3. 硬件接口
12.3.1. set_pixel_bm:位图中画像素
bool_t (*set_pixel_bm)(struct tagRectBitmap *Bitmap, s32 x,s32 y,u32 Color,u32 Rop2Code);
参数:
Bitmap:目标位图。
x:绘图位置的横坐标,相对于位图。
y:绘图位置的纵坐标,相对于位图。
Color:画图使用的颜色,颜色格式为真彩色。
Rop2Code:二元光栅操作码。
返回值:
true:成功;false:失败。
说明:
在矩形位图中画一个像素,若显示器使用CN_CUSTOM_PF(自定义)格式,或者有硬件加速功能,应该实现这个函数,否则直接返回false。即使有硬件加速,但该加速功能不支持r2_code编码的话,也返回false。color的格式是CN_SYS_PF_ERGB8888。
12.3.2. line_bm:位图中画直线
bool_t (*line_bm)(struct tagRectBitmap *Bitmap,struct tagRectangle *Limit,
s32 x1,s32 y1,s32 x2,s32 y2,u32 Color,u32 Rop2Code);
参数:
Bitmap:目标位图。
Limit:限制矩形,只允许在该矩形内绘制。
x1:绘图起点的横坐标,相对于位图。
y1:绘图起点的纵坐标,相对于位图。
x2:绘图终点的横坐标,相对于位图。
y2:绘图终点的纵坐标,相对于位图。
Color:画图使用的颜色,颜色格式为真彩色。
Rop2Code:二元光栅操作码。
返回值:
true:成功;false:失败。
说明:
在矩形位图中画一条任意细直线,不含端点,若显示器使用CN_CUSTOM_PF(自定义)格式,或者有硬件加速功能,应该实现这个函数,否则直接返回false。即使有硬件加速,但该加速功能不支持r2_code编码的话,也返回false。color格式是CN_SYS_PF_ERGB8888。
另外有公交车中画直线函数line_bm_ie,与line_bm的唯一区别在于,line_bm_ie画直线包括端点,而line_bm不包含端点。
bool_t (*fill_rect_bm)(struct tagRectBitmap *DstBitmap,
struct tagRectangle *Target,
struct tagRectangle *Focus,
u32 Color0,u32 Color1,u32 Mode);
参数:
DstBitmap:目标位图。
Target:目标矩形,填充范围不能超过该矩形。
Focus:聚焦矩形,当前填充矩形区域。
Color0:渐变颜色0,颜色格式为真彩色。
Color1:渐变颜色1,颜色格式为真彩色,模式为直接填充时无效。
Mode:填充模式,请参照gkernel.h宏定义组CN_FILLRECT_MODE_N。
返回值:
true:成功;false:失败。
说明:
在矩形位图中填充矩形,若显示器使用CN_CUSTOM_PF(自定义)格式,或者有硬件加速功能,应该实现这个函数,否则直接返回false。color格式是CN_SYS_PF_ERGB8888。目标矩形Target是渐变填充的整个矩形区域,聚焦矩形Focus是当前填充的可视域。Target和Focus的关系如图 4‑1所示。如需要填充Target内的三个focus区域,需要调用该函数三次,每次使用相应的Focus参数。
图 4‑1 Target和Focus关系图
12.3.4. blt_bm_to_bm:位图中显示矩形
bool_t (*blt_bm_to_bm)( struct tagRectBitmap *DstBitmap,
struct tagRectangle *DstRect,
struct tagRectBitmap *SrcBitmap,
struct tagRectangle *SrcRect,
u32 RopCode,u32 TransparentColor);
参数:
DstBitmap:目标位图。
DstRect:目标矩形。
SrcBitmap:源位图。
SrcRect:源矩形。
RopCode:光栅操作码。
TransparentColor:透明色,为真彩色。
返回值:
true:成功;false:失败。
说明:
在两个矩形位图中位图块传送,如果显示器使用的像素格式是CN_CUSTOM_PF,或者硬件2d加速支持位图块传送,需实现这个函数,否则直接返回false。对于有硬件加速,但部分RopCode编码不支持的情况,可以实现支持的RopCode,不支持的部分,返回false。本函数返回false的话,gui kernel会自行用逐像素方法拷贝。目标矩形和源矩形相对坐标不同,但大小相同。
12.3.5. get_pixel_bm:位图中读取像素
u32 (*get_pixel_bm)(struct tagRectBitmap *Bitmap,s32 x,s32 y);
参数:
Bitmap:目标位图。
x:读像素的横坐标,相对于目标位图。
y:读像素的纵坐标,相对于目标位图。
返回值:
读取的像素值,需转化为真彩色。
说明:
从矩形位图中取一像素,并转换成CN_SYS_PF_ERGB888。只有在bitmap的像素格式为CN_CUSTOM_PF时,才需要读取。如果显卡不打算支持自定义格式,本函数直接返回0。
12.3.6. get_rect_bm:位图中剪切矩形
bool_t (*get_rect_bm)(struct tagRectBitmap
*Src, struct tagRectangle *Rect, struct tagRectBitmap *Dest);
参数:
Src:源位图。
Rec:读取位图的矩形区域。
Dest:目标位图。
返回值:
true:成功;false:失败。
说明:
把src位图内rect矩形区域的内容复制到dest位图中,调用前,先设置好dest的FixelFormat,本函数不理会src的FixelFormat,直接使用screen的格式。本函数用于从窗口剪切矩形,而blt_bm_to_bm用于显示矩形。如果显示器使用的像素格式是CN_CUSTOM_PF,或者硬件加速支持位图间拷贝图形,需实现这个函数,否则直接返回false。由于dest->FixelFormat存在很多可能,即使有硬件加速,也存在只支持部分FixelFormat的情况,对不支持的格式,返回false。
12.3.7. set_pixel_screen:屏幕上画像素
bool_t (*set_pixel_screen)(s32 x,s32 y,u32 Color,u32 Rop2Code);
参数:
x:绘制像素的横坐标,相对于屏幕。
y:绘制像素的纵坐标,相对于屏幕。
Color:绘制像素的颜色,为真彩色。
Rop2Code:二元光栅操作码。
返回值:
true:成功;false:失败。
说明:
在screen中画一个像素,有frame buffer的情况下,正常显示gui不会调用这个函数,如果窗口direct_screen==true,则可能调用本函数。因此,无论是否有frame buffer,driver都必须提供并且必须实现本函数。镜像显示器的driver必须实现本函数。color的格式是CN_SYS_PF_ERGB8888,因此绘制前需转化为本地颜色格式。
12.3.8. line_screen:屏幕上画直线
bool_t (*line_screen)( tagRectangle *limit, s32 x1,s32 y1,s32 x2,s32 y2,
u32 Color,u32 Rop2Code);
参数:
limit:限制矩形,只绘制矩形内部的部分。
x1:绘图起点横坐标,相对于屏幕。
y1:绘图起点纵坐标,相对于屏幕。
x2:绘图终点横坐标,相对于屏幕。
y2:绘图终点横坐标,相对于屏幕。
Color:绘制像素的颜色,为真彩色,因此绘制前需转化为本地颜色格式。
Rop2Code:二元光栅操作码。
返回值:
true:成功;false:失败。
说明:
在screen中画一条任意直线,不含端点,如硬件加速不支持在screen上画线,driver可以简化,直接返回false即可。有frame buffer的情况下,正常显示gui不会调用这个函数,如果窗口direct_screen==true,则可能调用本函数,本函数返回false的话,会进一步调用set_pixel_screen函数。由于不确定本地显示器是否有frame_buffer,镜像显示器driver必须实现本函数,不能简单返回false。color的格式是CN_SYS_PF_ERGB8888,因此绘制前需转化为本地颜色格式。
此外,函数line_screen_ie也是在屏幕上画直线,但是它画的直线包含端点。
12.3.9. fill_rect_screen:屏幕上填充矩形
bool_t (*fill_rect_screen)(struct tagRectangle *Target,
struct tagRectangle *Focus,
u32 Color0,u32 Color1,u32 Mode);
参数:
Target:目标矩形区域。
Focus:聚焦矩形区域。
Color0:渐变颜色0,颜色格式为真彩色。
Color1:渐变颜色1,颜色格式为真彩色。
Mode:渐变填充模式。
返回值:
true:成功;false:失败。
说明:
screen中矩形填充,如硬件加速不支持在screen上矩形填充,driver可以简化,直接返回false即可。有frame buffer的情况下,正常显示gui不会调用这个函数,如果窗口direct_screen==true,则可能调用本函数,本函数返回false的话,会进一步调用set_pixel_screen函数。由于不知道本地显示器的情况,镜像显示器driver必须实现本函数,不能简单返回false。color的格式是CN_SYS_PF_ERGB8888。Target与Focus的关系如图 4‑1所示。
12.3.10. bm_to_screen:屏幕上画位图
bool_t (*bm_to_screen)(struct tagRectangle *DstRect,
struct tagRectBitmap *SrcBitmap,s32 xSrc,s32 ySrc);
参数:
DstRect:目标矩形区域。
SrcBitmap:源位图。
xSrc:源位图中显示的区域左上角横坐标,相对于源位图。
ySrc:源位图中显示的区域左上角纵坐标,相对于源位图。
返回值:
true:成功;false:失败。
说明:
从内存缓冲区到screen位块传送,只支持块拷贝,不支持rop操作。如硬件加速不支持在screen上绘制位图,driver可以简化,直接返回false即可。有frame buffer的情况下,__GK_OutputRedraw中会调用这个函数。如果窗口direct_screen==true,也可能调用本函数。本函数返回false的话,gui kernel会进一步调用set_pixel_screen函数。即使硬件加速支持,但如果不支持具体的src_bitmap->PixelFormat,也可返回false。由于不知道本地显示器的情况,镜像显示器driver必须实现本函数,不能简单返回false。
12.3.11. get_pixel_screen:屏幕上读像素
u32 (*get_pixel_screen)(s32 x,s32 y);
参数:
x:目标像素的横坐标,相对于屏幕。
y:目标像素的纵坐标,相对于屏幕。
返回值:
像素值,转化为真彩色格式。
说明:
从screen中取一像素,并转换成CN_SYS_PF_ERGB8888。
12.3.12. get_rect_screen:屏幕上读位图
bool_t (*get_rect_screen)(struct tagRectangle *Rect,struct tagRectBitmap *Dest);
参数:
rect:读取的目标矩形区域。
dest:保存矩形区域读到的位图。
返回值:
true:成功;false:失败。
说明:
把screen内矩形区域的内容复制到bitmap,调用前,先设置好dest的FixelFormat。
12.3.13. disp_ctrl:控制显示器
bool_t (*disp_ctrl)(struct display_rsc *Disp);
参数:
disp:显示器指针。
返回值:
true:成功;false:失败。
说明:
控制显示器,这是由driver提供的一个应用程序的入口,该应用程序用于提供一个可视化的方式。设定该显示器所有可以由用户设定的参数,比如分辨率和和色彩参数。函数的功能不做统一规定,驱动程序的文档应该提供函数的使用说明。利用本函数,可以提供类似windows中设置显示器属性的功能。
12.4. API说明
12.4.1. GK_ApiGetPixelFormat:查询显卡格式
u16 GK_ApiGetPixelFormat(struct tagDisplayRsc *Display)
头文件:
gkernel.h
参数:
Display:待查询的显卡
返回值:
显卡格式,也称颜色格式,如CN_SYS_PF_RGB565。
说明:
查询显卡使用的颜色格式,画位图时,如果使用跟显卡相同的颜色格式,将获得最优性能。
12.4.2. GK_InstallDisplay:安装显示器
bool_t GK_InstallDisplay(struct tagDisplayRsc *Display, char *Name)
头文件:
gk_display.h
参数:
Display:待安装的显示器。
Name:显示器名称。
返回值:
true:成功;false:失败。
说明:
把一台新显示器登记到显示器资源队列中。
12.4.3. GK_InstallDisplayMirror:安装镜像显示器
bool_t GK_InstallDisplayMirror(struct tagDisplayRsc *BaseDisplay,
struct tagDisplayRsc *MirrorDisplay,char *Name)
头文件:
gk_display.h
参数:
BaseDisplay:本地显示器。
MirrorDisplay:待安装的镜像显示器。
Name:显示器名称。
返回值:
true:成功;false:失败。
说明:
把一台镜像显示器登记到本地显示器。
12.4.4. GK_SetDefaultDisplay:设置默认显示器
bool_t GK_SetDefaultDisplay(char *Name)
头文件:
gk_display.h
参数:
Name:显示器名称。
返回值:
true:成功;false:失败。
说明:
设置默认显示器。
12.4.5. GK_GetRootWin:取显示器的默认设置
struct tagGkWinRsc *GK_GetRootWin(struct tagDisplayRsc *Display)
头文件:
gk_display.h
参数:
Display:显示器指针。
返回值:
显示器桌面指针。
说明:
取一个显示器的默认显示设置,实际上就是桌面窗口的资源节点。
12.4.6. GK_SwitchFrameBuffer:切换帧缓冲
bool_t GK_SwitchFrameBuffer(struct tagDisplayRsc *Display,
struct tagRectBitmap *FrameBuf)
头文件:
gk_display.h
参数:
Display:显示器指针。
FrameBuf:帧缓冲打针。
返回值:
true:成功;false:失败。
说明:
当一个显示器有多个Frame Buffer时,用本函数切换当前Frame Buffer。
12.4.7. GK_CreateFrameBuffer:创建帧缓冲
struct tagRectBitmap *GK_CreateFrameBuffer(struct tagDisplayRsc *Display)
头文件:
gk_display.h
参数:
Display:显示器指针。
返回值:
缓冲区指针。
说明:
为某显示器创建一个Frame Buffer。
13.程序示例
13.1. 程序调用步骤
GK初始化步骤流程如下:
1. 初始化GK,即内核初始化,调用初始化函数ModuleInstall_GK;
2. 显示器安装,将当前显示器安装到图形系统。
3. 安装字符集,创建桌面和窗口,绘图。
13.2. 参考代码
下面以天嵌开发板TQ2440举例,说明GK图形化编程。
GK图形内核的初始化对用户而言,相对简单,大部分工作已经由内核完成,用户只需调用函数ModuleInstall_GK即可。如所示,初始化内核后,调用函数ModuleInstall_Lcd实现安装名为“lcd_2440”的显示器,返回显示器指针,然后创建了显示器的桌面,并安装字符集。如代码 5‑1所示。
代码 5‑1 GK初始化
ModuleInstall_GK(0); lcd_2440 = (struct tagDisplayRsc*)ModuleInstall_Lcd((ptu32_t)"lcd_2440");
GK_ApiCreateDesktop(lcd_2440,&desktop,0,0, CN_COLOR_RED+CN_COLOR_GREEN,CN_WINBUF_BUF,0,0);
Gk_Gb2312EncodeModuleInit(0); |
函数ModuleInstall_Lcd完成的功能是初始化LCD硬件,并调用函数GK_InstallDisplay实现显示器安装。硬件初始化和显示器安装代码如代码 5‑2所示。
代码 5‑2 显示器初始化
ptu32_t ModuleInstall_Lcd(ptu32_t para) { static struct tagGkWinRsc frame_win; static struct tagRectBitmap frame_bm;
__lcd_hard_init(); __lcd_power_enable(0,1); __lcd_envid_of(1);
frame_bm.PixelFormat = cn_lcd_pf; frame_bm.width = cn_lcd_xsize; frame_bm.height = cn_lcd_ysize; frame_bm.linebytes = cn_lcd_xsize*2; frame_bm.bm_bits = (u8*)pg_frame_buffer;
frame_win.wm_bitmap =&frame_bm; tg_lcd_display.frame_buffer = &frame_win; tg_lcd_display.xmm = 0; tg_lcd_display.ymm = 0; tg_lcd_display.width = cn_lcd_xsize; tg_lcd_display.height = cn_lcd_ysize; tg_lcd_display.pixel_format = CN_SYS_PF_RGB565; tg_lcd_display.reset_clip = false; tg_lcd_display.framebuf_direct = false; //无须初始化frame_buffer和desktop,z_topmost三个成员 tg_lcd_display.draw.set_pixel_bm = __lcd_set_pixel_bm; tg_lcd_display.draw.fill_rect_bm = __lcd_fill_rect_bm; tg_lcd_display.draw.get_pixel_bm = __lcd_get_pixel_bm; tg_lcd_display.draw.line_bm = __lcd_line_bm; tg_lcd_display.draw.line_bm_ie = __lcd_line_bm_ie; tg_lcd_display.draw.blt_bm_to_bm = __lcd_blt_bm_to_bm; tg_lcd_display.draw.get_rect_bm = __lcd_get_rect_bm; tg_lcd_display.draw.set_pixel_screen = __lcd_set_pixel_screen; tg_lcd_display.draw.line_screen = __lcd_line_screen; tg_lcd_display.draw.line_screen_ie = __lcd_line_screen_ie; tg_lcd_display.draw.fill_rect_screen = __lcd_fill_rect_screen; tg_lcd_display.draw.bm_to_screen = __lcd_bm_to_screen; tg_lcd_display.draw.get_pixel_screen = __lcd_get_pixel_screen; tg_lcd_display.draw.get_rect_screen = __lcd_get_rect_screen;
tg_lcd_display.DisplayHeap = M_FindHeap("display"); tg_lcd_display.disp_ctrl = __lcd_disp_ctrl;
if(GK_InstallDisplay(&tg_lcd_display,(char*)para)) return (ptu32_t)&tg_lcd_display; else return (ptu32_t)NULL; } |
完成了GK初始化和显示器安装后,创建了第一个桌面后,便就可以实现绘图操作。如代码 5‑1所示,实现在桌面上创建窗口,并输出“Hello World!”文本到新创建的窗口。
代码 5‑3 GK应用示例
struct tagGkWinRsc desktop,win1;
desk = GK_ApiGetDesktop(“lcd_2440”); if(GK_ ApiCreateGkwin (desktop,win1,20,20,200,200,CN_COLOR_RED, CN_WINBUF_BUF,”WIN1”,CN_SYS_PF_DISPLAY,0,0,0); { GK_ApiDrawText(win1,40,80,”Hello World!”,13,CN_COLOR_BLACK,0,0); } |