实现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();
}
最新发布