747 lines
20 KiB
C
747 lines
20 KiB
C
#include "mywin_inc.h"
|
||
|
||
// 定义基本窗口类型字符串
|
||
#define WIN_WINDOW_TYPE "WIN_WindowStruct"
|
||
|
||
// 窗口环境变量
|
||
static WIN_Struct g_win_struct = {0};
|
||
|
||
int WIN_Init(void) {
|
||
// 配置初始化
|
||
WIN_InitCfg();
|
||
|
||
// 屏幕初始化
|
||
WIN_GetWinStruct()->lcd->Init();
|
||
|
||
// 基础窗口初始化
|
||
WIN_GetWinStruct()->baseWin.x = 0;
|
||
WIN_GetWinStruct()->baseWin.y = 0;
|
||
WIN_GetWinStruct()->baseWin.x_size = WIN_GetWinStruct()->lcd->getLcdSizeX();
|
||
WIN_GetWinStruct()->baseWin.y_size = WIN_GetWinStruct()->lcd->getLcdSizeY();
|
||
WIN_GetWinStruct()->baseWin.baseWin = 0;
|
||
WIN_GetWinStruct()->baseWin.chidWinMaxSize = WIN_CHIDWIN_MAXNUM;
|
||
WIN_GetWinStruct()->baseWin.id = WIN_GetWinStruct()->winId++;
|
||
WIN_GetWinStruct()->baseWin.winType = WIN_WINDOW_TYPE; // 基本窗口类型
|
||
u16 color = WIN_GetWinStruct()->lcd->getLcdBkColor();
|
||
WIN_GetWinStruct()->baseWin.color = COLOR565TO888(color);
|
||
color = WIN_GetWinStruct()->lcd->getLcdBkColor();
|
||
WIN_GetWinStruct()->baseWin.bkcolor = COLOR565TO888(color);
|
||
WIN_GetWinStruct()->baseWin.msgLoop = WIN_DefaultMsgLoop;
|
||
|
||
// 主窗口的消息队列初始化
|
||
QUEUE_Init(&WIN_GetWinStruct()->baseWin.winMsgQueue, sizeof(WIN_MsgStruct),
|
||
50);
|
||
WIN_MsgStruct msg = {0};
|
||
msg.msg = WIN_MSG_INIT;
|
||
WIN_SendMsg(0, &WIN_GetWinStruct()->baseWin, &msg);
|
||
|
||
// 键盘,触摸队列初始化
|
||
QUEUE_Init(&WIN_GetWinStruct()->touchQueue, sizeof(WIN_TouchStruct), 50);
|
||
QUEUE_Init(&WIN_GetWinStruct()->keyQueue, sizeof(WIN_KeyStruct), 50);
|
||
|
||
// 显示基础窗口
|
||
WIN_ShowWindow(&WIN_GetWinStruct()->baseWin);
|
||
return 0;
|
||
}
|
||
|
||
// 返回窗口环境变量
|
||
WIN_Struct *WIN_GetWinStruct(void) { return &g_win_struct; }
|
||
|
||
// 设置窗口运行回调函数
|
||
void *WIN_SetRunCallBack(void (*callback)(void)) {
|
||
void *ret = g_win_struct.runCallBack;
|
||
if (callback)
|
||
g_win_struct.runCallBack = callback;
|
||
return ret;
|
||
}
|
||
|
||
// 获取外部数据指针,这个函数在窗口应用中调用,
|
||
// 获取之后要释放g_win_struct.ExtData 指向的内存
|
||
void *WIN_GetExtData(u32 *datasize) {
|
||
WIN_IRQ_DISABLE();
|
||
void *ret = g_win_struct.ExtData;
|
||
*datasize = g_win_struct.ExtDataSize;
|
||
g_win_struct.ExtData = 0;
|
||
g_win_struct.ExtDataSize = 0;
|
||
WIN_IRQ_ENABLE();
|
||
return ret;
|
||
}
|
||
|
||
// 放置外部数据到窗口,这个函数在其他线程或中断中调用
|
||
int WIN_PlaceExtData(void *data, u32 size) {
|
||
int ret = -1;
|
||
void *buff = mymalloc(size);
|
||
mymemcpy(buff, data, size);
|
||
WIN_IRQ_DISABLE();
|
||
if (g_win_struct.ExtData == 0) {
|
||
g_win_struct.ExtData = buff;
|
||
g_win_struct.ExtDataSize = size;
|
||
ret = 0;
|
||
} else {
|
||
ret = -1;
|
||
myfree(buff);
|
||
}
|
||
WIN_IRQ_ENABLE();
|
||
return ret;
|
||
}
|
||
|
||
// 设置在指定窗口运行的函数,返回0,成功
|
||
// 这个函数用于在窗口线程之外通知窗口调用函数
|
||
int WIN_RunInWindow(const char *title, void (*fun)(void *ptr), void *ptr) {
|
||
int ret = -1;
|
||
WIN_IRQ_DISABLE();
|
||
WIN_WindowStruct *win = WIN_GetWinByTitle(0, (char *)title);
|
||
if (win) {
|
||
WIN_MsgStruct msg = {0};
|
||
msg.msg = WIN_MSG_RUN;
|
||
msg.data.p = fun;
|
||
msg.data2.p = ptr;
|
||
ret = WIN_SendMsg(0, win, &msg);
|
||
}
|
||
WIN_IRQ_ENABLE();
|
||
return ret;
|
||
}
|
||
|
||
// 运行消息中的函数 ,返回0,成功
|
||
// 这个函数在窗口消息循环中接收到运行消息后调用
|
||
int WIN_RunMsgFunction(WIN_MsgStruct *msg) {
|
||
int ret = -1;
|
||
if (msg->msg == WIN_MSG_RUN) {
|
||
if (msg->data.p) {
|
||
((void (*)(void *t))msg->data.p)(msg->data2.p);
|
||
ret = 0;
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// 在堆中创建一个窗口,返回窗口的指针
|
||
WIN_WindowStruct *WIN_CreatWindow(WIN_WindowStruct *base,
|
||
void (*msgLoop)(struct _WIN_WindowStruct *win,
|
||
WIN_MsgStruct *msg),
|
||
int x, int y, int x_size, int y_size) {
|
||
if (base == 0)
|
||
base = WIN_GetBaseWindow(); // 没有父窗口,默认父窗口
|
||
WIN_WindowStruct *ret = mymalloc(sizeof(WIN_WindowStruct));
|
||
mymemset(ret, 0, sizeof(WIN_WindowStruct));
|
||
u16 color = WIN_GetWinStruct()->lcd->getLcdBkColor();
|
||
ret->bkcolor = COLOR565TO888(color);
|
||
color = WIN_GetWinStruct()->lcd->getLcdColor();
|
||
ret->color = COLOR565TO888(color);
|
||
ret->chidWinMaxSize = WIN_CHIDWIN_MAXNUM;
|
||
ret->x = x;
|
||
ret->y = y;
|
||
ret->x_size = x_size;
|
||
ret->y_size = y_size;
|
||
ret->id = WIN_GetWinStruct()->winId++; // 设置窗口唯一ID
|
||
ret->winType = WIN_WINDOW_TYPE; // 基本窗口类型
|
||
ret->baseWin = base; // 注册父窗口
|
||
if (msgLoop)
|
||
ret->msgLoop = msgLoop; // 设置消息处理函数
|
||
else
|
||
ret->msgLoop = WIN_DefaultMsgLoop; // 设置默认消息处理函数
|
||
ret->deleteWindow = WIN_DeleteWindow; // 设置销毁函数
|
||
if (WIN_AddToChidList(base, ret) == 0) {
|
||
QUEUE_Init(&ret->winMsgQueue, sizeof(WIN_MsgStruct), 50);
|
||
WIN_MsgStruct msg = {0};
|
||
msg.msg = WIN_MSG_INIT;
|
||
WIN_SendMsg(0, ret, &msg);
|
||
return ret;
|
||
} else {
|
||
myfree(ret);
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// 创建已经实例化的窗口,返回1,创建成功
|
||
int WIN_CreatWindowExt(WIN_WindowStruct *win, WIN_WindowStruct *base,
|
||
void (*msgLoop)(struct _WIN_WindowStruct *win,
|
||
WIN_MsgStruct *msg),
|
||
int x, int y, int x_size, int y_size) {
|
||
if (base == 0)
|
||
base = WIN_GetBaseWindow(); // 没有父窗口,默认父窗口
|
||
mymemset(win, 0, sizeof(WIN_WindowStruct));
|
||
u16 color = WIN_GetWinStruct()->lcd->getLcdBkColor();
|
||
win->bkcolor = COLOR565TO888(color);
|
||
color = WIN_GetWinStruct()->lcd->getLcdColor();
|
||
win->color = COLOR565TO888(color);
|
||
win->chidWinMaxSize = WIN_CHIDWIN_MAXNUM;
|
||
win->x = x;
|
||
win->y = y;
|
||
win->x_size = x_size;
|
||
win->y_size = y_size;
|
||
win->id = WIN_GetWinStruct()->winId++; // 设置窗口唯一ID
|
||
win->winType = WIN_WINDOW_TYPE; // 基本窗口类型
|
||
win->baseWin = base; // 注册父窗口
|
||
if (msgLoop)
|
||
win->msgLoop = msgLoop; // 设置消息处理函数
|
||
else
|
||
win->msgLoop = WIN_DefaultMsgLoop; // 设置默认消息处理函数
|
||
win->deleteWindow = WIN_DeleteWindow; // 设置销毁函数
|
||
if (WIN_AddToChidList(base, win) == 0) {
|
||
QUEUE_Init(&win->winMsgQueue, sizeof(WIN_MsgStruct), 50);
|
||
WIN_MsgStruct msg = {0};
|
||
msg.msg = WIN_MSG_INIT;
|
||
WIN_SendMsg(0, win, &msg);
|
||
return 1;
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// 销毁一个窗口,资源回收
|
||
void WIN_DeleteWindow(WIN_WindowStruct *win) {
|
||
|
||
// 调用子窗口的销毁函数
|
||
while (win->chidWinNum) {
|
||
(win->chid)->deleteWindow(win->chid);
|
||
}
|
||
|
||
// 在父窗口的窗口列表中删除
|
||
WIN_DelFromChidList(win->baseWin, win);
|
||
|
||
WIN_MsgStruct msg = {0};
|
||
// 告知父窗口,子窗口已删除
|
||
msg.msg = WIN_MSG_CHID;
|
||
msg.data.v = CHID_DELETE;
|
||
msg.data2.v = win->id;
|
||
WIN_SendMsg(win, win->baseWin, &msg);
|
||
|
||
// 清空消息队列
|
||
WIN_ClearMsgQueue(win);
|
||
|
||
// 发送delete消息
|
||
msg.msg = WIN_MSG_DELETE;
|
||
WIN_SendMsg(0, win, &msg);
|
||
|
||
// 通过运行一遍消息循环让窗口处理善后工作
|
||
WIN_Working(win);
|
||
|
||
// 父窗口需要重绘
|
||
WIN_SetInvalidRect(win->baseWin, win->x, win->y, win->x_size, win->y_size);
|
||
|
||
// 删除创建的定时器
|
||
WIN_WinDeleteTimer(win);
|
||
|
||
// 取消置顶
|
||
WIN_ResetAsTopWin(win);
|
||
|
||
// 销毁队列
|
||
QUEUE_Delete(&win->winMsgQueue);
|
||
|
||
// 当前在阻塞运行本窗口,返回
|
||
if (g_win_struct.BlockWin[0] == win) {
|
||
WIN_SetBlockWinReturn(-1, 0, 0);
|
||
}
|
||
|
||
// 清除窗口无效标志
|
||
if (win->invald) {
|
||
win->invald = 0;
|
||
g_win_struct.numOfWindowToPrint--;
|
||
}
|
||
|
||
// printf ("deleteWin:%s\r\n",win->winType);
|
||
|
||
// 删除窗口,如果当前还在窗口的消息循环里,则不能立即释放内存
|
||
if (win->msgLoopEnter) {
|
||
win->memFree = myfree;
|
||
} else {
|
||
myfree(win);
|
||
}
|
||
}
|
||
|
||
// 将指定窗口设置为置顶,返回1添加成功
|
||
int WIN_SetAsTopWin(WIN_WindowStruct *win) {
|
||
int i = 0;
|
||
// for (i=0;g_win_struct.TopWin[i];i++);
|
||
i = g_win_struct.TopWinNum;
|
||
if (i < WIN_TOP_MAXNUM) {
|
||
g_win_struct.TopWin[i] = win;
|
||
g_win_struct.TopWinNum++;
|
||
return 1;
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// 窗口取消置顶,返回1成功
|
||
int WIN_ResetAsTopWin(WIN_WindowStruct *win) {
|
||
int i = 0;
|
||
for (i = 0; i < g_win_struct.TopWinNum; i++) {
|
||
if (g_win_struct.TopWin[i] == win) {
|
||
g_win_struct.TopWin[i] = 0;
|
||
// 后面的窗口向前移
|
||
g_win_struct.TopWinNum--;
|
||
for (; i < g_win_struct.TopWinNum; i++) {
|
||
g_win_struct.TopWin[i] = g_win_struct.TopWin[i + 1];
|
||
}
|
||
return 1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// 根据指定id号获取窗口指针
|
||
WIN_WindowStruct *WIN_GetWindowStructById(WIN_WindowStruct *win, u32 id) {
|
||
WIN_WindowStruct *ret = 0;
|
||
if (win == 0)
|
||
win = WIN_GetBaseWindow();
|
||
if (win->id == id) {
|
||
return win;
|
||
} else {
|
||
WIN_WindowStruct *prev = WIN_GetLastChidWin(win);
|
||
for (int i = win->chidWinNum; i > 0; i--) {
|
||
if (ret = WIN_GetWindowStructById(prev, id), ret) {
|
||
return ret;
|
||
}
|
||
prev = prev->prev;
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// 从子窗口列表中删除指定窗口
|
||
int WIN_DelFromChidList(WIN_WindowStruct *win, WIN_WindowStruct *chidWin) {
|
||
WIN_WindowStruct *next = win->chid;
|
||
for (int i = 0; i < win->chidWinNum; i++) {
|
||
if (next == chidWin) {
|
||
if(next != win->chid) {
|
||
next->prev->next = next->next;
|
||
} else {
|
||
win->chid = next->next;
|
||
}
|
||
if(next->next){
|
||
next->next->prev = next->prev;
|
||
}else{
|
||
win->chid->prev = next->prev;
|
||
}
|
||
win->chidWinNum--; // 子窗口个数减一
|
||
return 0;
|
||
}
|
||
next = next->next;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
// 把指定子窗口设置为最高
|
||
int WIN_SetChidWinTop(WIN_WindowStruct *win, WIN_WindowStruct *chidWin) {
|
||
WIN_WindowStruct *t = 0;
|
||
WIN_WindowStruct *next = win->chid;
|
||
for (int i = 0; i < win->chidWinNum; i++) {
|
||
if (next == chidWin) {
|
||
t = next;
|
||
if(next != win->chid) {
|
||
next->prev->next = next->next;
|
||
} else {
|
||
win->chid = next->next;
|
||
}
|
||
if(next->next){
|
||
next->next->prev = next->prev;
|
||
}else{
|
||
win->chid->prev = next->prev;
|
||
}
|
||
t->next = 0;
|
||
t->prev = win->chid->prev;
|
||
win->chid->prev->next = t;
|
||
win->chid->prev = t;
|
||
return 0;
|
||
}
|
||
next = next->next;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
// 添加窗口到子窗口列表中
|
||
int WIN_AddToChidList(WIN_WindowStruct *win, WIN_WindowStruct *chidWin) {
|
||
if (win->chidWinNum < win->chidWinMaxSize) {
|
||
chidWin->next = 0;
|
||
if(win->chid == 0){
|
||
win->chid = chidWin;
|
||
}else{
|
||
chidWin->prev = win->chid->prev;
|
||
win->chid->prev->next = chidWin;
|
||
}
|
||
win->chid->prev = chidWin;
|
||
win->chidWinNum++;
|
||
return 0;
|
||
} else {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// 判断目标窗口是不是子窗口,是返回1
|
||
int WIN_CheckChidWin(WIN_WindowStruct *win, WIN_WindowStruct *chid) {
|
||
WIN_WindowStruct *next = win->chid;
|
||
for (int i = 0; i < win->chidWinNum; i++) {
|
||
if (next == chid)
|
||
return 1;
|
||
next = next->next;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// 找到指定窗口在屏幕上的坐标和大小
|
||
void WIN_GetWinPosOnLcd(WIN_WindowStruct *win, int *x, int *y, int *x_size,
|
||
int *y_size) {
|
||
*x = 0;
|
||
*y = 0;
|
||
*x_size = win->x_size;
|
||
*y_size = win->y_size;
|
||
|
||
// 遍历父窗口获得窗口的实际屏幕坐标
|
||
WIN_WindowStruct *t = win;
|
||
do {
|
||
*x += t->x;
|
||
*y += t->y;
|
||
t = t->baseWin;
|
||
} while (t);
|
||
}
|
||
|
||
// 阻塞窗口运行结束时设置返回值
|
||
void WIN_SetBlockWinReturn(int ret, void *data, int datasize) {
|
||
g_win_struct.BlockWinReturn = ret;
|
||
|
||
// 上个阻塞窗口的数据没有读取,这里丢弃掉
|
||
if (g_win_struct.BlockWinData)
|
||
myfree(g_win_struct.BlockWinData);
|
||
if (data && datasize) {
|
||
g_win_struct.BlockWinData = mymalloc(datasize);
|
||
mymemcpy(g_win_struct.BlockWinData, data, datasize);
|
||
g_win_struct.BlockWinDataSize = datasize;
|
||
} else {
|
||
g_win_struct.BlockWinData = 0;
|
||
g_win_struct.BlockWinDataSize = 0;
|
||
}
|
||
|
||
// 调用了这个函数之后窗口返回
|
||
// 这里执行窗口栈出栈
|
||
if (g_win_struct.BlockWinNum) {
|
||
g_win_struct.BlockWinNum--;
|
||
for (int i = 0; i < g_win_struct.BlockWinNum; i++) {
|
||
g_win_struct.BlockWin[i] = g_win_struct.BlockWin[i + 1];
|
||
}
|
||
g_win_struct.BlockWin[g_win_struct.BlockWinNum] = 0;
|
||
}
|
||
}
|
||
|
||
// 获取阻塞窗口的数据
|
||
int WIN_GetBlockWinReturn(int *ret, void *buff, int buffsize) {
|
||
int size = buffsize;
|
||
if (size > g_win_struct.BlockWinDataSize)
|
||
size = g_win_struct.BlockWinDataSize;
|
||
*ret = g_win_struct.BlockWinReturn;
|
||
if (g_win_struct.BlockWinData) {
|
||
mymemcpy(buff, g_win_struct.BlockWinData, size);
|
||
myfree(g_win_struct.BlockWinData);
|
||
// 解决free(g_win_struct.BlockWinData)之后在函数WIN_SetBlockWinReturn再次free的bug
|
||
// 2020.8.3
|
||
g_win_struct.BlockWinData = 0;
|
||
}
|
||
return size;
|
||
}
|
||
|
||
// 返回基础窗口指针
|
||
WIN_WindowStruct *WIN_GetBaseWindow(void) {
|
||
return &WIN_GetWinStruct()->baseWin;
|
||
}
|
||
|
||
// 返回最后一次运行的窗口
|
||
WIN_WindowStruct *WIN_GetCurrentWindow(void) {
|
||
return WIN_GetWinStruct()->winCurrent;
|
||
}
|
||
|
||
// 找到顶端可控窗口
|
||
WIN_WindowStruct *WIN_FindTopWin(WIN_WindowStruct *win) {
|
||
WIN_WindowStruct *ret = 0;
|
||
WIN_WindowStruct *prev = WIN_GetLastChidWin(win);
|
||
if (win && (win->chidWinNum)) {
|
||
for (int i = win->chidWinNum; i > 0; i--) {
|
||
ret = WIN_FindTopWin(prev);
|
||
if (ret)
|
||
return ret;
|
||
prev = prev->prev;
|
||
}
|
||
}
|
||
// 本窗口接受消息处理并且不是子窗口
|
||
if (win && (win->keyShield == 0) && (win->keyChid == 0))
|
||
return win;
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
// 查找win是否被遮挡,是,返回1
|
||
int WIN_FindBlock(WIN_WindowStruct *win) {
|
||
RECT_Struct r1 = {0};
|
||
RECT_Struct r2 = {0};
|
||
WIN_WindowStruct *top = 0;
|
||
WIN_WindowStruct *base = win->baseWin;
|
||
WIN_WindowStruct *next = win->chid;
|
||
WIN_WindowStruct *prev;
|
||
|
||
// 该窗口被遮挡只可能是其子窗口和其同辈父辈窗口
|
||
for (int i = 0; i < win->chidWinNum; i++) {
|
||
top = next;
|
||
if ((top->keyShield == 1) || (top->keyChid == 1))
|
||
continue;
|
||
r1.x = 0;
|
||
r1.y = 0;
|
||
r1.x_size = win->x_size;
|
||
r1.y_size = win->y_size;
|
||
r2.x = top->x;
|
||
r2.y = top->y;
|
||
r2.x_size = top->x_size;
|
||
r2.y_size = top->y_size;
|
||
if (POS_RectIntersection(&r1, &r1, &r2)) {
|
||
return 1;
|
||
}
|
||
next = next->next;
|
||
}
|
||
while (base) {
|
||
prev = WIN_GetLastChidWin(base);
|
||
for (int i = base->chidWinNum; i > 0; i--) {
|
||
top = prev;
|
||
if (top == win) {
|
||
// 只比较在此窗口之前的窗口
|
||
// 若没有被遮挡,则继续判断其父窗口是否被遮挡
|
||
win = base;
|
||
break;
|
||
}
|
||
WIN_GetWinPosOnLcd(top, &r1.x, &r1.y, &r1.x_size, &r1.y_size);
|
||
WIN_GetWinPosOnLcd(win, &r2.x, &r2.y, &r2.x_size, &r2.y_size);
|
||
if (POS_RectIntersection(&r1, &r1, &r2)) {
|
||
return 1;
|
||
}
|
||
prev = prev->prev;
|
||
}
|
||
base = base->baseWin;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// 屏蔽和接触屏蔽子窗口的按键和键盘消息
|
||
int WIN_SetChildWinkeyShield(WIN_WindowStruct *win, int power) {
|
||
WIN_WindowStruct *prev = WIN_GetLastChidWin(win);
|
||
for (int i = win->chidWinNum - 1; i >= 0; i--) {
|
||
prev->keyShield = power;
|
||
prev = prev->prev;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
// 通过指定的坐标找到顶端可控的窗口,没找到返回0
|
||
WIN_WindowStruct *WIN_FindTopWinByPos(WIN_WindowStruct *win, int x, int y) {
|
||
WIN_WindowStruct *ret = win;
|
||
int win_x_s = 0;
|
||
int win_y_s = 0;
|
||
int x_size = win->x_size;
|
||
int y_size = win->y_size;
|
||
WIN_WindowStruct *prev = WIN_GetLastChidWin(win);
|
||
|
||
WIN_GetWinPosOnLcd(win, &win_x_s, &win_y_s, &x_size, &y_size);
|
||
|
||
WIN_WindowStruct *t = 0;
|
||
if (((x >= win_x_s) && (x < win_x_s + x_size)) &&
|
||
((y >= win_y_s) && (y < win_y_s + y_size)) && (win->keyShield == 0)) {
|
||
// 在本窗口内,查找是否有子窗口
|
||
// 从最后开始查找,因为越最后的显示在越前面
|
||
for (int i = win->chidWinNum - 1; i >= 0; i--) {
|
||
t = WIN_FindTopWinByPos(prev, x, y);
|
||
if (t) {
|
||
ret = t; // 找到了最前面的窗口
|
||
break;
|
||
}
|
||
prev = prev->prev;
|
||
}
|
||
} else {
|
||
// 指定点不在本窗口之类
|
||
ret = 0;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// 返回两个窗口的共同父窗口,没有共同父窗口返回0
|
||
WIN_WindowStruct *WIN_FindPrent(WIN_WindowStruct *win1,
|
||
WIN_WindowStruct *win2) {
|
||
while ((win1) && (win2)) {
|
||
if (win1 == win2)
|
||
return win1;
|
||
win1 = win1->baseWin;
|
||
win2 = win2->baseWin;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// 设置窗口标题
|
||
void WIN_SetWinTitle(WIN_WindowStruct *win, char *title) {
|
||
int len = strlen(title);
|
||
if (len > WIN_WINTITLE_MAXLEN - 1) {
|
||
len = WIN_WINTITLE_MAXLEN - 1;
|
||
}
|
||
mymemcpy(win->winTitle, title, len);
|
||
win->winTitle[len] = 0;
|
||
}
|
||
|
||
// 根据窗口标题找到窗口指针
|
||
// 深度优先搜索
|
||
WIN_WindowStruct *WIN_GetWinByTitle(WIN_WindowStruct *win, char *title) {
|
||
WIN_WindowStruct *ret = 0;
|
||
if (win == 0)
|
||
win = WIN_GetBaseWindow();
|
||
WIN_WindowStruct *next = win->chid;
|
||
|
||
if (strcmp(win->winTitle, title) == 0) {
|
||
ret = win;
|
||
} else {
|
||
for (int i = 0; i < win->chidWinNum; i++) {
|
||
if (ret = WIN_GetWinByTitle(next, title), ret)
|
||
break;
|
||
next = next->next;
|
||
}
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
// 根据窗口坐标设置LCD的活动窗口,所有绘制操作都在这个窗口之内
|
||
void WIN_EnterPaint(WIN_WindowStruct *win) {
|
||
int x = 0;
|
||
int y = 0;
|
||
int x_size = win->x_size;
|
||
int y_size = win->y_size;
|
||
|
||
WIN_GetWinPosOnLcd(win, &x, &y, &x_size, &y_size);
|
||
|
||
WIN_GetWinStruct()->lcd->setWindow(x, y, x_size, y_size);
|
||
}
|
||
|
||
// 设置无效区矩形,此矩形会被限制在窗口无效区之内
|
||
void WIN_SetWinInvalidRect(WIN_WindowStruct *win, RECT_Struct *r) {
|
||
if (r == 0)
|
||
r = &win->invaldRect;
|
||
RECT_Struct out = {0};
|
||
POS_RectIntersection(&out, r, &win->invaldRect);
|
||
int x = out.x;
|
||
int y = out.y;
|
||
int x_size = out.x_size;
|
||
int y_size = out.y_size;
|
||
|
||
g_win_struct.Invalid_x = x;
|
||
g_win_struct.Invalid_y = y;
|
||
g_win_struct.Invalid_x_size = x_size;
|
||
g_win_struct.Invalid_y_size = y_size;
|
||
}
|
||
|
||
// 获取窗口无效区矩形
|
||
void WIN_GetWinInvalidRect(WIN_WindowStruct *win, RECT_Struct *r) {
|
||
r->x = g_win_struct.Invalid_x;
|
||
r->y = g_win_struct.Invalid_y;
|
||
r->x_size = g_win_struct.Invalid_x_size;
|
||
r->y_size = g_win_struct.Invalid_y_size;
|
||
}
|
||
|
||
// 在窗口绘制时,判断需不需要绘制顶端窗口
|
||
void WIN_TopWinPaint(WIN_WindowStruct *win) {
|
||
RECT_Struct r1 = {0};
|
||
RECT_Struct r2 = {0};
|
||
RECT_Struct rout = {0};
|
||
WIN_GetWinPosOnLcd(win, &r1.x, &r1.y, &r1.x_size, &r1.y_size);
|
||
for (int i = 0; i < g_win_struct.TopWinNum; i++) {
|
||
WIN_GetWinPosOnLcd(g_win_struct.TopWin[i], &r2.x, &r2.y, &r2.x_size,
|
||
&r2.y_size);
|
||
if (POS_RectIntersection(&rout, &r1, &r2) == 1) {
|
||
// 需要刷新顶端窗口
|
||
WIN_SetInvalidRect(g_win_struct.TopWin[i], rout.x - r2.x, rout.y - r2.y,
|
||
rout.x_size, rout.y_size);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 窗口默认的绘制函数
|
||
void WIN_DefaultPaint(WIN_WindowStruct *win) {
|
||
WIN_PaintBackGround(win);
|
||
// WIN_SetLcdColor (win->color);
|
||
// WIN_Clear();
|
||
// WIN_DrawHLine(0,0,LCD_GetWindowSizeX()-1);
|
||
// WIN_DrawVLine(0,0,LCD_GetWindowSizeY()-1);
|
||
// WIN_DrawHLine(0,LCD_GetWindowSizeY()-1,LCD_GetWindowSizeX()-1);
|
||
// WIN_DrawVLine(LCD_GetWindowSizeX()-1,0,LCD_GetWindowSizeY()-1);
|
||
}
|
||
|
||
// 显示窗口
|
||
void WIN_ShowWindow(WIN_WindowStruct *win) {
|
||
// 把窗口设置为无效,
|
||
WIN_SetInvalid(win);
|
||
|
||
// 通过运行一遍消息循环来显示
|
||
// WIN_Working (win);
|
||
}
|
||
|
||
// 绘制背景
|
||
void WIN_PaintBackGround(WIN_WindowStruct *win) {
|
||
// 如果有图片就显示图片
|
||
WIN_SetLcdBkColor(win->bkcolor);
|
||
WIN_PicStruct *pic = 0;
|
||
|
||
if (win->drawBackPic) {
|
||
win->drawBackPic();
|
||
} else if (pic = WIN_GetPicNoAlpha(win->pic_path), pic) {
|
||
WIN_DrawPic(pic, 0, 0, ((WIN_WindowStruct *)win)->x_size,
|
||
((WIN_WindowStruct *)win)->y_size);
|
||
} else if (WIN_DrawPic(&win->pic, 0, 0, ((WIN_WindowStruct *)win)->x_size,
|
||
((WIN_WindowStruct *)win)->y_size)) {
|
||
} else {
|
||
WIN_Clear();
|
||
}
|
||
}
|
||
|
||
void WIN_SetColor(WIN_WindowStruct *win, u32 color) { win->color = color; }
|
||
|
||
void WIN_SetBkColor(WIN_WindowStruct *win, u32 bkcolor) {
|
||
win->bkcolor = bkcolor;
|
||
}
|
||
|
||
// 设置页面的背景图片路径
|
||
void WIN_SetBackPicPath(WIN_WindowStruct *win, char *path) {
|
||
if (path) {
|
||
int len = strlen(path);
|
||
if (len + 1 > WIN_FILE_PATH_MAXLEN)
|
||
printf("%s:err,pic path too long\r\n", __func__);
|
||
|
||
mymemcpy(&win->pic_path, path, len + 1);
|
||
WIN_PicStruct *pic = WIN_GetPic(win->pic_path);
|
||
if (pic)
|
||
mymemcpy(&win->pic, pic, sizeof(WIN_PicStruct));
|
||
} else {
|
||
int len = strlen(path);
|
||
mymemset(&win->pic_path, 0, len + 1);
|
||
}
|
||
}
|
||
|
||
// 设置页面的背景图片
|
||
void WIN_SetBackPic(WIN_WindowStruct *win) {
|
||
WIN_PicStruct pic = {0};
|
||
WIN_WindowStruct *base = win->baseWin;
|
||
WIN_PicStruct *pic_base = WIN_GetPic(base->pic_path);
|
||
if (pic_base) {
|
||
int x = win->x;
|
||
int y = win->y;
|
||
if ((y < pic_base->ysize) && (x < pic_base->xsize)) {
|
||
pic.data = pic_base->data + pic_base->xsize * y + x;
|
||
pic.xsize = pic_base->xsize;
|
||
pic.ysize = pic_base->ysize - y - 1;
|
||
}
|
||
mymemcpy(&win->pic, &pic, sizeof(WIN_PicStruct));
|
||
} else {
|
||
mymemset(&win->pic, 0, sizeof(WIN_PicStruct));
|
||
}
|
||
}
|
||
|
||
// 设置页面的画背景函数
|
||
void *WIN_SetBackFun(WIN_WindowStruct *win, void (*fun)(void)) {
|
||
void *ret = win->drawBackPic;
|
||
if (fun) {
|
||
win->drawBackPic = fun;
|
||
}
|
||
return ret;
|
||
}
|