Loading

数码相框-编写框架

程序框架

程序界面:

image

程序结构:

  • main.c调用一个T_PageAction​数据类型的Run函数,展示界面。

  • T_PageAction​ 类型的结构体。T_PageAction​ 结构体用于定义页面的行为接口,包含以下成员:

    • .name: 字符串,表示页面名称(这里是 "main"),用于标识该页面。
    • .Run: 函数指针,指向执行页面运行逻辑的函数(这里是 MainPageRun​)。
    • .GetInputEvent: 函数指针,指向获取页面输入事件的函数(这里是 MainPageGetInputEvent​)。
    • .Prepare: 函数指针,指向执行页面预处理逻辑的函数(此处未提供具体的 MainPagePrepare​ 函数定义)

    image

  • 把freetype和libjepg封装到render.c。通过render.c得到要展示的数据。

    image

  • 位图调用disp_mannger.c在framebuffer或者vga上显示。image

  • 可以通过key或者触摸屏捕获按键输入。

编写程序框架

是基于image这个文件夹进行修改的。

删除draw​文件夹,创建page​文件夹,创建以下文件:

image

编写page_manager

写page_manager结构体:

image



#ifndef _PAGE_MANAGER_H
#define _PAGE_MANAGER_H

typedef struct PageAction {
	char *name;
	int (*Run)(void);
	int (*GetInputEvent)();
	int (*Prepare)();
	struct PageAction *ptNext;
}T_PageAction, *PT_PageAction;


#endif /* _PAGE_MANAGER_H */

定义了一个名为PageAction​的结构体,用于表示页面操作的类型。该结构体具有以下成员:

  • name​:一个指向字符数组的指针,用于存储页面操作的名称。
  • Run​:一个指向函数的指针,该函数在页面操作执行时被调用,没有参数和返回值。
  • GetInputEvent​:一个指向函数的指针,该函数在页面等待用户输入时被调用,没有参数和返回值。
  • Prepare​:一个指向函数的指针,该函数在页面操作准备时被调用,没有参数和返回值。
  • ptNext​:一个指向PageAction​结构体的指针,用于表示下一个页面操作。

该结构体可用于创建一个页面操作的链表,每个链表节点代表一个页面操作,可以通过调用相应成员函数来执行、获取输入事件和准备页面操作。

编写page_manger.c:

#include <config.h>
#include <page_manager.h>
#include <string.h>


// 链表头部,用于存储注册的所有页面动作
static PT_PageAction g_ptPageActionHead;

/**
 * 注册一个页面动作到链表中。
 * 
 * @param ptPageAction 指向待注册页面动作的指针。
 * @return 始终返回0。
 */
int RegisterPageAction(PT_PageAction ptPageAction)
{
    // 如果链表为空,将传入的页面动作设置为链表头
	if (!g_ptPageActionHead)
	{
		g_ptPageActionHead   = ptPageAction;
		ptPageAction->ptNext = NULL;
	}
	else
	{
        // 遍历链表,找到最后一个页面动作并添加新页面动作
		ptTmp = g_ptPageActionHead;
		while (ptTmp->ptNext)
		{
			ptTmp = ptTmp->ptNext;
		}
		ptTmp->ptNext	  = ptPageAction;
		ptPageAction->ptNext = NULL;
	}

	return 0;
}


/**
 * 打印所有已注册的页面动作名称。
 */
void ShowPages(void)
{
    // 遍历链表,打印每个页面动作的名称
	int i = 0;
	PT_PageAction ptTmp = g_ptPageActionHead;

	while (ptTmp)
	{
		printf("%02d %s\n", i++, ptTmp->name);
		ptTmp = ptTmp->ptNext;
	}
}

/**
 * 查找指定名称的页面动作。
 * 
 * @param pcName 指向要查找的页面动作名称的字符指针。
 * @return 如果找到与名称匹配的页面动作,则返回其指针;否则返回NULL。
 */
PT_PageAction Page(char *pcName)
{
    PT_PageAction ptTmp = g_ptPageActionHead; // 从页面动作链表头开始查找
  
    // 遍历链表,查找名称匹配的页面动作
    while (ptTmp)
    {
        if (strcmp(ptTmp->name, pcName) == 0) // 比较当前页面动作名称与目标名称
        {
            return ptTmp; // 名称匹配,返回当前页面动作
        }
        ptTmp = ptTmp->ptNext; // 继续查找下一个页面动作
    }

    return NULL; // 未找到匹配的页面动作
}

/**
 * 初始化页面管理功能。
 * 
 * @return 初始化错误码。
 */
int PagesInit(void)
{
	int iError;

	// 初始化过程中的错误处理

	return iError;
}

主要用于实现页面动作(PT_PageAction​)的管理和操作。具体功能如下:

  1. 页面动作注册:通过RegisterPageAction​函数,可以将新的页面动作实例(PT_PageAction​类型)添加到全局静态链表g_ptPageActionHead​中。链表用于存储所有已注册的页面动作。当链表为空时,直接将新页面动作作为链表头;否则,将新页面动作追加到链表尾部。
  2. 页面动作展示ShowPages​函数用于遍历并打印所有已注册页面动作的名称。它以序号和名称的形式输出每一个页面动作。
  3. 页面动作查找Page​函数接收一个字符串参数pcName​,表示要查找的页面动作名称。函数遍历链表,逐个比较每个页面动作的名称是否与给定名称匹配。若找到匹配项,返回该页面动作的指针;否则返回NULL​。
  4. 页面管理初始化PagesInit​函数负责初始化页面管理相关功能。仅保留了错误码变量声明,其预期功能是在执行必要的初始化操作后,返回一个表示初始化结果(成功或失败)的错误码。

综上所述主要提供了一个轻量级的页面动作管理模块,支持页面动作的注册、展示、按名称查找以及整个模块的初始化操作。这些功能可能服务于一个需要对页面动作进行集中管理和调度的应用程序。

编写main

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <config.h>
#include <draw.h>
#include <encoding_manager.h>
#include <fonts_manager.h>
#include <disp_manager.h>
#include <input_manager.h>
#include <string.h>


int main(int argc, char **argv)
{
	/* 一系列的初始化 */

	Page("main")->Run();
	return 0;
}

写程序框架的初始化,从main页面开始。接下来定义main:

编写main_page

/*
 * 主页面管理程序
 * 
 * 本程序实现了主页面的运行逻辑,包括处理用户输入事件,切换到其他页面等功能。
 * 
 * @Author: Bleaach008
 * @Date: 2024-04-07 14:15:32
 * @LastEditTime: 2024-04-07 15:05:10
 * @FilePath: \14.digial_photo_frame\page\main_page.c
 */

#include <config.h> // 系统配置头文件
#include <page_manager.h> // 页面管理器头文件

// 主页面动作结构体,定义了主页面的运行、输入事件获取、准备等函数指针
static T_PageAction g_tMainPageAction = {
	.name          = "main", // 页面名称
	.Run           = MainPageRun, // 运行页面的函数指针
	.GetInputEvent = MainPageGetInputEvent, // 获取输入事件的函数指针
	.Prepare       = MainPagePrepare; // 准备页面的函数指针
};

/*
 * 主页面运行函数
 * 该函数不断地获取输入事件,并根据事件进行相应的操作,如切换到浏览模式、连播模式或设置页面。
 */
static void MainPageRun(void)
{
    /* 显示主页面 */

    /* 创建Prepare线程,用于页面切换前的准备工作 */

    /* 不断获取输入事件并处理 */
    while (1)
    {
        InputEvent = MainPageGetInputEvent();
        switch (InputEvent)   // 根据获取的输入事件选择相应的操作
        {
            case "浏览模式":
            {
                /* 保存当前页面 */
                StorePage();
              
                /* 切换到浏览模式页面 */
                Page("explore")->Run();
              
                /* 恢复之前的页面 */
                RestorePage();
                break;
            }
            case "连播模式":
            {
                /* 保存当前页面 */
                StorePage();

                /* 切换到连播模式页面 */
                Page("auto")->Run();
                break;
            }
            case "设置":
            {
                /* 保存当前页面 */
                StorePage();
                /* 切换到设置页面 */
                Page("setting")->Run();
                /* 恢复之前的页面 */
                RestorePage();
                break;
            }      
        }
    }
}

/*
 * 主页面获取输入事件函数
 * 该函数负责从输入管理器获取触摸屏事件。
 * 
 * @返回值: 输入事件类型,具体类型依据实现而定。
 */
int MainPageGetInputEvent(...)
{
    /* 获得原始的触摸屏数据,会使得当前线程休眠,直到有触摸屏事件发生 */
    GetInputEvent();
  
    /* 处理数据,返回处理结果 */
}

/*
 * 主页面初始化函数
 * 该函数用于注册主页面的动作到页面管理器。
 * 
 * @返回值: 注册结果,成功返回0,失败返回非0。
 */
int MainPageInit(void)
{
    return RegisterPageAction(&g_tMainPageAction);
}

主要用来实现一个数字相框中主页面的管理功能。它包含了以下核心组件:

  1. 主页面动作结构体 (g_tMainPageAction​​):定义了与主页面相关的操作接口,如运行(Run​​)、获取输入事件(GetInputEvent​​)和准备(Prepare​​)。这些接口通过函数指针关联到具体的实现函数,便于在程序中以统一方式管理和调用主页面的各种功能。

  2. 主页面运行函数 (MainPageRun​​):负责主页面的主循环逻辑。首先显示主页面,然后创建一个用于页面准备的线程。接下来,函数进入一个无限循环,不断从MainPageGetInputEvent​​ 函数获取用户输入事件。对于接收到的不同事件(如“浏览模式”、“连播模式”或“设置”),函数执行相应的操作,如保存当前页面状态、切换到指定页面执行其Run​​方法,以及在操作完成后恢复先前的页面状态。

  3. 主页面获取输入事件函数 (MainPageGetInputEvent​):负责从输入管理器获取触摸屏事件。该函数调用input_mannger.c的函数,确定是否让电脑跟前线程休眠,直至有触摸屏事件发生,会将线程唤醒,然后处理接收到的数据,并返回相应的输入事件类型。

    image

    image

    image

  4. 主页面初始化函数 (MainPageInit​​):负责将主页面的动作结构体注册到全局的页面管理器中。这样,当系统需要启动或调度主页面时,可以通过页面管理器调用已注册的g_tMainPageAction​​ 中的函数,实现对主页面的控制。

编写explorer_page

只需要在main_page.c上修改页面运行函数的程序逻辑:

static void ExplorePageRun(void)
{
	/* 1. 显示页面 */

	/* 2. 创建Prepare线程 */

	/* 3. 调用GetInputEvent获得输入事件,进而处理 */
	while (1)
	{
		InputEvent = ExplorePageGetInputEvent();
		switch (InputEvent)
		{
			case "向上":
			{
				/* 判断是否已经是顶层 */
				if (isTopLevel)
					return 0;
				else
				{
					/* 显示上一个目录的页面 */
				}
				break;
			}
			case "选择":
			{
				if (isSelectDir)
				{
					/* 显示下一级目录 */
				}
				else
				{
					/* 保存当前页面 */
					StorePage();
					Page("browse")->Run();
					/* 恢复之前的页面 */
					RestorePage();
				}
				break;
			}
			case "下页":
			{
				/* 显示下一页 */
				break;
			}	

			case "上页":
			{
				/* 显示上一页 */
				break;
			}	
		}
	}
}

通过调用ExplorePageGetInputEvent()​函数来获取输入事件,并根据不同的输入事件进行相应的处理:* 当输入事件为"向上"时,函数会判断当前是否已经是顶层目录,如果是,则退出函数并返回0;否则,显示上一个目录的页面。

  • 当输入事件为"选择"时,函数会判断当前是否选择了目录,如果是,则显示下一级目录;否则,保存当前页面,调用Page("browse")->Run()​来运行并显示下一页,并在完成后恢复之前的页面。
  • 当输入事件为"下页"时,函数会显示下一页。
  • 当输入事件为"上页"时,函数会显示上一页。

编写browse_page

static void BrowsePageRun(void)
{
	/* 1. 显示页面 */

	/* 2. 创建Prepare线程 */

	/* 3. 调用GetInputEvent获得输入事件,进而处理 */
	while (1)
	{
		InputEvent = BrowsePageGetInputEvent();
		switch (InputEvent)
		{
			case "返回":
			{
				return 0;
			}
			case "缩小":
			{
				/* 显示缩小的页面 */
				break;
			}
			case "放大":
			{
				/* 显示放大的页面 */
				break;
			}	

			case "上幅":
			{
				/* 显示上一幅图片 */
				break;
			}	
			case "下幅":
			{
				/* 显示下一幅图片 */
				break;
			}	
		
			case "连播":
			{
				Page("auto")->Run();
				break;
			}	

			case "按住不放":
			{
				/* 显示挪动的图片 */
				break;
			}
		}
	}
}

调用BrowsePageGetInputEvent()​函数来获取输入事件,并根据不同的输入事件执行相应的操作:* 当输入事件为"返回"时,函数返回0。

  • 当输入事件为"缩小"时,显示缩小的页面。
  • 当输入事件为"放大"时,显示放大的页面。
  • 当输入事件为"上幅"时,显示上一幅图片。
  • 当输入事件为"下幅"时,显示下一幅图片。
  • 当输入事件为"连播"时,调用Page("auto")->Run()​来执行自动播放操作。
  • 当输入事件为"按住不放"时,显示挪动的图片。

编写render

创建render文件夹,并在里面创建一个render.c。

render.c会用到font/freetype.c,还会用到libjpeg,所以我们需要创建一个libjpeg文件夹,并在里面创建一个libjpeg.c。

编写render.c:



int GetFontPixel()
{
}

int GetPicPixel()
{
}


int DrawPixel()
{
}

  • GetFontPixel()​:该函数用于获取字体的一个像素点的颜色值。
  • GetPicPixel()​:该函数用于获取图像的一个像素点的颜色值。
  • DrawPixel()​:该函数用于在屏幕上绘制一个像素点。会调用disp_manager.c来实现硬件的输出。

posted @ 2024-04-07 20:02  阿四与你  阅读(2)  评论(0编辑  收藏  举报