数码相框项目学习笔记(三)

数码相框项目笔记

页面模块

这个是整个项目中的主体部分,该模块实现页面设计、显示、侦听输入事件、相应输入事件的功能。它同样提供了管理模块,当要增加页面时,向其注册即可。
1、主页面
主页面比较简单,提供三个按钮:浏览模式、连播模式、设置
点击浏览模式---->显示浏览页面
点击连播模式---->显示连播页面
点击设置---->显示设置界面
点击其他区域---->不作回应
大致设计效果如图:
在这里插入图片描述
在开发板上实际运行效果:

主页面上要显示图标,先要计算出每个图标的坐标值,如上图所示,然后调用解析和渲染模块,将RGB数据写入显存,在屏幕上显示页面。
如何确定用户点击了图标呢?直接通过输入模块读取触点的坐标,判断坐标位置是否位于图标区域即可。
主页面函数的核心在于run函数(MainPageRun),此函数主要做两件事:一是显示页面,二是调用输入模块获得数据,根据输入执行不同的动作。

/* 主页面运行函数:显示页面、处理输入事件 */
static void MainPageRun(PT_PageParams ptParentPageParams)
{
	int iIndex;
	T_InputEvent tInputEvent;
	int bPressed = 0;
	int iIndexPressed = -1;
    T_PageParams tPageParams;

    tPageParams.iPageID = ID("main");
	
	/* 1. 显示页面 */
	ShowMainPage(&g_tMainPageLayout);
	
	/* 2. 调用GetInputEvent获得输入事件,进而处理 */
	while (1)
	{
		iIndex = MainPageGetInputEvent(&g_tMainPageLayout, &tInputEvent);
		if (tInputEvent.iPressure == 0)
		{
			/* 如果是松开 */
			if (bPressed)
			{
				/* 曾经有按钮被按下 */
				ReleaseButton(&g_atMainPageIconsLayout[iIndexPressed]);
				bPressed = 0;

				if (iIndexPressed == iIndex) /* 按下和松开都是同一个按钮 */
				{
					switch (iIndexPressed)
					{
						case 0: /* 浏览按钮 */
						{
							Page("browse")->Run(&tPageParams);

							/* 从设置页面返回后显示当首的主页面 */
							ShowMainPage(&g_tMainPageLayout);

							break;
						}
						case 1: /* 连播按钮 */
						{
							Page("auto")->Run(&tPageParams);

							/* 从设置页面返回后显示当首的主页面 */
							ShowMainPage(&g_tMainPageLayout);

							break;
						}
						case 2: /* 设置按钮 */
						{
							Page("setting")->Run(&tPageParams);

							/* 从设置页面返回后显示当首的主页面 */
							ShowMainPage(&g_tMainPageLayout);

							break;
						}
						default:
						{
							break;
						}
					}
				}
				
				iIndexPressed = -1;
			}
		}
		else
		{
			/* 按下状态 */
			if (iIndex != -1)
			{
				if (!bPressed)
				{
					/* 未曾按下按钮 */
					bPressed = 1;
					iIndexPressed = iIndex;
					PressButton(&g_atMainPageIconsLayout[iIndexPressed]);
				}
			}
		}		
	}
}

2、浏览页面

浏览页面里把显示区域分为两部分:“菜单”、“目录和文件”

  • "菜单"就是"返回、选择、上一页、下一页"四个可操作的图标
  • "目录和文件"是浏览的内容
    设计大致如下:

在这里插入图片描述
因为有两个显示部分,所以需要分别计算菜单显示区域和目录及文件的显示区域。在目录及文件区域,我们需要确定一行显示几个目录或文件,它们之间的间隔要适当(大于10个像素)。
开发板运行画面:

当用户点击向上按钮:先判断是否是顶层目录“\”,如果是顶层目录则直接返回;如果不是,则释放当前目录内容,获取上一层目录内容并显示。
选择按钮:(如果不是用于"选择目录", 该按钮无用处)当点击选择按钮,看按钮之前是否被选中(标记),如果被选中则释放图标,如果不是则选中。
上一页:如果上一页还有数据,就显示
下一页:如果下一页有数据,就显示
当点击目录和文件区域:如果是目录就释放当前页面内容,进入该目录并显示其内容。如果是图片就调用图片显示页面,显示图片。

图片显示页面

当我们选中了图片文件时,就会进入图片显示页面。在此页面中可以对图片进行放大、缩小、移动等操作。
具体的页面设计如下

在这里插入图片描述
当点击菜单区域图标:
返回按钮:释放图片内容,获取当前目录内容并显示
放大:调用图片操作模块,实现图片的放大功能(通过缩放因子控制放大缩小程度)
缩小:调用图片操作模块,实现图片的缩小功能
上一张:如果有则释放当前图片内容,获得上一张图片内容并显示
下一张:如果有则释放当前图片内容,获得下一张图片内容并显示
连播:调用连播模块,连续播放当前目录中的图片

如果点击的是图片显示区域,则滑动图片:
滑动图片中,是一直触摸的,我们可以记录触点的移动距离(第一次触点和当前触点)来确定图片移动的位置。
run函数:

#define ZOOM_RATIO 0.9
#define SLIP_MIN_DISTANCE (2*2)
...
static void ManualPageRun(PT_PageParams ptParentPageParams)
{
	T_InputEvent tInputEvent;
	T_InputEvent tPreInputEvent;
	int bButtonPressed = 0;
	int bPicSlipping = 0;
	int iIndexPressed = -1;
    int iIndex;
    T_PageParams tPageParams;
    int iError;
    char strDirName[256];
    char strFileName[256];
    char strFullPathName[256];
    PT_DirContent *aptDirContents;
    int iDirContentsNumber;
    int iPicFileIndex;
    char *pcTmp;
    PT_VideoMem ptDevVideoMem;
    int iZoomedWidth;
    int iZoomedHeight;
    PT_PixelDatas ptZoomedPicPixelDatas = &g_tZoomedPicPixelDatas;

    /* 这两句只是避免编译警告 */
    tPreInputEvent.iX = 0;
    tPreInputEvent.iY = 0;

    tPageParams.iPageID = ID("manual");
    
    ptDevVideoMem = GetDevVideoMem();
    strcpy(strFullPathName, ptParentPageParams->strCurPictureFile);

    /* 显示菜单和图片文件 */
    ShowManualPage(&g_tManualPageMenuIconsLayout, strFullPathName);

    /* 取出目录名 */
    strcpy(strDirName, ptParentPageParams->strCurPictureFile);
    pcTmp = strrchr(strDirName, '/');
    *pcTmp = '\0';

    /* 取出文件名 */
    strcpy(strFileName, pcTmp+1);

    /* 获得当前目录下所有目录和文件的名字 */
    iError = GetDirContents(strDirName, &aptDirContents, &iDirContentsNumber);

    /* 确定当前显示的是哪一个文件 */
    for (iPicFileIndex = 0; iPicFileIndex < iDirContentsNumber; iPicFileIndex++)
    {
        if (0 == strcmp(strFileName, aptDirContents[iPicFileIndex]->strName))
        {
            break;
        }
    }

    while (1)
    {
        /* 先确定是否触摸了菜单图标 */
        iIndex = ManualPageGetInputEvent(&g_tManualPageMenuIconsLayout, &tInputEvent);
		
		/* 如果是松开 */
        if (tInputEvent.iPressure == 0)
        {
			bPicSlipping = 0;
			
            if (bButtonPressed)
            {
                /* 曾经有按钮被按下 */
                ReleaseButton(&g_atManualMenuIconsLayout[iIndexPressed]);
                bButtonPressed = 0;

                if (iIndexPressed == iIndex) /* 按下和松开都是同一个按钮 */
                {
                    switch (iIndexPressed)
                    {
                        case 0: /* 返回按钮 */
                        {
                            return;
                            break;
                        }
                        case 1: /* 缩小按钮 */
                        {
                            /* 获得缩小后的数据 */
                            iZoomedWidth  = (float)g_tZoomedPicPixelDatas.iWidth * ZOOM_RATIO;
                            iZoomedHeight = (float)g_tZoomedPicPixelDatas.iHeight * ZOOM_RATIO;
                            ptZoomedPicPixelDatas = GetZoomedPicPixelDatas(&g_tOriginPicPixelDatas, iZoomedWidth, iZoomedHeight);

                            /* 重新计算中心点 */
                            g_iXofZoomedPicShowInCenter = (float)g_iXofZoomedPicShowInCenter * ZOOM_RATIO;
                            g_iYofZoomedPicShowInCenter = (float)g_iYofZoomedPicShowInCenter * ZOOM_RATIO;

                            /* 显示新数据 */
                            ShowZoomedPictureInLayout(ptZoomedPicPixelDatas, ptDevVideoMem);

                            break;
                        }
                        case 2: /* 放大按钮 */
                        {
                            /* 获得放大后的数据 */
                            iZoomedWidth  = (float)g_tZoomedPicPixelDatas.iWidth / ZOOM_RATIO;
                            iZoomedHeight = (float)g_tZoomedPicPixelDatas.iHeight / ZOOM_RATIO;
                            ptZoomedPicPixelDatas = GetZoomedPicPixelDatas(&g_tOriginPicPixelDatas, iZoomedWidth, iZoomedHeight);

                            /* 重新计算中心点 */
                            g_iXofZoomedPicShowInCenter = (float)g_iXofZoomedPicShowInCenter / ZOOM_RATIO;
                            g_iYofZoomedPicShowInCenter = (float)g_iYofZoomedPicShowInCenter / ZOOM_RATIO;

                            /* 显示新数据 */
                            ShowZoomedPictureInLayout(ptZoomedPicPixelDatas, ptDevVideoMem);

                            break;
                        }
                        case 3: /* "上一张"按钮 */
                        {
                            while (iPicFileIndex > 0)
                            {
                                iPicFileIndex--;
                                snprintf(strFullPathName, 256, "%s/%s", strDirName, aptDirContents[iPicFileIndex]->strName);
                                strFullPathName[255] = '\0';
                                
                                if (isPictureFileSupported(strFullPathName))
                                {
                                    ShowPictureInManualPage(ptDevVideoMem, strFullPathName);
                                    break;
                                }
                            }
                            
                            break;
                        }
                        case 4: /* "下一张"按钮 */
                        {
                            while (iPicFileIndex < iDirContentsNumber - 1)
                            {
                                iPicFileIndex++;
                                snprintf(strFullPathName, 256, "%s/%s", strDirName, aptDirContents[iPicFileIndex]->strName);
                                strFullPathName[255] = '\0';

                                if (isPictureFileSupported(strFullPathName))
                                {
                                    ShowPictureInManualPage(ptDevVideoMem, strFullPathName);
                                    break;
                                }
                            }
                            break;
                        }
                        case 5: /* "连播"按钮 */
                        {
                            /* Manual页面的触发有两个方法: 在主页面按"浏览模式"进入"浏览页面"->"选中某个文件", 在"连播页面"里点击正在显示的图片 
                             * 如果是后者, 直接return就可以了:因为return后是返回到"连播页面"的, 它会继续"连播"
                             */
                            if (ptParentPageParams->iPageID == ID("browse"))  /* 触发自"浏览页面" */
                            {
                                strcpy(tPageParams.strCurPictureFile, strFullPathName);
                                Page("auto")->Run(&tPageParams);
                                ShowManualPage(&g_tManualPageMenuIconsLayout, tPageParams.strCurPictureFile);
                            }
                            else /* 当前manual页面的父页面是auto页面, 直接返回即可 */
                            {
                                return;
                            }
                            break;
                        }
                        default:
                        {
                            break;
                        }
                    }
                }
                
                iIndexPressed = -1;
            }
        }
        else /* 按下状态 */
        {
            /* 点击的是菜单按钮 */
            if (iIndex != -1)
            {
                if (!bButtonPressed)
                {
                    /* 未曾按下按钮 */
                    bButtonPressed = 1;
                    iIndexPressed = iIndex;
                    PressButton(&g_atManualMenuIconsLayout[iIndexPressed]);
                }
            }
			else  /* 点击的是图片显示区域, 滑动图片 */
			{
				/* 如果没有按钮被按下 */
				if (!bButtonPressed && !bPicSlipping)
				{
					bPicSlipping = 1;
                    tPreInputEvent = tInputEvent;
				}

				if (bPicSlipping)
				{
                    /* 如果触点滑动距离大于规定值, 则挪动图片 */
                    if (DistanceBetweenTwoPoint(&tInputEvent, &tPreInputEvent) > SLIP_MIN_DISTANCE)
                    {                            
                        /* 重新计算中心点 */
                        g_iXofZoomedPicShowInCenter -= (tInputEvent.iX - tPreInputEvent.iX);
                        g_iYofZoomedPicShowInCenter -= (tInputEvent.iY - tPreInputEvent.iY);
                        
                        /* 显示新数据 */
                        ShowZoomedPictureInLayout(ptZoomedPicPixelDatas, ptDevVideoMem);
                        
                        /* 记录滑动点 */
                        tPreInputEvent = tInputEvent;                            
                    }
				}
			}
        }       
    }
}

开发板实际画面:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ChenNightZ/article/details/108259791