Listctrl 样式和LV_ITEM和LV_COLUMN

本文介绍列表框控件的样式属性、常用消息及其处理方法。列表框允许用户从多个选项中进行选择,支持单选或多选,并可通过不同消息实现增删项目、查询选择状态等功能。

列表框主要用于输入,它允许用户从所列出的表项中进行单项或多项选择,被选择的项呈高亮度显示.列表框具有边框,并且一般带有一个垂直滚动条.列表框分单选列表框和多重选择列表框两种.单选列表框一次只能选择一个列表项,而多重选择列表框可以进行多重选择.对于列表项的选择,
  应用程序用CreateWindowEx创建列表框控件时,可根据控件的用途在下表中选择部份常数来设定其风格属性(style)。

 

常数说明
LBS_DISABLENOSCROLL固定显示垂直滚动条。未指定本项时,当列表未超出窗口,垂直滚动条自动隐藏。
LBS_EXTENDEDSEL使用键盘“SHIFT”键或另指定键加鼠标进行多选。
LBS_HASSTRINGS含有字符串的自绘式列表框.应用程序在自绘式列表框进行自绘时可以用LB_GETTEXT消息来取得列表项的文本。
LBS_MULTICOLUMN多列列表框,带有水平滚动条。应用程序可以用 LB_SETCOLUMNWIDTH 消息来为列表框指定列数。
LBS_MULTIPLESEL支持多重选择。列表项的选择状态随着用户对该项单击或双击鼠标而翻转。
LBS_NODATA本项已不被支持。
LBS_NOINTEGRALHEIGHT列表框的尺寸由应用程序而不是Windows指定.通常,Windows指定尺寸会使列表项的某些部分隐藏起来。
LBS_NOREDRAW禁止刷新。当选择发生变化时防止列表框被更新,可发送WM_SETREDRAW来改变该风格。
LBS_NOSEL禁止选择,列表项只能看,不能被选择。
LBS_NOTIFY当用户单击或双击鼠标时通知父窗口。
LBS_OWNERDRAWFIXED指定自绘式列表框,即由父窗口负责绘制列表框的内容,并且列表项有相同的高度。在控件被创建时父窗口将收到WM_MEASUREITEM 消息,当需要重绘时父窗口将收到 WM_DRAWITEM 消息。
LBS_OWNERDRAWVARIABLE指定自绘式列表框,并且列表项有不同的高度.在控件被创建时父窗口将收到WM_MEASUREITEM消息,当需要重绘时父窗口将收到 WM_DRAWITEM 消息。
LBS_SORT使插入列表框中的项按字母升序排列.
LBS_STANDARD使用默认风格,相当于指定了边框,垂直滚动条,字母升序排列和鼠标单双击通知消息这几项风格
LBS_USETABSTOPS使列表框在显示列表项时识别并扩展制表符(08h),缺省的制表宽度是32个对话框单位。
LBS_WANTKEYBOARDINPUT响应键盘输入。当控件拥有键盘输入焦点时,允许接收父窗口接收WM_VKEYTOITEM和WM_CHARTOITEM消息,输入字符。


  应用程序可以通过调用SendMessage向控件发送如下消息来设定和查询控件各种参数。

uMsgwParamlParam说明
LB_ADDFILE0文件名地址增加文件名。
LB_ADDSTRING0字符串地址追加一个列表项。如果指定了LBS_SORT风格,表项将被重排序,否则将被追加在列表框的最后一项。
LB_DELETESTRING列表项序号0删除指定的列表项,
LB_DIRDDL_ARCHIVE指向通配符地址在列表框中列出文件名,必须是当前路径内,符合指定通配符,存档属性的文件名。
DDL_DIRECTORY在列表框中列出当前路径的子文件夹。子文件夹名前后将加上一对方括号"[*]"
DDL_DRIVES在列表框中列出本机的所有驱动器名。驱动器名前后将加上一对方括号和减号"[-*-]"
DDL_EXCLUSIVE只列出指定属性的文件名,默认情况下是所有可读写文件都列出。如果没有指定任何文件属性,则不列出文件名。
DDL_HIDDEN列出隐藏属性的文件名。
DDL_READONLY列出只读属性的文件名。
DDL_READWRITE列出读写属性的文件名。
DDL_SYSTEM列出系统属性的文件名。
LB_FINDSTRING开始表项序号字符串地址查找匹配字符串,忽略大小写,从指定开始表项序号开始查找,当查到某表项的文本字符串的前面包括指定的字符串则结束,找不到则转到列表框第一项继续查找,直到查完所有表项,如果wParam为-1则从列表框第一项开始查找,如果找到则返回表项序号,否则返回LB_ERR。如:表项字符串为"abc123"和指定字串"ABC"就算匹配。
LB_FINDSTRINGEXACT开始表项序号字符串地址查找字符串,忽略大小写,与LB_FINDSTRING不同,本操作必须整个字符串相同。如果找到则返回表项序号,否则返回LB_ERR。
LB_GETANCHORINDEX00返回鼠标最后选中的项的索引
LB_GETCARETINDEX00返回具有矩形焦点的项的索引
LB_GETCOUNT00返回列表项的总项数,若出错则返回LB_ERR.
LB_GETCURSEL00本操作仅适用于单选择列表框,用来返回当前被选择项的索引,如果没有列表项被选择或有错误发生,则返回LB_ERR.
LB_GETHORIZONTALEXTENT00返回列表框的可滚动的宽度(象素)
LB_GETITEMDATA索引0每个列表项都有一个32位的附加数据.该函数返回指定列表项的附加数据。若出错则函数返回LB_ERR.
LB_GETITEMHEIGHT索引0返回列表框中某一项的高度(单位:象素)
LB_GETITEMRECT索引RECT结构地址获得列表项的客户区的RECT
LB_GETLOCALE00取列表项当前用于排序的语言代码,当用户使用LB_ADDSTRING向组合框中的列表框中添加记录并使用LBS_SORT风格进行重新排序时,必须使用该语言代码。返回值中高16位为国家代码。
LB_GETSEL索引0返回指定列表项的状态。如果查询的列表项被选择了,函数返回一个正值,否则返回0,若出错则返回LB_ERR。
LB_GETSELCOUNT00本操作仅用于多重选择列表框,它返回选择项的数目,若出错函数返回LB_ERR.
LB_GETSELITEMS数组的大小缓冲区本操作仅用于多重选择列表框,用来获得选中的项的数目及位置。参数lParam指向一个整型数数组缓冲区,用来存放选中的列表项的索引。wParam说明了数组缓冲区的大小。本操作返回放在缓冲区中的选择项的实际数目,若出错函数返回LB_ERR.
LB_GETTEXT索引缓冲区用于获取指定列表项的字符串。参数lParam指向一个接收字符串的缓冲区.wParam则指定了接收字符串的列表项索引。返回获得的字符串的长度,若出错,则返回LB_ERR。
LB_GETTEXTLEN索引0返回指定列表项的字符串的字节长度。wParam指定了列表项的索引.若出错则返回LB_ERR。
LB_GETTOPINDEX00返回列表框中第一个可见项的索引,若出错则返回LB_ERR.
LB_INITSTORAGE表项数内存字节数本操作只适用于Windows95版本,当你将要向列表框中加入很多表项或有很大的表项时,本操作将预先分配一块内存,以免在今后的操作中一次一次地分配内存,从而加快程序运行速度。
LB_INSERTSTRING索引字符串地址在列表框中的指定位置插入字符串。wParam指定了列表项的索引,如果为-1,则字符串将被添加到列表的末尾。lParam指向要插入的字符串。本操作返回实际的插入位置,若发生错误,会返回LB_ERR或LB_ERRSPACE。与LB_ADDSTRING不同,本操作不会导致LBS_SORT风格的列表框重新排序。建议不要在具有LBS_SORT风格的列表框中使用本操作,以免破坏列表项的次序。
LB_ITEMFROMPOINT0位置获得与指定点最近的项的索引,lParam指定在列表框客户区,低16位为X坐标,高16位为Y坐标。
LB_RESETCONTENT00清除所有列表项。
LB_SELECTSTRING开始表项序号字符串地址本操作仅适用于单选择列表框,设定与指定字符串相匹配的列表项为选中项。本操作会滚动列表框以使选择项可见。参数的意义及搜索的方法与LB_FINDSTRING类似。如果找到了匹配的项,返回该项的索引,如果没有匹配的项,返回LB_ERR并且当前的选中项不被改变。
LB_SELITEMRANGETRUE或FALSE范围本操作仅用于多重选择列表框,用来使指定范围内的列表项选中或落选.参数lParam指定了列表项索引的范围,低16位为开始项高16位为结束项。如果参数wParam为TRUE,那么就选择这些列表项,否则就使它们落选。若出错函数返回LB_ERR。
LB_SELITEMRANGEEX起点终点本操作仅用于多重选择列表框,若指定终点大于起点则设定该范围为选中,若指定起点大于终点则设定该范围为落选。
LB_SETANCHORINDEX索引0设置鼠标最后选中的表项成指定表项
LB_SETCARETINDEX索引TRUE或FALSE设置键盘输入焦点到指定表项,若lParam为TRUE则滚动到指定项部份可见,若lParam为FALSE则滚动到指定项全部可见。
LB_SETCOLUMNWIDTH宽度(点)0设置列的宽度。
LB_SETCOUNT项数0设置表项数目
LB_SETCURSEL索引0本操作仅适用于单选择列表框,设置指定的列表项为当前选择项。本操作会滚动列表框以使选择项可见。参数wParam指定了列表项的索引,若为-1,那么将清除列表框中的选择。若出错函数返回LB_ERR。
LB_SETHORIZONTALEXTENT宽度(点)0设置列表框的滚动宽度。
LB_SETITEMDATA索引数据值更新指定列表项的32位附加数据。
LB_SETITEMHEIGHT索引高度(点)指定列表项显示高度,带有LBS_OWNERDRAWVARIABLE(自绘列表项)风格的控件,只设置由wParam指定项的高度,其它风格将更新所有的列表项的高度。
LB_SETLOCALE语言代码0取列表项当前用于排序的语言代码,当用户使用LB_ADDSTRING向组合框中的列表框中添加记录并使用LBS_SORT风格进行重新排序时,必须使用该语言代码。返回值中高16位为国家代码。
LB_SETSELTRUE或FALSE索引本操作仅适用于多重选择列表框,它使指定的列表项选中或落选。参数lParam指定了列表项的索引,若为-1,则相当于指定了所有的项。参数wParam为TRUE时选中列表项,否则使之落选。若出错则返回LB_ERR。
LB_SETTABSTOPS站数索引顺序表设置列表框的光标(输入焦点)站数及索引顺序表。
LB_SETTOPINDEX索引0用来将指定的列表项设置为列表框的第一个可见项,该函数会将列表框滚动到合适的位置。wParam指定了列表项的索引.若操作成功,返回0值,否则返回LB_ERR。


  当用户在列表框上进行各种操作时,其父窗口将收到WM_COMMAND通知消息,同时wParam的低16位带控件的ID。lParam带控件句柄(hWnd),wParam的高16位带有如下表的消息代码。

消息代码说明
LBN_DBLCLK用户单击了列表项。
LBN_ERRSPACE列表框无法申请到足够的内存空间。
LBN_KILLFOCUS列表框失去输入焦点。
LBN_SELCANCEL取消选择列表项。
LBN_SELCHANGE列表框的选择项即将被改变。
LBN_SETFOCUS列表框得到键盘输入焦点。

 

       LVS_ALIGNLEFT 用来确定表项的大小图标以左对齐方式显示;

  LVS_ALIGNTOP 用来确定表项的大小图标以顶对齐方式显示;

  LVS_AUTOARRANGE 用来确定表项的大小图标以自动排列方式显示;

  LVS_EDITLABELS 设置表项文本可以编辑,父窗口必须设有LVN_ENDLABELEDIT风格;

  LVS_ICON 用来确定大图标的显示方式;

  LVS_LIST 用来确定列表方式显示;

  LVS_NOCOLUMNHEADER 用来确定在详细资料方式时不显示列表头;

  LVS_NOLABELWRAP 用来确定以单行方式显示图标的文本项;

  LVS_NOSCROLL 用来屏蔽滚动条;

  LVS_NOSORTHEADER 用来确定列表头不能用作按钮功能;

  LVS_OWNERDRAWFIXED 在详细列表方式时允许自绘窗口;

  LVS_REPORT 用来确定以详细资料即报告方式显示;

  LVS_SHAREIMAGELISTS用来确定共享图像列表方式;

  LVS_SHOWSELALWAYS 用来确定一直显示被选中表项方式;

  LVS_SINGLESEL 用来确定在某一时刻只能有一项被选中;

  LVS_SMALLICON 用来确定小图标显示方式;

  LVS_SORTASCENDING 用来确定表项排序时是基于表项文本的升序方式;

  LVS_SORTDESCENDING 用来确定表项排序时是基于表项文本的降序方式;

typedef struct _LV_ITEM {

UINT mask; //结构成员屏蔽位

int iItem; //表项索引号

int iSubItem; //子表项索引号

UINT state; //表项状态

UINT stateMask; //状态有效性屏蔽位

LPTSTR pszText; //表项名文本

int cchTextMax; //表项名最大长度

int iImage; // 表项图标的索引号

LPARAM lParam; // 与表项相关的32位数

} LV_ITEM;

typedef struct _LV_COLUMN {

UINT mask; //结构成员有效性屏蔽位

int fmt; //表列对齐方式

int cx; //表列的象素宽度

LPTSTR pszText; //表列的表头名

int cchTextMax; //表列名的文本长度

int iSubItem; //与表列关联的子表项索引号

} LV_COLUMN;


  其中fmt可以取如下值:

   LVCFMT_CENTER 表列居中对齐

   LVCFMT_LEFT 表列左对齐

实现gec6818开发板与阿里云ECS连接并利用LVGL 8.2构建即时通信系统#include "dir_look.h" #include "lvgl/lvgl.h" #include "lv_drivers/display/fbdev.h" #include "lv_drivers/indev/evdev.h" #include <unistd.h> #include <pthread.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <stdlib.h> #include <time.h> #include <sys/time.h> #include <fcntl.h> #include <signal.h> #include <stdbool.h> #define _POSIX_C_SOURCE 200809L // 屏幕分辨率 #ifndef DISP_HOR_RES #define DISP_HOR_RES 800 #endif #ifndef DISP_VER_RES #define DISP_VER_RES 480 #endif // 网络配置 #define SERVER_ADDR "8.138.170.224" #define SERVER_PORT 8888 // 命令定义 #define CMD_SOCKET_REGSITER 1001 #define CMD_SOCKET_LOGIN 1002 #define CMD_SOCKET_ADDFRIEND 1003 #define CMD_SOCKET_DELFRIEND 1004 #define CMD_SOCKET_CHATGPT 1005 #define CMD_SOCKET_FRIENDLIST 1006 #define CMD_SOCKET_EXIT 1007 #define CMD_SOCKET_UPDATE_FRIENDLIST 1008 #define CMD_SOCKET_REPLY_OK 2001 // 状态类型定义 typedef enum { ALIYUN_DISCONNECTED, ALIYUN_CONNECTED } aliyun_status_t; typedef enum { NETWORK_DISCONNECTED, NETWORK_CONNECTED } network_status_t; // 数据结构定义 typedef struct sockaddr_in SockAddr_t; typedef struct { int cmd; char account[256]; char passwd[256]; char replyErrorCode[256]; int replyState; SockAddr_t addr; union { char chatMsg[1024]; char friendList[4096]; } cmdData; } SockData_t; typedef struct NodeData { char account[256]; SockAddr_t addr; } NodeData_t; typedef struct Node { NodeData_t data; struct Node *next; } Node_t; typedef struct list { Node_t *head; Node_t *tail; int nodeNumber; } List_t; typedef struct { int exit_mask; // 其他UI控制相关字段 } Ui_Ctrl; // 客户端模式定义 enum { MODE_REGSITER = 1,//注册 MODE_SOCKET_LOGIN,//登录 MODE_ADDFRIEND,//添加好友 MODE_DELFRIEND,//删除好友 MODE_CHATGPT,//聊天 MODE_FRIENDLIST,//好友列表 MODE_EXIT,//退出 }; // 全局变量 int g_tcpSocketFd = -1; int g_udpSockFd = -1; List_t *friend_list = NULL; int server_socket = -1; aliyun_status_t aliyun_status = ALIYUN_DISCONNECTED; network_status_t network_status = NETWORK_DISCONNECTED; lv_obj_t *main_screen = NULL; static volatile bool lvgl_ready = false; static pthread_mutex_t lvgl_mutex = PTHREAD_MUTEX_INITIALIZER; static volatile bool thread_exit_flag = false; static pthread_t lvgl_thread_id; static pthread_t server_thread_id; static lv_obj_t *current_msg_container = NULL; static lv_color_t *disp_buf = NULL; char current_account[256] = {0}; lv_obj_t *hint_label = NULL; // 提示标签 // 消息数据结构 typedef struct { const char *name; const char *msg; const char *time; } msg_data_t; // 样式全局变量 static lv_style_t style_bar; static lv_style_t style_btn; static lv_style_t style_btn_pressed; static lv_style_t style_label_title; static lv_style_t style_label_normal; static lv_style_t style_chat_self; static lv_style_t style_chat_other; static lv_style_t style_list_item; // 函数声明 static void back_to_main_event_handler(lv_event_t *e); static void send_message_event_handler(lv_event_t *e); static void enter_chat_event_handler(lv_event_t *e); static void enter_contacts_event_handler(lv_event_t *e); static void enter_settings_event_handler(lv_event_t *e); static lv_obj_t *create_session_item(lv_obj_t *parent, const char *name, const char *msg, const char *time, bool unread, int unread_count); static void add_other_message_async(void *data); void add_other_message(const char *name, const char *msg, const char *time); char *my_strdup(const char *s); static void *network_recv_thread(void *arg); int init_network(void); int loginWidget_register(void); int loginWidget_login(void); void mainWidget_addFriend(void); void mainWidget_friendList(SockData_t *data); int chatWidget_chat(const char *recvObject, const char *msg); void chat_styles_init(void); void create_contacts_interface(void); // 自定义符号 #define CUSTOM_SYMBOL_USER "U" #define CUSTOM_SYMBOL_WIFI "W" #define CUSTOM_SYMBOL_OK "OK" #define CUSTOM_SYMBOL_CLOSE "X" // 链表操作函数 int initList() { friend_list = malloc(sizeof(List_t)); if(friend_list == NULL) { perror("malloc list error"); return -1; } friend_list->head = friend_list->tail = NULL; friend_list->nodeNumber = 0; return 0; } int insertNodeToList(NodeData_t inputData) { if(friend_list == NULL) return -1; Node_t *newNode = malloc(sizeof(Node_t)); if(newNode == NULL) { perror("malloc newNode error"); return -1; } newNode->data = inputData; newNode->next = NULL; if(friend_list->nodeNumber == 0) { friend_list->head = newNode; friend_list->tail = newNode; } else { friend_list->tail->next = newNode; friend_list->tail = newNode; } friend_list->nodeNumber++; return 0; } // 自定义strdup char *my_strdup(const char *s) { if (!s) return NULL; size_t len = strlen(s) + 1; char *dup = (char *)malloc(len); if (dup) memcpy(dup, s, len); return dup; } // 网络初始化 int init_network() { // 初始化TCP socket g_tcpSocketFd = socket(AF_INET, SOCK_STREAM, 0); if(g_tcpSocketFd == -1) { perror("tcp socket error"); return -1; } struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr(SERVER_ADDR); serverAddr.sin_port = htons(SERVER_PORT); if(connect(g_tcpSocketFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) { perror("connect error"); close(g_tcpSocketFd); return -1; } // 初始化UDP socket g_udpSockFd = socket(AF_INET, SOCK_DGRAM, 0); if(g_udpSockFd == -1) { perror("udp socket error"); close(g_tcpSocketFd); return -1; } // 设置UDP异步接收 signal(SIGIO, chatRecvHandle); fcntl(g_udpSockFd, F_SETOWN, getpid()); int state = fcntl(g_udpSockFd, F_GETFL); state |= O_ASYNC; fcntl(g_udpSockFd, F_SETFL, state); network_status = NETWORK_CONNECTED; return 0; } // UDP消息接收处理 void chatRecvHandle(int num) { SockData_t data; memset(&data, 0, sizeof(data)); struct sockaddr_in cliaddr; socklen_t len = sizeof(cliaddr); int ret = recvfrom(g_udpSockFd, &data, sizeof(data), 0, (struct sockaddr *)&cliaddr, &len); if(ret <= 0) { perror("recvfrom error"); return; } if(data.cmd == CMD_SOCKET_CHATGPT) { char time_str[32]; time_t now = time(NULL); strftime(time_str, sizeof(time_str), "%H:%M:%S", localtime(&now)); add_other_message(data.account, data.cmdData.chatMsg, time_str); } } // 注册处理 int loginWidget_register() { SockData_t data = {0}; data.cmd = CMD_SOCKET_REGSITER; strcpy(data.account, "user123"); // 从LVGL输入框获取账号 strcpy(data.passwd, "123456"); // 从LVGL输入框获取密码 // 发送到服务器 send(g_tcpSocketFd, &data, sizeof(SockData_t), 0); // 接收服务器应答 recv(g_tcpSocketFd, &data, sizeof(SockData_t), 0); if (data.replyState == CMD_SOCKET_REPLY_OK) { // 在LVGL界面显示“注册成功” if (hint_label) lv_label_set_text(hint_label, "注册成功"); return true; } else { if (hint_label) lv_label_set_text(hint_label, data.replyErrorCode); // 显示失败原因 return false; } } // 登录处理 int loginWidget_login() { SockData_t data = {0}; data.cmd = CMD_SOCKET_LOGIN; strcpy(data.account, "user123"); strcpy(data.passwd, "123456"); send(g_tcpSocketFd, &data, sizeof(SockData_t), 0); recv(g_tcpSocketFd, &data, sizeof(SockData_t), 0); if (data.replyState == CMD_SOCKET_REPLY_OK) { if (hint_label) lv_label_set_text(hint_label, "登录成功"); strcpy(current_account, data.account); // 切换到好友列表界面 create_contacts_interface(); // 请求获取在线用户 data.cmd = CMD_SOCKET_UPDATE_FRIENDLIST; send(g_tcpSocketFd, &data, sizeof(SockData_t), 0); // 接收服务器返回的在线用户列表 recv(g_tcpSocketFd, &data, sizeof(SockData_t), 0); mainWidget_friendList(&data); // 显示好友列表 return true; } else { if (hint_label) lv_label_set_text(hint_label, data.replyErrorCode); return false; } } // 添加好友 void mainWidget_addFriend() { SockData_t *data = (SockData_t *)malloc(sizeof(SockData_t)); if (data == NULL) { perror("malloc SockData_t error"); return; } memset(data, 0, sizeof(SockData_t)); // 修复内存初始化错误 // 实际应用中需要添加UI输入处理 strcpy(data->account, "friend1"); data->cmd = CMD_SOCKET_ADDFRIEND; int w_byte = write(g_tcpSocketFd, data, sizeof(SockData_t)); if(w_byte != sizeof(SockData_t)) { printf("发送数据包失败 添加好友失败...\n"); free(data); return; } read(g_tcpSocketFd, data, sizeof(SockData_t)); if(data->replyState == CMD_SOCKET_REPLY_OK) { NodeData_t inputData; memset(&inputData, 0, sizeof(inputData)); strcpy(inputData.account, data->account); inputData.addr = data->addr; insertNodeToList(inputData); printf("添加好友成功....\n"); } else { printf("添加好友失败:%s\n", data->replyErrorCode); } free(data); } // 显示好友列表 void mainWidget_friendList(SockData_t *data) { // 实际应用中需要解析data并更新UI显示好友列表 Node_t *p = friend_list->head; while(p) { printf("账号:%s IP:%s Port:%d\n", p->data.account, inet_ntoa(p->data.addr.sin_addr), ntohs(p->data.addr.sin_port)); p = p->next; } } // 发送聊天消息 int chatWidget_chat(const char *recvObject, const char *msg) { SockData_t data; memset(&data, 0, sizeof(data)); Node_t *p = friend_list->head; while(p) { if(!strcmp(recvObject, p->data.account)) break; p = p->next; } if(p == NULL) { printf("聊天对象并非你的好友,请先添加好友.....\n"); return -1; } data.cmd = CMD_SOCKET_CHATGPT; strcpy(data.cmdData.chatMsg, msg); strcpy(data.account, current_account); data.addr = p->data.addr; struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr(SERVER_ADDR); serverAddr.sin_port = htons(SERVER_PORT); int ret = sendto(g_udpSockFd, &data, sizeof(data), 0, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr_in)); if(ret <= 0) { printf("sendto chat msg error\n"); return -1; } return 0; } // LVGL刷新线程 static void *lvgl_refresh_thread(void *arg) { (void)arg; printf("LVGL刷新线程启动\n"); pthread_mutex_lock(&lvgl_mutex); lvgl_ready = true; pthread_mutex_unlock(&lvgl_mutex); while (!thread_exit_flag) { lv_timer_handler(); usleep(5000); } printf("LVGL刷新线程退出\n"); return NULL; } // 网络接收线程 static void *network_recv_thread(void *arg) { (void)arg; printf("网络接收线程启动\n"); while (!thread_exit_flag) { // 处理TCP接收数据 usleep(100000); } printf("网络接收线程退出\n"); return NULL; } // 检查LVGL是否准备就绪 static bool is_lvgl_ready(void) { bool ready; pthread_mutex_lock(&lvgl_mutex); ready = lvgl_ready; pthread_mutex_unlock(&lvgl_mutex); return ready; } // 显示设备初始化 static void display_init(void) { printf("初始化帧缓冲设备...\n"); fbdev_init(); uint32_t buf_size = DISP_HOR_RES * 50; disp_buf = (lv_color_t *)malloc(buf_size * sizeof(lv_color_t)); if (!disp_buf) { printf("错误:显示缓冲区内存分配失败\n"); return; } memset(disp_buf, 0, buf_size * sizeof(lv_color_t)); static lv_disp_draw_buf_t disp_draw_buf; lv_disp_draw_buf_init(&disp_draw_buf, disp_buf, NULL, buf_size); lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.flush_cb = fbdev_flush; disp_drv.draw_buf = &disp_draw_buf; disp_drv.hor_res = DISP_HOR_RES; disp_drv.ver_res = DISP_VER_RES; lv_disp_t *disp = lv_disp_drv_register(&disp_drv); if (disp == NULL) { printf("错误:显示驱动注册失败\n"); free(disp_buf); disp_buf = NULL; } else { printf("显示驱动注册成功\n"); } } // 输入设备初始化 static void input_init(void) { evdev_init(); lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = evdev_read; lv_indev_drv_register(&indev_drv); } // 样式初始化 void chat_styles_init(void) { // 状态栏样式 lv_style_init(&style_bar); lv_style_set_bg_color(&style_bar, lv_color_white()); lv_style_set_border_width(&style_bar, 1); lv_style_set_border_color(&style_bar, lv_palette_darken(LV_PALETTE_GREY, 2)); // 按钮基础样式 lv_style_init(&style_btn); lv_style_set_radius(&style_btn, 10); lv_style_set_bg_color(&style_btn, lv_palette_lighten(LV_PALETTE_GREY, 3)); lv_style_set_pad_top(&style_btn, 10); lv_style_set_pad_bottom(&style_btn, 10); // 按钮按下样式 lv_style_init(&style_btn_pressed); lv_style_set_bg_color(&style_btn_pressed, lv_palette_main(LV_PALETTE_GREY)); // 标题文字样式 lv_style_init(&style_label_title); lv_style_set_text_font(&style_label_title, &lv_font_montserrat_20); lv_style_set_text_color(&style_label_title, lv_color_black()); // 普通文字样式 lv_style_init(&style_label_normal); lv_style_set_text_font(&style_label_normal, &lv_font_montserrat_16); lv_style_set_text_color(&style_label_normal, lv_palette_darken(LV_PALETTE_GREY, 2)); // 自己的消息气泡样式 lv_style_init(&style_chat_self); lv_style_set_radius(&style_chat_self, 10); lv_style_set_bg_color(&style_chat_self, lv_palette_main(LV_PALETTE_BLUE)); lv_style_set_text_color(&style_chat_self, lv_color_white()); lv_style_set_pad_all(&style_chat_self, 10); // 他人的消息气泡样式 lv_style_init(&style_chat_other); lv_style_set_radius(&style_chat_other, 10); lv_style_set_bg_color(&style_chat_other, lv_palette_lighten(LV_PALETTE_GREY, 3)); lv_style_set_text_color(&style_chat_other, lv_color_black()); lv_style_set_pad_all(&style_chat_other, 10); // 列表项样式 lv_style_init(&style_list_item); lv_style_set_bg_color(&style_list_item, lv_color_white()); lv_style_set_border_width(&style_list_item, 0); lv_style_set_pad_all(&style_list_item, 5); } // 样式获取接口 lv_style_t *get_style_bar(void) { return &style_bar; } lv_style_t *get_style_btn(void) { return &style_btn; } lv_style_t *get_style_btn_pressed(void) { return &style_btn_pressed; } lv_style_t *get_style_label_title(void) { return &style_label_title; } lv_style_t *get_style_label_normal(void) { return &style_label_normal; } lv_style_t *get_style_chat_self(void) { return &style_chat_self; } lv_style_t *get_style_chat_other(void) { return &style_chat_other; } lv_style_t *get_style_list_item(void) { return &style_list_item; } // 创建会话列表项 static lv_obj_t *create_session_item(lv_obj_t *parent, const char *name, const char *msg, const char *time, bool unread, int unread_count) { lv_obj_t *item = lv_btn_create(parent); lv_obj_set_size(item, 780, 80); lv_obj_add_style(item, &style_list_item, 0); // 头像(文本替代) lv_obj_t *avatar = lv_label_create(item); lv_label_set_text(avatar, CUSTOM_SYMBOL_USER); lv_obj_set_style_text_font(avatar, &lv_font_montserrat_20, 0); lv_obj_align(avatar, LV_ALIGN_LEFT_MID, 10, 0); lv_obj_set_size(avatar, 60, 60); // 名称 lv_obj_t *name_label = lv_label_create(item); lv_label_set_text(name_label, name); lv_obj_add_style(name_label, &style_label_title, 0); lv_obj_align_to(name_label, avatar, LV_ALIGN_OUT_RIGHT_TOP, 10, 5); // 消息预览 lv_obj_t *msg_label = lv_label_create(item); lv_label_set_text(msg_label, msg); lv_obj_add_style(msg_label, &style_label_normal, 0); lv_obj_align_to(msg_label, name_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5); // 时间戳 lv_obj_t *time_label = lv_label_create(item); lv_label_set_text(time_label, time); lv_obj_add_style(time_label, &style_label_normal, 0); lv_obj_align(time_label, LV_ALIGN_TOP_RIGHT, -10, 5); // 未读消息提示(呼吸动画) if (unread && unread_count > 0) { lv_obj_t *unread_dot = lv_obj_create(item); lv_obj_set_size(unread_dot, 20, 20); lv_obj_set_style_radius(unread_dot, LV_RADIUS_CIRCLE, 0); lv_obj_set_style_bg_color(unread_dot, lv_palette_main(LV_PALETTE_RED), 0); lv_obj_align_to(unread_dot, time_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5); if (unread_count > 1) { lv_obj_t *count_label = lv_label_create(unread_dot); lv_label_set_text_fmt(count_label, "%d", unread_count); lv_obj_set_style_text_font(count_label, &lv_font_montserrat_12, 0); lv_obj_set_style_text_color(count_label, lv_color_white(), 0); lv_obj_center(count_label); } // 呼吸动画 lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, unread_dot); lv_anim_set_values(&a, LV_OPA_100, LV_OPA_50); lv_anim_set_time(&a, 1200); lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_style_bg_opa); lv_anim_start(&a); } lv_obj_add_event_cb(item, enter_chat_event_handler, LV_EVENT_CLICKED, NULL); return item; } // 更新状态图标 static void update_status_icons(lv_obj_t *status_bar) { // 状态图标更新逻辑 } // 消息处理函数 static void add_other_message_async(void *data) { msg_data_t *msg = (msg_data_t *)data; if(!msg || !current_msg_container) return; lv_obj_t *msg_cont = lv_obj_create(current_msg_container); lv_obj_set_size(msg_cont, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_add_style(msg_cont, &style_chat_other, 0); lv_obj_align(msg_cont, LV_ALIGN_TOP_LEFT, 10, 10); lv_obj_t *name_label = lv_label_create(msg_cont); lv_label_set_text(name_label, msg->name); lv_obj_add_style(name_label, &style_label_title, 0); lv_obj_align(name_label, LV_ALIGN_TOP_LEFT, 5, 5); lv_obj_t *msg_label = lv_label_create(msg_cont); lv_label_set_text(msg_label, msg->msg); lv_obj_add_style(msg_label, &style_label_normal, 0); lv_obj_align_to(msg_label, name_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5); lv_obj_t *time_label = lv_label_create(msg_cont); lv_label_set_text(time_label, msg->time); lv_obj_add_style(time_label, &style_label_normal, 0); lv_obj_align_to(time_label, msg_label, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, 5); free((void *)msg->name); free((void *)msg->msg); free((void *)msg->time); free(msg); } void add_other_message(const char *name, const char *msg, const char *time) { if(!is_lvgl_ready()) return; msg_data_t *data = malloc(sizeof(msg_data_t)); data->name = my_strdup(name); data->msg = my_strdup(msg); data->time = my_strdup(time); lv_async_call(add_other_message_async, data); } // 界面创建函数 void create_main_interface(void) { printf("创建主界面...\n"); main_screen = lv_obj_create(NULL); lv_obj_set_size(main_screen, DISP_HOR_RES, DISP_VER_RES); // 顶部状态栏 lv_obj_t *status_bar = lv_obj_create(main_screen); lv_obj_set_size(status_bar, DISP_HOR_RES, 60); lv_obj_add_style(status_bar, &style_bar, 0); lv_obj_align(status_bar, LV_ALIGN_TOP_LEFT, 0, 0); update_status_icons(status_bar); // 中间会话列表 lv_obj_t *session_list = lv_list_create(main_screen); lv_obj_set_size(session_list, DISP_HOR_RES, 340); lv_obj_align(session_list, LV_ALIGN_TOP_LEFT, 0, 60); lv_obj_set_style_pad_all(session_list, 0, 0); lv_obj_set_flex_flow(session_list, LV_FLEX_FLOW_COLUMN); create_session_item(session_list, "开发小组", "小李: 今天的会议取消了", "09:45", true, 3); create_session_item(session_list, "张三", "明天一起讨论项目细节", "昨天", false, 0); create_session_item(session_list, "技术支持", "您的问题已经解决", "周一", false, 0); // 底部功能栏 lv_obj_t *bottom_bar = lv_obj_create(main_screen); lv_obj_set_size(bottom_bar, DISP_HOR_RES, 80); lv_obj_add_style(bottom_bar, &style_bar, 0); lv_obj_align(bottom_bar, LV_ALIGN_BOTTOM_LEFT, 0, 0); // 消息按钮 lv_obj_t *msg_btn = lv_btn_create(bottom_bar); lv_obj_set_size(msg_btn, 250, 60); lv_obj_add_style(msg_btn, &style_btn, 0); lv_obj_add_style(msg_btn, &style_btn_pressed, LV_STATE_PRESSED); lv_obj_align(msg_btn, LV_ALIGN_LEFT_MID, 10, 0); lv_obj_add_event_cb(msg_btn, enter_chat_event_handler, LV_EVENT_CLICKED, NULL); lv_obj_t *msg_label = lv_label_create(msg_btn); lv_label_set_text(msg_label, "消息"); lv_obj_center(msg_label); // 联系人按钮 lv_obj_t *contact_btn = lv_btn_create(bottom_bar); lv_obj_set_size(contact_btn, 250, 60); lv_obj_add_style(contact_btn, &style_btn, 0); lv_obj_add_style(contact_btn, &style_btn_pressed, LV_STATE_PRESSED); lv_obj_align_to(contact_btn, msg_btn, LV_ALIGN_OUT_RIGHT_MID, 10, 0); lv_obj_add_event_cb(contact_btn, enter_contacts_event_handler, LV_EVENT_CLICKED, NULL); lv_obj_t *contact_label = lv_label_create(contact_btn); lv_label_set_text(contact_label, "联系人"); lv_obj_center(contact_label); // 设置按钮 lv_obj_t *setting_btn = lv_btn_create(bottom_bar); lv_obj_set_size(setting_btn, 250, 60); lv_obj_add_style(setting_btn, &style_btn, 0); lv_obj_add_style(setting_btn, &style_btn_pressed, LV_STATE_PRESSED); lv_obj_align_to(setting_btn, contact_btn, LV_ALIGN_OUT_RIGHT_MID, 10, 0); lv_obj_add_event_cb(setting_btn, enter_settings_event_handler, LV_EVENT_CLICKED, NULL); lv_obj_t *setting_label = lv_label_create(setting_btn); lv_label_set_text(setting_label, "设置"); lv_obj_center(setting_label); lv_scr_load(main_screen); printf("主界面创建完成\n"); } // 聊天界面创建逻辑 void create_chat_interface(void) { lv_obj_t *chat_screen = lv_obj_create(NULL); lv_obj_set_size(chat_screen, DISP_HOR_RES, DISP_VER_RES); // 顶部导航栏 lv_obj_t *nav_bar = lv_obj_create(chat_screen); lv_obj_set_size(nav_bar, DISP_HOR_RES, 60); lv_obj_add_style(nav_bar, &style_bar, 0); lv_obj_align(nav_bar, LV_ALIGN_TOP_LEFT, 0, 0); // 返回按钮 lv_obj_t *back_btn = lv_btn_create(nav_bar); lv_obj_set_size(back_btn, 80, 40); lv_obj_add_style(back_btn, &style_btn, 0); lv_obj_align(back_btn, LV_ALIGN_LEFT_MID, 10, 0); lv_obj_add_event_cb(back_btn, back_to_main_event_handler, LV_EVENT_CLICKED, NULL); lv_obj_t *back_label = lv_label_create(back_btn); lv_label_set_text(back_label, "返回"); lv_obj_center(back_label); // 群组名称状态 lv_obj_t *group_label = lv_label_create(nav_bar); lv_label_set_text(group_label, "开发小组"); lv_obj_add_style(group_label, &style_label_title, 0); lv_obj_align(group_label, LV_ALIGN_LEFT_MID, 100, -8); lv_obj_t *status_label = lv_label_create(nav_bar); lv_label_set_text(status_label, "5人在线"); lv_obj_add_style(status_label, &style_label_normal, 0); lv_obj_align_to(status_label, group_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5); // 更多按钮 lv_obj_t *more_btn = lv_btn_create(nav_bar); lv_obj_set_size(more_btn, 40, 40); lv_obj_add_style(more_btn, &style_btn, 0); lv_obj_align(more_btn, LV_ALIGN_RIGHT_MID, -20, 0); lv_obj_t *more_label = lv_label_create(more_btn); lv_label_set_text(more_label, "⋮"); lv_obj_center(more_label); // 中间消息区 lv_obj_t *msg_container = lv_obj_create(chat_screen); lv_obj_set_size(msg_container, DISP_HOR_RES, 320); lv_obj_set_style_bg_color(msg_container, lv_color_white(), 0); lv_obj_set_style_pad_all(msg_container, 5, 0); lv_obj_align(msg_container, LV_ALIGN_TOP_LEFT, 0, 60); lv_obj_set_scrollbar_mode(msg_container, LV_SCROLLBAR_MODE_AUTO); current_msg_container = msg_container; add_other_message("张三", "大家好,今天我们讨论一下项目进度", "09:30"); add_other_message("李四", "我负责的模块已经完成了80%", "09:35"); // 底部输入区 lv_obj_t *input_area = lv_obj_create(chat_screen); lv_obj_set_size(input_area, DISP_HOR_RES, 100); lv_obj_add_style(input_area, &style_bar, 0); lv_obj_align(input_area, LV_ALIGN_BOTTOM_LEFT, 0, 0); // 表情按钮 lv_obj_t *emoji_btn = lv_btn_create(input_area); lv_obj_set_size(emoji_btn, 40, 40); lv_obj_align(emoji_btn, LV_ALIGN_LEFT_MID, 10, 0); lv_obj_t *emoji_label = lv_label_create(emoji_btn); lv_label_set_text(emoji_label, "😀"); lv_obj_center(emoji_label); // 图片按钮 lv_obj_t *img_btn = lv_btn_create(input_area); lv_obj_set_size(img_btn, 40, 40); lv_obj_align_to(img_btn, emoji_btn, LV_ALIGN_OUT_RIGHT_MID, 10, 0); lv_obj_t *img_label = lv_label_create(img_btn); lv_label_set_text(img_label, "📷"); lv_obj_center(img_label); // 文本输入框 lv_obj_t *textarea = lv_textarea_create(input_area); lv_obj_set_style_radius(textarea, 5, 0); lv_obj_set_width(textarea, 500); lv_obj_align_to(textarea, img_btn, LV_ALIGN_OUT_RIGHT_MID, 10, 0); lv_textarea_set_placeholder_text(textarea, "输入消息..."); // 发送按钮 lv_obj_t *send_btn = lv_btn_create(input_area); lv_obj_set_size(send_btn, 80, 60); lv_obj_add_style(send_btn, &style_btn, 0); lv_obj_set_style_bg_color(send_btn, lv_palette_main(LV_PALETTE_GREEN), 0); lv_obj_align_to(send_btn, textarea, LV_ALIGN_OUT_RIGHT_MID, 10, 0); lv_obj_add_event_cb(send_btn, send_message_event_handler, LV_EVENT_CLICKED, NULL); lv_obj_t *send_label = lv_label_create(send_btn); lv_label_set_text(send_label, "发送"); lv_obj_set_style_text_color(send_label, lv_color_white(), 0); lv_obj_center(send_label); lv_scr_load(chat_screen); } // 联系人界面创建逻辑 void create_contacts_interface(void) { lv_obj_t *contacts_screen = lv_obj_create(NULL); lv_obj_set_size(contacts_screen, DISP_HOR_RES, DISP_VER_RES); // 顶部导航栏 lv_obj_t *nav_bar = lv_obj_create(contacts_screen); lv_obj_set_size(nav_bar, DISP_HOR_RES, 60); lv_obj_add_style(nav_bar, &style_bar, 0); lv_obj_align(nav_bar, LV_ALIGN_TOP_LEFT, 0, 0); // 返回按钮 lv_obj_t *back_btn = lv_btn_create(nav_bar); lv_obj_set_size(back_btn, 80, 40); lv_obj_add_style(back_btn, &style_btn, 0); lv_obj_align(back_btn, LV_ALIGN_LEFT_MID, 10, 0); lv_obj_add_event_cb(back_btn, back_to_main_event_handler, LV_EVENT_CLICKED, NULL); lv_obj_t *back_label = lv_label_create(back_btn); lv_label_set_text(back_label, "返回"); lv_obj_center(back_label); // 标题 lv_obj_t *title_label = lv_label_create(nav_bar); lv_label_set_text(title_label, "联系人"); lv_obj_add_style(title_label, &style_label_title, 0); lv_obj_align(title_label, LV_ALIGN_CENTER, 0, 0); // 占位文本 lv_obj_t *placeholder = lv_label_create(contacts_screen); lv_label_set_text(placeholder, "联系人界面 - 待实现"); lv_obj_center(placeholder); lv_scr_load(contacts_screen); } // 设置界面创建逻辑 void create_settings_interface(void) { lv_obj_t *settings_screen = lv_obj_create(NULL); lv_obj_set_size(settings_screen, DISP_HOR_RES, DISP_VER_RES); // 顶部导航栏 lv_obj_t *nav_bar = lv_obj_create(settings_screen); lv_obj_set_size(nav_bar, DISP_HOR_RES, 60); lv_obj_add_style(nav_bar, &style_bar, 0); lv_obj_align(nav_bar, LV_ALIGN_TOP_LEFT, 0, 0); // 返回按钮 lv_obj_t *back_btn = lv_btn_create(nav_bar); lv_obj_set_size(back_btn, 80, 40); lv_obj_add_style(back_btn, &style_btn, 0); lv_obj_align(back_btn, LV_ALIGN_LEFT_MID, 10, 0); lv_obj_add_event_cb(back_btn, back_to_main_event_handler, LV_EVENT_CLICKED, NULL); lv_obj_t *back_label = lv_label_create(back_btn); lv_label_set_text(back_label, "返回"); lv_obj_center(back_label); // 标题 lv_obj_t *title_label = lv_label_create(nav_bar); lv_label_set_text(title_label, "聊天设置"); lv_obj_add_style(title_label, &style_label_title, 0); lv_obj_align(title_label, LV_ALIGN_CENTER, 0, 0); // 占位文本 lv_obj_t *placeholder = lv_label_create(settings_screen); lv_label_set_text(placeholder, "设置界面 - 待实现"); lv_obj_center(placeholder); lv_scr_load(settings_screen); } // 事件处理函数 // 返回主界面逻辑 static void back_to_main_event_handler(lv_event_t *e) { if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; lv_obj_t *obj = lv_event_get_target(e); if (!obj) return; lv_obj_t *parent1 = lv_obj_get_parent(obj); if (!parent1) return; lv_obj_t *chat_screen = lv_obj_get_parent(parent1); if (!chat_screen) return; lv_obj_del(chat_screen); current_msg_container = NULL; if (main_screen) { lv_obj_clear_flag(main_screen, LV_OBJ_FLAG_HIDDEN); lv_scr_load(main_screen); } } // 发送消息事件 static void send_message_event_handler(lv_event_t *e) { if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; lv_obj_t *obj = lv_event_get_target(e); if (!obj) return; lv_obj_t *input_area = lv_obj_get_parent(obj); if (!input_area) return; lv_obj_t *textarea = lv_obj_get_child(input_area, 2); if (!textarea) return; const char *text = lv_textarea_get_text(textarea); if (!text || strlen(text) == 0) return; if (!current_msg_container) return; lv_obj_t *msg_container = current_msg_container; // 自己的消息气泡 lv_obj_t *msg_row = lv_obj_create(msg_container); lv_obj_set_size(msg_row, 780, LV_SIZE_CONTENT); lv_obj_set_style_bg_opa(msg_row, LV_OPA_0, 0); lv_obj_align(msg_row, LV_ALIGN_BOTTOM_RIGHT, 0, 0); lv_obj_t *bubble = lv_obj_create(msg_row); lv_obj_add_style(bubble, &style_chat_self, 0); lv_obj_set_width(bubble, LV_SIZE_CONTENT); lv_obj_set_style_max_width(bubble, 500, 0); lv_obj_align(bubble, LV_ALIGN_RIGHT_MID, -10, 0); // 消息内容 lv_obj_t *msg_label = lv_label_create(bubble); lv_label_set_text(msg_label, text); lv_obj_center(msg_label); // 时间状态 time_t now; time(&now); struct tm *tm_info = localtime(&now); char time_str[64]; strftime(time_str, sizeof(time_str), "%H:%M", tm_info); lv_obj_t *status_label = lv_label_create(bubble); char status_text[64]; snprintf(status_text, sizeof(status_text), "%s ✓", time_str); lv_label_set_text(status_label, status_text); lv_obj_set_style_text_font(status_label, &lv_font_montserrat_12, 0); lv_obj_align(status_label, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, 5); // 清空输入框 lv_textarea_set_text(textarea, ""); // 滚动到底部 lv_obj_scroll_to_y(msg_container, lv_obj_get_scroll_y(msg_container) + lv_obj_get_height(bubble) + 20, LV_ANIM_ON); // 发送动画 lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, bubble); lv_anim_set_values(&a, LV_OPA_0, LV_OPA_100); lv_anim_set_time(&a, 200); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_style_opa); lv_anim_start(&a); // 发送到服务器 chatWidget_chat("开发小组", text); } // 进入聊天界面逻辑 static void enter_chat_event_handler(lv_event_t *e) { if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; if (main_screen) { lv_obj_add_flag(main_screen, LV_OBJ_FLAG_HIDDEN); create_chat_interface(); } } // 联系人按钮事件 static void enter_contacts_event_handler(lv_event_t *e) { if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; if (main_screen) { lv_obj_add_flag(main_screen, LV_OBJ_FLAG_HIDDEN); create_contacts_interface(); } } // 设置按钮事件 static void enter_settings_event_handler(lv_event_t *e) { if (lv_event_get_code(e) != LV_EVENT_CLICKED) return; if (main_screen) { lv_obj_add_flag(main_screen, LV_OBJ_FLAG_HIDDEN); create_settings_interface(); } } // 系统初始化 void chat_system_init(void) { lv_init(); display_init(); input_init(); chat_styles_init(); initList(); pthread_create(&lvgl_thread_id, NULL, lvgl_refresh_thread, NULL); init_network(); pthread_create(&server_thread_id, NULL, network_recv_thread, NULL); create_main_interface(); } // 主运行函数 void Dir_Look_Running(Ui_Ctrl *uc) { uc->exit_mask = 1; while(uc->exit_mask) { sleep(1); } } // 资源释放 void Dir_Look_Free(Ui_Ctrl *uc) { thread_exit_flag = true; pthread_join(lvgl_thread_id, NULL); pthread_join(server_thread_id, NULL); if(g_tcpSocketFd != -1) close(g_tcpSocketFd); if(g_udpSockFd != -1) close(g_udpSockFd); // 释放链表资源 Node_t *p = friend_list->head; while(p) { Node_t *tmp = p; p = p->next; free(tmp); } free(friend_list); free(disp_buf); lv_deinit(); }
最新发布
09-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值