1.位图显示
emWin 支持三种位图文件形式: .c 文件位图、 .dta 格式流位图和.bmp 格式位图
.c 文件形式的位图必须跟随工程文件一起放置在 MCU 的内部 FLASH 中,这就导致 c 文件位图的大小、质量和数量等受到内部 FLASH 容量的限制。相反流位图可放置在任何存储器中,并可按照与 C 文件位图相同的方式使用
(1)BmpCvt[位图转换器]
作用将位图从PC格式转换为C文件,emwin可使用的位图在C文件中定义为
GUI_BITMAP结构体。
注:如果图片要转化为bmp格式,可以用画图软件,像素大小要合适
1)配置颜色保存模式
设置如下:

讯享网
2)打开文件添加图片
3)保存C文件
4)选择C文件的颜色格式
选择RGB565格式

通过上述步骤,即可成功创建 BMP 图像文件的 C 数组。如果需要生成.dta 格式的流位图,在保存文件时选择保存类型为.dta 文件即可。
生成的主要代码:

GUI_BITMAP 结构体
typedef struct {
U16P XSize; U16P YSize; U16P BytesPerLine; U16P BitsPerPixel; const U8 * pData; const GUI_LOGPALETTE * pPal; const GUI_BITMAP_METHODS * pMethods; } GUI_BITMAP; 1) XSize:位图的宽度; 2) YSize:位图的高度; 3) BytesPerLine:位图图像每一行的字节数,该参数与位图的宽度和颜色格式有关, 假设位图使用的颜色格式是 ARGB8888,乘上图片的宽度,就是图像每一行的字节数; 4) BitsPerPixel:位图图像单个像素所占的位数,该参数和上一个参数都与位图的宽 度和颜色格式有关,假设位图使用的颜色格式是 ARGB8888,那么图像单个像素数据就 占 32 位; 5) pData:指向位图像素数据; 6) pPal:调色板,该参数在 24 位色及以上的位图中是没有的,只有低于 24 位色的 位图才有调色板; 7) pMethods: emWin 的绘图调色板,在位图转换时生成。
讯享网
绘制位图API

GUI_DrawBitmap()
在当前窗口中的指定位置绘制位图图像。
讯享网void GUI_DrawBitmap(const GUI_BITMAP * pBM, int x, int y); 1) pBM:指向要显示的位图的指针; 2) x:位图在显示屏中左上角的 X 轴坐标; 3) y:位图在显示屏中左上角的 Y 轴坐标。
GUI_DrawBitmapEx()
通过此例程可以缩放和/或镜像显示屏上的位图
void GUI_DrawBitmapEx(const GUI_BITMAP * pBitmap, int x0, int y0, int xCenter, int yCenter, int xMag, int yMag); 1) pBM:指向要显示的位图的指针; 2) x0:显示屏中定位点的 X 坐标; 3) y0:显示屏中定位点的 Y 坐标; 4) xCenter:位图中定位点的 X 坐标; 5) yCentert:位图中定位点的 Y 坐标; 6) xMag:X方向的缩放比例因子,单位为 1/1000,当值为负值时将在 X 轴镜像位图; 7) yMag:Y方向的缩放比例因子,单位为 1/1000,当值为负值时将在 Y 轴镜像位图。
GUI_CreateBitmapFromStream()
函数通过传递任何类型的位图流来创建位图结构体
讯享网int GUI_CreateBitmapFromStream( GUI_BITMAP * pBMP, GUI_LOGPALETTE * pPAL, const void * p); 1) pBMP:指向要由函数初始化的 GUI_BITMAP 结构体的指针; 2) pPAL:指向要由函数初始化的 GUI_LOGPALETTE 结构体的指针; 3) p:指向数据流的指针。
void GUI_DrawStreamedBitmapAuto(const void * p, int x, int y); 1) p:指向数据流的指针; 2) x:显示屏中位图左上角的 X 坐标; 3) y:显示屏中位图左上角的 Y 坐标。
效果:

2.颜色
逻辑颜色和物理颜色
逻辑颜色:应用程序处理的颜色,包含三个 8位的颜色分量和一个 8 位的 alpha 通道。
逻辑颜色有ABGR和ARGB
ABGR:

ARGB:

现在主要使用ARGB这个格式
物理颜色是显示器实际显示的颜色,在运行时,逻辑颜色映射到物理颜色
调色板:

注:
调色板的标识符有些带有字母 M,而另外一些则不带字母 M。这也是跟之前的逻辑颜色格式有关,含字母 M 的表示 ARGB 颜色格式使用的板,不带 M的表示在 ABGR 格式下使用的调色板
色彩深度和像素格式
色彩深度 (color depth),也称为位深度 (bit depth),表示图像中存储一个像素的色彩信息所占用的位数,单位是位/像素 (bits per pixel) 或 bpp。
通常说的什么 8 位、 24 位图像,这个多少位指的就是色彩深度。色彩深度越大,则单个像素包含的色彩信息越多,图像整体的颜色就越丰富。常见的色彩深度有 1bpp、 4bpp、 8bpp、 16bpp、 24bpp 和 32bpp。
像素格式 (pixel format),它表示为一个像素的颜色信息以什么样的方式和顺序进行存储。
如 RGB565 表示用 16 位的色彩深度存储单个像素的颜色信息,从高位到低位依次存放红绿蓝三色,其中红色和蓝色占 5 位,绿色占 6 位。同一种色彩深度可以对应不同的像素格式。还是刚才的 RGB565 像素格式,这次我交换红色和蓝色的存放顺序,就变成了另一种像素格式 BGR565,但色彩深度还是 16 位
重要颜色API
讯享网GUI_SetBkColor() 设置背景色颜色 GUI_SetColor() 设置前景色颜色
3.内存设备
内存设备是 emWin 的一种绘图机制,可以用在各种绘图操作中,可以通过它实现一些华丽炫酷的界面效果。不过其最主要的作用是用来消除在绘制重叠项目时出现的屏幕闪烁。
如果使用内存设备,所有的绘制操作都在内存中进行,绘制完成后才更新到屏幕,所以没有闪烁。所谓闪烁其实就是屏幕出现了明显可观察到的绘图过程,而内存设备机制只将绘制完成的图形写入屏幕,所以观察不到明显的绘图过程,也就消除了闪烁。
常用API
1.GUI_MEMDEV_CopyToLCD()
将内存设备的内容从内存复制到 LCD
void GUI_MEMDEV_CopyToLCD(GUI_MEMDEV_Handle hMem ); hMem:内存设备的句柄。
注:该函数忽略窗口管理器的剪切区域和 alpha 通道。因此,不建议在 paint 事件中使用此函数。为了显示关于剪切区域和 alpha 通道的内存设备,应该使用函数 GUI_MEMDEV_WriteAt()。
2.GUI_MEMDEV_CopyToLCDAt()
将内存设备的内容复制到 LCD 的指定位置。
讯享网void GUI_MEMDEV_CopyToLCDAt(GUI_MEMDEV_Handle hMem, int x, int y); 1) hMem:内存设备的句柄; 2) x:指定的 X 位置; 3) y:指定的 Y 位置。
3.GUI_MEMDEV_Create()
创建一个内存设备。
GUI_MEMDEV_Handle GUI_MEMDEV_Create(int x0, int y0, int xSize, int ySize); 1) x0:内存设备的 X 位置; 2) y0:内存设备的 Y 位置; 3) xSize:内存设备的 X 方向大小; 4) ySize:内存设备的 Y 方向大小。 返回值:创建的内存设备句柄,如果创建失败,则返回值为 0。
4.GUI_MEMDEV_CreateFixed()
创建一个具有固定色彩深度和调色板的内存设备。
讯享网GUI_MEMDEV_Handle GUI_MEMDEV_CreateFixed ( int x0, int y0, int xSize, int ySize, int Flags, const tLCDDEV_APIList * pMemDevAPI, const LCD_API_COLOR_CONV *pColorConvAPI ); 1) x0:内存设备的 X 位置; 2) y0:内存设备的 Y 位置; 3) xSize:内存设备的 X 方向大小; 4) ySize:内存设备的 Y 方向大小; 5) Flags:创建标志,允许的参数如下: GUI_MEMDEV_HASTRANS:默认值,内存设备使用透明标志创建,该标志确保正确 绘制背景; GUI_MEMDEV_NOTRANS:创建不透明的内存设备,必须正确绘制背景。可用于非 矩形区域,比透明标志内存设备快 30 - 50%。 6) pMemDevAPI:定义内存设备的色彩深度,允许的参数值如下: GUI_MEMDEV_APILIST_1:创建具有 1bpp 色彩深度的内存设备; GUI_MEMDEV_APILIST_8:创建具有 8bpp 色彩深度的内存设备; GUI_MEMDEV_APILIST_16:创建具有 16bpp 色彩深度的内存设备; GUI_MEMDEV_APILIST_32:创建具有 32bpp 色彩深度的内存设备。 7) pColorConvAPI:所需的固定调色板,允许的参数值如下: GUICC_1:固定调色板模式 1(黑/白); GUICC_2:固定调色板模式 2(4 种灰度); GUICC_4:固定调色板模式 4(16 种灰度); GUICC_565:固定调色板模式 565; GUICC_M565:固定调色板模式 M565; GUICC_8666:固定调色板模式 8666; GUICC_888:固定调色板模式 888; GUICC_8888:固定调色板模式 8888。 返回值:创建的内存设备句柄,如果创建失败,则返回值为 0
5.GUI_MEMDEV_Delete()
删除内存设备。
void GUI_MEMDEV_Delete(GUI_MEMDEV_Handle MemDev); hMem:需要删除的内存设备句柄。
6.GUI_MEMDEV_Select()
激活内存设备 / (如果句柄为 0,则激活 LCD)。
讯享网GUI_MEMDEV_Handle GUI_MEMDEV_Select(GUI_MEMDEV_Handle hMemDev); hMem:内存设备的句柄。 返回值:上一个内存设备的句柄,如果上一次选择的是 LCD,则返回 0。
大致步骤:

GUI_MEMDEV_Handle hMem = 0; //创建一个句柄对象 hMem = GUI_MEMDEV_Create(Rect.x0, Rect.y0, Rect.x1 - Rect.x0, Rect.y1 - Rect.y0); //创建存储设备 其实就是一个矩形框 GUI_MEMDEV_Select(hMem); //选择hMem作为绘制操作目标的存储设备 _Draw(0); //执行要显示的内容复制到存储设备中 GUI_MEMDEV_Select(0); //选中LCD ,激活内存设备 (如果句柄为 0,则激活 LCD)。 GUI_MEMDEV_CopyToLCDAt(hMem, LCD_GetXSize() - Rect.x1, Rect.y0); //将存储设备的内容从内存复制到LCD的指定位置
4.窗口管理器
窗口管理器是 emWin 的核心功能。窗口就是应用程序对应的一个个矩形区域,而窗口管理器用来管理这些矩形区域。
一些术语:
讯享网活动窗口:当前用于绘图操作的窗口称为活动窗口。它不一定就是最上层的窗口 回调函数:回调函数由用户程序定义,指示图形系统在发生特定事件时调用特定函数。 通常,当窗口的内容发生更改时,它们用于自动重绘窗口 子窗口/父窗口 : 子窗口是相对于其他窗口(称为父窗口)定义的。只要父窗口移动,其子窗口就 会相应移动。子窗口始终完全包含在其父窗口中,并在必要时会被裁剪。具有相 同父窗口的多个子窗口被视为同属窗口 客户区: 客户区就是窗口的的可用区域。如果一个窗口包含一个框架或标题栏,那么客户 端区域就是矩形的内部区域。如果没有这样的框架,则客户端区域的坐标与窗口 本身的坐标相同。 裁剪,裁剪区域: 裁剪是将输出限制为窗口或窗口的一部分的过程。窗口的剪辑区域是其可见区 域,是窗口区域减去被更高 Z 轴阶层的同属窗口遮挡的区域,然后减去没有放入 父窗口可见区域的任何部分 坐标: 坐标通常是二维坐标,以像素为单位表示(x,y) 桌面坐标: 桌面坐标是桌面窗口的坐标。屏幕的左上角位置 (原点) 是 (0,0) 桌面窗口(背景窗口): 由窗口管理器自动创建的,并且总是覆盖整个显示区域。 桌面窗口在 emWin 初始化完成后就创建好了, 之后所有的操作都在桌面窗口基础上进行 前期裁剪/后期裁剪: 前期裁剪是默认的裁剪模式。 裁剪动作在窗口接收绘制事件之前执行。 如果需要裁剪当前窗口,它将在单个绘图过程中接收多个 WM_PAINT 消息。 后期裁剪,窗口始终只接收一条 WM_PAINT 消息, 此时裁剪动作在绘图操作中执行 句柄: 创建新窗口时,窗口管理器会为其分配一个名为句柄的唯一标识符。句柄用于在 该特定窗口上执行的任何进一步操作 隐藏/显示窗口: 一个隐藏的窗口是不可见的,尽管它仍然存在 (有一个句柄)。 创建窗口时,如果没有指定创建标志,则默认情况下它是隐藏的。 父坐标: 父坐标是相对于父窗口的窗口坐标。窗口的左上角位置(原点)是(0,0) 窗口坐标: 窗口坐标是窗口的坐标。窗口的左上位置(原点)是(0,0)。 透明度: 具有透明度的窗口包含不随窗口其余部分重新绘制的区域。这些区域的运作方式 就像“透过”它们背后的窗口一样。在这种情况下,重要的是要在窗口之前以透 明的方式重新绘制后面的窗口。窗口管理器自动按照正确的顺序处理重绘。 有效化/无效化: 一个有效的窗口是一个完全更新的窗口,它不需要重新绘制。无效窗口尚未反映 所有更新,因此需要全部或部分重新绘制。 当发生影响特定窗口的更改时,窗口 管理器将该窗口标记为无效。下一次重新绘制窗口 (手动或通过回调例程) 时,将 验证它 Z 轴位置,底部/顶部: 虽然窗口以 X 和 Y 的形式显示在二维屏幕上,但窗口管理器还可管理 Z-位置 (深 度坐标) 即虚拟三维中的一个位置,它决定了窗口从背景到前景的位置。 将一个窗口设置为底部将把它“放在”它所的同属窗口 (如果有的话) 下面; 将它设置为顶部将会将它“置于”它的同属窗口之上。 创建窗口时,如果没有指定创建标志,则默认将其设置为顶部。
窗口的特点:
是矩形的; 有一个 Z 位置; 可能隐藏或显示; 可能包含有效和/或无效区域; 可能有也可能没有透明度; 可能有也可能没有回调函数。
窗口管理器的回调机制、无效化和渲染
1)使用回调函数渲染窗口
想要创建具有回调的窗口,必须定义一个回调函数
当使用 WM_CreateWindow() 函数创建窗口时,这个回调函数将作为参数
回调函数
讯享网void Callback(WM_MESSAGE * pMsg); // pMsg:指向 WM_MESSAGE 类型结构体的指针 结构体: struct WM_MESSAGE {
int MsgId; /* 消息类型 */ WM_HWIN hWin; /* 目标窗口 */ WM_HWIN hWinSrc; /* 源窗口 */ union {
const void * p;/* 消息特定数据指针 */ int v; GUI_COLOR Color; void (* pFunc)(void); } Data; }; 1) MsgId:消息类型; 2) hWin:目标窗口; 3) hWinSrc:源窗口; 4) Data:数据联合体,其中比较重要的两个参数如下: • p:消息特定数据指针; • v:消息数据
回调函数中执行的具体操作取决于它接收的消息类型。窗口回调函数中需要构建一个 switch 语句,它使用一个或多个 case 语句为不同的消息定义不同的行为。通常至少需要存在一个 WM_PAINT消息
窗口通过 WM_PAINT 消息重绘自身,不过在将此消息发送到窗口之前,窗口管理器需要确保需要重绘的窗口已被选中。普通窗口收到 WM_PAINT 消息后,默认情况下会重绘自身整个区域。为了加快绘制过程,窗口管理器的裁剪机制会确保只重绘窗口的无效区域
emWin 支持多种消息类型,主要分为四大类

桌面窗口重绘和回调
在窗口管理器初始化期间,会创建一个包含整个 LCD 区域的窗口作为桌面窗口。这个窗口的句柄是 WM_HBKWIN。
由于没有默认的背景颜色,窗口管理器并不会自动重绘桌面窗口区域。
如果你创建了一个新的窗口然后删除它,这个窗口仍然可见不会消失。
解决办法是通过WM_SetDesktopColor() 函数设置用于重绘桌面窗口的颜色。
或者可以设置一个回调函数来处理这个问题。如果像上面一样创建并删除一个窗口,回调函数将触发窗口管理器确认桌面窗口不再有效并自动重绘。
窗口无效化
无效窗口或窗口的一部分失效区域会告诉窗口管理器,在下一次调用重绘函数时重绘窗口的无效区域。
emWin 提供的无效化函数不负责重绘窗口的无效部分,它们只负责管理窗口的无效区域。
无效化函数:
void WM_InvalidateWindow(WM_HWIN hWin); 使指定窗口无效。hWin 窗口句柄 void WM_InvalidateRect(WM_HWIN hWin, GUI_RECT* pRect); 使窗口的指定矩形区域无效。 hWin 窗口句柄 pRect 指向带父窗口的窗口坐标的GUI_RECT结构的指针 void WM_InvalidateArea(GUI_RECT* pRect); 使显示器的指定矩形区域无效 pRect:指向带有桌面坐标的GUI_RECT结构的指针
真正负责重绘的是 GUI_Exec() 或 GUI_Delay() 等函数。
裁剪机制
窗口的绘制或重绘通常是通过发送一次 WM_PAINT 消息来完成的。
但是,如果一个窗口的部分区域被子窗口或任何其他窗口覆盖,那么被覆盖的窗口将会重复接收到若干次的 WM_PAINT 消息。
窗口管理器将窗口未被覆盖的区域裁剪成若干子矩形。在此过程中,
窗口管理器将每个子矩形都设置为裁剪区域,并将所有子矩形的 WM_PAINT 消息都发送给被覆盖的窗口。
窗口被覆盖的区域越碎片,存在的矩形就越多,发送的消息就越多。因此,在处理WM_PAINT 消息的程序中不应该执行费时的操作。
渲染透明窗口
如果需要绘制或重绘透明窗口,窗口管理器将自动确保在透明窗口收到 WM_PAINT 消息之前绘制窗口的背景。
实现方法是,在向透明窗口发送 WM_PAINT 消息前,先重绘透明窗口无效区域下的所有窗口区域,然后再向透明窗口发送 WM_PAINT 消息。
透明窗口的重绘操作必须在WM_PAINT 消息内进行,否则可能无法正确绘制外观。透明窗口比普通不透明窗口更耗费 CPU。
自动使用内存设备
窗口管理器的默认行为是向每个需要重绘的窗口发送 WM_PAINT 消息,这可能导致闪烁现象。使用内存设备可以在绘图操作时自动抑制每个窗口的闪烁现象
通过在创建窗口时设置WM_CF_MEMDEV 标志,或使用 WM_SetCreateFlags() 函数设置默认创建标志即可使用内存设备进行重绘操作,或使用函数 WM_EnableMemdev() 为指定窗口开启内存设备
窗口管理器将 WM_PAINT 消息的输出位置重定向到内存设备中,重绘完成后把内存设备中的内容复制到屏幕上。
以上这些内存设备都是在窗口管理器发送 WM_PAINT 消息之前在内部创建的,并在重绘完成后立即删除。如果使用内存设备重绘透明窗口,那么窗口无效区域下方的内容也会放到内存设备中进行重绘。
重要窗口管理器 API
讯享网void WM_BringToBottom(WM_HWIN hWin); 将指定的窗口放在其同属窗口的底部。 hWin:窗口句柄 注:执行该函数后,窗口将被放置在所有其他同属窗口的下方,但仍将位于其父窗口的 前面。WM_BringToTop() 函数与其相反 WM_HWIN WM_CreateWindow(int x0, int y0, int xSize, int ySize, U32Style, WM_CALLBACK * cb, int NumExtraBytes); 1) x0:窗口坐标中的左上 X 位置; 2) y0:窗口坐标中的左上 Y 位置; 3) xSize:窗口的 X 方向大小; 4) ySize:窗口的 Y 方向大小; 5) Style:窗口创建标志,最常用的有 WM_CF_MEMDEV(使用内存设备)、 WM_CF_SHOW(开启显示) 等标志 6) cb:指向回调函数的指针,如果没有使用回调函数则填 NULL; 7) NumExtraBytes:要分配的额外字节数,通常为 0。 返回值:创建好的窗口的句柄 WM_HWIN WM_CreateWindowAsChild(int x0, int y0, int xSize, int ySize, WM_HWIN hWinParent, U32 Style, WM_CALLBACK* cb, int NumExtraBytes); 1) x0:窗口坐标中的左上 X 位置; 2) y0:窗口坐标中的左上 Y 位置; 3) xSize:窗口的 X 方向大小; 4) ySize:窗口的 Y 方向大小; 5) hWinParent:父窗口的句柄; 6) Style:窗口创建标志,同 WM_CreateWindow(); 7) cb:指向回调函数的指针,如果没有使用回调函数则填 NULL; 8) NumExtraBytes:要分配的额外字节数,通常为 0。 返回值:创建好的窗口的句柄。 注:如果 hWinParent 参数设置为 0,则使用桌面窗口作为父窗口 void WM_DefaultProc(WM_MESSAGE * pMsg); 默认的消息处理函数 x0:消息指针。 该函数用来处理用户不关心或不处理的各种消息。 void WM_DeleteWindow(WM_HWIN hWin); 删除指定窗口。并释放窗口动态分配的内存 如果指定的窗口具有子窗口,则在删除窗口本身之前,自动删除这些子窗口。 WM_HWIN WM_GetDialogItem(WM_HWIN hDialog, int Id); 返回指定对话框中的指定控件的句柄 hDialog:对话框句柄; Id:控件 ID。 返回值:控件句柄。 创建对话框时必须使用此函数,因为对话框中使用的控件 ID 必须在使用前转换为句柄 void WM_HideWindow(WM_HWIN hWin); 调用此函数后,窗口不会立即隐藏。只有当执行 WM_Exec() 重绘后,才会被隐藏 如果需要立即隐藏一个窗口,应该调用 WM_Paint 来重绘。 WM_ShowWindow() 函数与其类似 void WM_InvalidateWindow(WM_HWIN hWin); 无效化指定窗口 void WM_MoveTo(WM_HWIN hWin, int x, int y); 将指定的窗口移动到指定位置 void WM_MoveWindow(WM_HWIN hWin, int dx, int dy); 将指定的窗口移动一定距离 1) hWin:需要移动的窗口的句柄; 2) dx:水平移动距离; 3) dy:垂直移动距离。 WM_CALLBACK * WM_SetCallback(WM_HWIN hWin, WM_CALLBACK * cb); 设置要由窗口管理器执行的回调例程,可以是自定义回调 1) hWin:需要设置的窗口的句柄; 2) cb:指向回调函数的指针。 返回值:上一个回调函数的指针。 U8 WM_SetCreateFlags(U8 Flags); 设置创建新窗口时默认使用的标志 1) Flags:窗口创建标志, 此函数设置的创建标志会影响到所有窗口,可以通过此函数在 GUI_Init() 之前设置 创建标志。通常此函数与 WM_CF_MEMDEV 标志一起使用,用于在所有窗口上启用内存 设备 GUI_COLOR WM_SetDesktopColor(GUI_COLOR Color); 设置桌面窗口的颜色。 由于桌面窗口默认没有指定颜色,所以它没有重绘功能。使用此函数设置桌面窗口颜色 后,桌面窗口就可以重绘自身 void WM_GetInsideRect(GUI_RECT* pRect) 返回客户区的坐标,该区域由活动小工具尺寸减去边界尺寸确定 int GUI_Exec(void); 执行回调函数(通常为重新绘制窗口)。 如果未执行任务,则返回值为0。 如果执行了一个任务,则返回值为1。 此函数将自动重复调用GUI_Exec1(),直至完成所有作业–实质是直至返回0值为止。 正常情况下,用户应用不需要调用此函数。它自动由GUI_Delay()调用。 int GUI_Exec1(void); 执行一个回调函数(仅一个任务——通常为重新绘制窗口)。
窗口创建标志

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/39797.html