|
特别说明:pdf版60期emWin教程已经发布:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=2932
armfly-x2,x3,v2,v3,v5开发板裸机和带系统的emWin工程已经全部建立,链接如下:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=1830
再次强调一下,存储设备非常重要,要想做出华丽的界面,关于存储设备方面的东西一定要学习的各种熟悉。要
不设计出来的界面永远是菜鸟级别的,最近我也在学习这方面的东西。
考虑了一下,决定还是把官方在这方面做的几个例子分析一下,希望可以帮到大家,本期分析一下这个例子
MEMDEV_ImageFlow, 显示效果如下:
本期分为两个小节:
17. 1 例子概括说明
17. 2 函数分析
17. 1 例子概括说明
例程位置: 让这个例子运行的方法看第四期教程emWin模拟器的使用方法。
下面用三个emWin官方小软件查看输出结果:
第一个:emWinView.exe
第二个:emVNC.exe
第一步:
第二步:点击链接后的效果
第三个:emWin模拟器的输出效果
下面简单的介绍一下这个函数实现的功能:
1. 整体上面就是实现了7张图片的环形浏览。
2. 主要用到下面几个存储设备的函数,在第十六期已经和大家讲过。
GUI_MEMDEV_Select
GUI_MEMDEV_CreateFixed
GUI_MEMDEV_DrawPerspectiveX
GUI_MEMDEV_WriteAt
3. 这个例子涉及到虚拟显示区的问题,在文件LCDConf.c文件里面
#define XSIZE_PHYS 320
#define YSIZE_PHYS 240
#define VYSIZE_PHYS (YSIZE_PHYS<<1)
LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS); /* 设置显示区的尺寸 */
LCD_SetVSizeEx (0, VXSIZE_PHYS, VYSIZE_PHYS); /* 设置虚拟显示区的尺寸 */
举一个例子,比如我们的显示器实际显示大小是320*240,如果设置了虚拟显示区
将其设置成320*480,那么我们在显示器上面只能看到如下的效果:
要想看到虚拟显示区部分,需要用emWin查看器,显示效果如下
17. 2 函数分析
1. 主函数就不分析了,比较简单。
2. _DemoImageFlow
该函数实现一张图片的循环。
static void _DemoImageFlow(void) {
int Index;
/* 存储设备函数句柄 */
GUI_MEMDEV_Handle ahMem[GUI_COUNTOF(_apData)] = {0};
GUI_MEMDEV_Handle ahMemNarrow[6] = {0};
/* 申请7张图片所需的内存空间,以及6个内存空间(下面讲这6个用什么)*/
if (_GetImages(ahMem, ahMemNarrow, GUI_COUNTOF(ahMem)) == 0) {
GUI_SetColor(0xFFFFFF);
GUI_SetTextMode(GUI_TM_TRANS);
GUI_SetFont(&GUI_Font24B_ASCII);
/* 下面这几个在前面几期都讲过,又不懂去看看,或者看手册都可以的 */
/* 有一点要注意,对于实际显示区和虚拟显示区做了相同的处理 */
GUI_DrawGradientV(0, 0, 319, 49, 0x800000, 0x800000);
GUI_DrawGradientV(0, 30, 319, 49, 0x800000, 0xFFFFFF);
GUI_DrawGradientV(0, 220, 319, 239, 0xFFFFFF, 0x800000);
GUI_DrawGradientV(0, 0 + 240, 319, 49 + 240, 0x800000, 0x800000);
GUI_DrawGradientV(0, 30 + 240, 319, 49 + 240, 0x800000, 0xFFFFFF);
GUI_DrawGradientV(0, 220 + 240, 319, 239 + 240, 0xFFFFFF, 0x800000);
GUI_DispStringHCenterAt("armfly-v5 Demo", 190, 6);
GUI_DispStringHCenterAt("armfly-v5 Demo", 190, 246);
GUI_DrawBitmap(&bmlogo, 6, 6);
GUI_DrawBitmap(&bmlogo, 6, 246);
Index = 0;
/* 主要通过下面的函数实现图片的循环 */
do {
_DrawScreenAnimated(ahMem, ahMemNarrow, GUI_COUNTOF(ahMem), Index);
GUI_Delay(2000);
if (++Index == GUI_COUNTOF(ahMem)) {
Index = 0;
}
} while (1);
}
}
3. _GetImages
申请7张图片所需的内存空间,以及6个内存空间,6个空间是给函数GUI_MEMDEV_DrawPerspectiveX使用的,用在这
6个地方。
static int _GetImages(GUI_MEMDEV_Handle * phMem, GUI_MEMDEV_Handle * phMemNarrow, int MaxItems) {
int i;
GUI_JPEG_INFO Info;
/*
* Draw the JPEG files into memory devices
*/
for (i = 0; (i < GUI_COUNTOF(_apData)) && (i < MaxItems); i++) {
GUI_JPEG_GetInfo(_apData, _aSize, &Info);
/* 通过函数GUI_MEMDEV_CreateFixed申请7张图片所需的控件 */
*(phMem + i) = GUI_MEMDEV_CreateFixed(0, 0, Info.XSize, Info.YSize, GUI_MEMDEV_NOTRANS, GUI_MEMDEV_APILIST_32, &LCD_API_ColorConv_888);
if (*(phMem + i) == 0) {
return 1;
}
/* 选择使用刚才申请的内存空间*/
GUI_MEMDEV_Select(*(phMem + i));
/* 将图片画到内存空间里面 */
GUI_JPEG_Draw(_apData, _aSize, 0, 0);
}
/* 清除 */
GUI_MEMDEV_Select(0);
/*
* Create memory devices for the 6 narrow outer p_w_picpath
*/
for (i = 0; i < 6; i++) {
*(phMemNarrow + i) = GUI_MEMDEV_CreateFixed(0, 0, 60, 120, GUI_MEMDEV_NOTRANS, GUI_MEMDEV_APILIST_32, &LCD_API_ColorConv_888);
if (*(phMemNarrow + i) == 0) {
return 1;
}
}
return 0;
}
4. _DrawScreenAnimated
此函数是这个例子里面最重要的部分,这个函数有一点必须要注意,图像在实际显示区和虚拟显示区
都做了输出,而且输出的图像是一样的,只是节拍不太一样,从下面的这个图可以看出,请仔细看中间
显示的那幅图就可以。
static void _DrawScreenAnimated(GUI_MEMDEV_Handle * phMem, GUI_MEMDEV_Handle * phMemNarrow, int MaxItems, int Index) {
static int ScreenIndex = 1;
int i, j, yOff, aIndex[8];
int TimeStart, aTimeUsed[GUI_COUNTOF(_aParaL)];
/*
* Initialize index
*/
for (i = GUI_COUNTOF(aIndex) - 1; i >= 0; i--) {
/* 每次通过不同的index得到7张图片不同的显示顺序 */
aIndex = (Index++) % MaxItems;
}
/*
* Do screen animation
*/
/* 下面的for循环实现图片的动态切换效果 */
for (i = 0; i < GUI_COUNTOF(_aParaL); i++) {
GUI_SetClipRect(&_aRect[ScreenIndex]);
TimeStart = GUI_GetTime();
/*
* On first iteration store outer p_w_picpath into memory devices
* for later use
* 第一次迭代的时候,先将相应的图片放入到相应的内存设备中
*/
if (i == 0) {
for (j = 0; j < 6; j++) {
GUI_MEMDEV_Select(*(phMemNarrow + j));
GUI_SetBkColor(0xFFFFFF);
GUI_ClearRect(0, 0, 59, 119);
/* 这个地方大家摸索一下逻辑关系,有一点要特别的注意phMemNarrow + 0和phMemNarrow + 5是存的相同的图片
为什么存的相同的图片,大家看一下实验效果理解一下。
*/
if (j < 3) {
/* 放到左侧的三幅图 0,1,2 =》 0,6,5 */
_DrawPerspective(*(phMem + aIndex[0 + j]), 0, 0, 120, 80, 60);
} else {
/* 放到右侧的三幅图 5,6,7 =》 2,1,0 */
_DrawPerspective(*(phMem + aIndex[2 + j]), 0, 0, 80, 120, 60);
}
}
GUI_MEMDEV_Select(0);
}
yOff = 50;
/*
* Manage background
*/
GUI_SetBkColor(0xFFFFFFFF);
GUI_ClearRect(0, _ayOffScreen[ScreenIndex] + yOff, 319, _ayOffScreen[ScreenIndex] + 169 + yOff);
/*
* Draw 3 p_w_picpath at the left side
*/
GUI_MEMDEV_WriteAt(*(phMemNarrow + 0), -35 + _axOffPicture, _ayOffScreen[ScreenIndex] + 25 + yOff);
GUI_MEMDEV_WriteAt(*(phMemNarrow + 1), - 5 + _axOffPicture, _ayOffScreen[ScreenIndex] + 25 + yOff);
GUI_MEMDEV_WriteAt(*(phMemNarrow + 2), 25 + _axOffPicture, _ayOffScreen[ScreenIndex] + 25 + yOff);
/*
* Draw 3 p_w_picpath at the right side
*/
GUI_MEMDEV_WriteAt(*(phMemNarrow + 5), 265 + _axOffPicture, _ayOffScreen[ScreenIndex] + 25 + yOff);
GUI_MEMDEV_WriteAt(*(phMemNarrow + 4), 235 + _axOffPicture, _ayOffScreen[ScreenIndex] + 25 + yOff);
GUI_MEMDEV_WriteAt(*(phMemNarrow + 3), 205 + _axOffPicture, _ayOffScreen[ScreenIndex] + 25 + yOff);
/*
* Draw fade-in/fade-out effect
*/
/* 下面的函数说白了就是第三张下面第四章在上面,大于9以后反过来 */
if (i < 9) {
_DrawPerspective(*(phMem + aIndex[3]), 55 + _aParaL.xOff, _ayOffScreen[ScreenIndex] + yOff + _aParaL.yOff, _aParaL.h0, _aParaL.h1, _aParaL.w);
_DrawPerspective(*(phMem + aIndex[4]), 85 + _aParaR.xOff, _ayOffScreen[ScreenIndex] + yOff + _aParaR.yOff, _aParaR.h0, _aParaR.h1, _aParaR.w);
} else {
_DrawPerspective(*(phMem + aIndex[4]), 85 + _aParaR.xOff, _ayOffScreen[ScreenIndex] + yOff + _aParaR.yOff, _aParaR.h0, _aParaR.h1, _aParaR.w);
_DrawPerspective(*(phMem + aIndex[3]), 55 + _aParaL.xOff, _ayOffScreen[ScreenIndex] + yOff + _aParaL.yOff, _aParaL.h0, _aParaL.h1, _aParaL.w);
}
/*
* Wait a while (if required)
*/
aTimeUsed = GUI_GetTime() - TimeStart;
if (aTimeUsed < MIN_TIME_PER_PICTURE) {
GUI_Delay(MIN_TIME_PER_PICTURE - aTimeUsed);
}
/*
* Manage screen origin
*/
/* 实现实际显示区和虚拟显示区的切换 */
ScreenIndex += 1;
if (ScreenIndex == 2) {
ScreenIndex = 0;
}
GUI_SetOrg(0, _ayOffScreen[ScreenIndex ^ 1]);
}
}
这个例子就分析到这里。 |
|