825 lines
24 KiB
C
825 lines
24 KiB
C
#include "mywin_inc.h"
|
||
|
||
// 存储触摸信息,0,成功,非0,失败
|
||
int WIN_StorTouchStruct(WIN_TouchStruct *t) {
|
||
static int press = 0;
|
||
|
||
// 队列还没有初始化
|
||
if (WIN_GetWinStruct()->touchQueue.data == 0)
|
||
return -1;
|
||
if (WIN_GetWinStruct()->keyShield == 1)
|
||
return -2;
|
||
// 存储最后一次松开后的触屏数据
|
||
if ((press != t->pressNum) || t->pressNum) {
|
||
press = t->pressNum;
|
||
if (QUEUE_In(&WIN_GetWinStruct()->touchQueue, t) == 1)
|
||
return -3;
|
||
else
|
||
return 0;
|
||
}
|
||
return -4;
|
||
}
|
||
|
||
// 存储按键信息,返回0,成功,非0,失败
|
||
int WIN_StorKeyStruct(WIN_KeyStruct *k) {
|
||
static int press = 0;
|
||
// 队列还没有初始化
|
||
if (WIN_GetWinStruct()->keyQueue.data == 0)
|
||
return -1;
|
||
if (WIN_GetWinStruct()->keyShield == 1)
|
||
return -2;
|
||
// 存储最后一次按键松开的消息
|
||
if ((press != k->state) || k->state) {
|
||
press = k->state;
|
||
if (QUEUE_In(&WIN_GetWinStruct()->keyQueue, k) == 1)
|
||
return -1;
|
||
else
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
// 清空按键队列
|
||
void WIN_ClearKeyQueue(void) {
|
||
WIN_KeyStruct k = {0};
|
||
while (QUEUE_Out(&WIN_GetWinStruct()->keyQueue, &k)) {
|
||
}
|
||
}
|
||
|
||
// 清空触摸队列
|
||
void WIN_ClearTouchQueue(void) {
|
||
WIN_KeyStruct k = {0};
|
||
while (QUEUE_Out(&WIN_GetWinStruct()->touchQueue, &k)) {
|
||
}
|
||
}
|
||
|
||
// 屏蔽按键和触屏
|
||
void WIN_KeyShieldOn(void) { WIN_GetWinStruct()->keyShield = 1; }
|
||
|
||
// 不屏蔽按键和触屏
|
||
void WIN_KeyShieldOff(void) { WIN_GetWinStruct()->keyShield = 0; }
|
||
|
||
// 默认的消息处理函数
|
||
void WIN_DefaultMsgLoop(WIN_WindowStruct *win, WIN_MsgStruct *msg) {
|
||
switch (msg->msg) {
|
||
case WIN_MSG_PAINT:
|
||
WIN_DefaultPaint(win);
|
||
break;
|
||
case WIN_MSG_INIT:
|
||
break;
|
||
case WIN_MSG_KEY:
|
||
// if (win!= WIN_GetBaseWindow())
|
||
// win->deleteWindow(win);
|
||
break;
|
||
case WIN_MSG_TOUCH:
|
||
// if (win != WIN_GetBaseWindow())
|
||
// win->deleteWindow(win);
|
||
break;
|
||
case WIN_MSG_CHID:
|
||
break;
|
||
case WIN_MSG_DELETE:
|
||
break;
|
||
case WIN_MSG_MOVE:
|
||
break;
|
||
case WIN_MSG_EXTMSG:
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 修改窗口的消息循环函数
|
||
void *WIN_SetMsgCallBack(WIN_WindowStruct *win,
|
||
void (*msgLoop)(struct _WIN_WindowStruct *win,
|
||
WIN_MsgStruct *msg)) {
|
||
void *ret = win->msgLoop;
|
||
win->msgLoop = msgLoop;
|
||
return ret;
|
||
}
|
||
|
||
// 设置窗口消息循环
|
||
void *WIN_SetMsgLoopCallBack(WIN_WindowStruct *win,
|
||
void (*msgLoop)(struct _WIN_WindowStruct *win,
|
||
WIN_MsgStruct *msg)) {
|
||
void *ret = 0;
|
||
if (win) {
|
||
ret = win->msgLoop;
|
||
win->msgLoop = msgLoop;
|
||
} else {
|
||
ret = WIN_GetBaseWindow()->msgLoop;
|
||
WIN_GetBaseWindow()->msgLoop = msgLoop;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// 存储外部消息到活动窗口返回0,成功,非0,失败
|
||
int WIN_StorExtMsg(void *msgData, int size) {
|
||
int ret = -1;
|
||
WIN_MsgStruct msg = {0};
|
||
// 有任务在执行
|
||
if (WIN_GetWinStruct()->BlockWin[0]) {
|
||
msg.msg = WIN_MSG_EXTMSG;
|
||
msg.data.p = mymalloc(size);
|
||
mymemcpy(msg.data.p, msgData, size);
|
||
ret = WIN_SendMsg(0, WIN_GetWinStruct()->BlockWin[0], &msg);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// 发送外部信息到指定窗口
|
||
int WIN_WinStorExtMsg(WIN_WindowStruct *win, void *msgData, int size) {
|
||
int ret = -1;
|
||
WIN_MsgStruct msg = {0};
|
||
// 有任务在执行
|
||
if (win) {
|
||
msg.msg = WIN_MSG_EXTMSG;
|
||
msg.data.p = mymalloc(size);
|
||
mymemcpy(msg.data.p, msgData, size);
|
||
ret = WIN_SendMsg(0, win, &msg);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// 发送消息到指定窗口
|
||
int WIN_SendMsg(WIN_WindowStruct *win, WIN_WindowStruct *dscWin,
|
||
WIN_MsgStruct *msg) {
|
||
int ret = -1;
|
||
if (win)
|
||
msg->srcWin = win;
|
||
if (dscWin) // 目标窗口为0,不发送消息
|
||
{
|
||
// 不能向已销毁的窗口发消息
|
||
if (dscWin->memFree)
|
||
ret = -1;
|
||
else
|
||
ret = QUEUE_In(&dscWin->winMsgQueue, msg);
|
||
}
|
||
// 发送失败
|
||
if (ret != 0) {
|
||
// 释放这些消息在构建时申请的内存
|
||
switch (msg->msg) {
|
||
case WIN_MSG_KEY:
|
||
case WIN_MSG_TOUCH:
|
||
case WIN_MSG_EXTMSG:
|
||
case WIN_MSG_MOVE:
|
||
myfree(msg->data.p);
|
||
break;
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// 发送消息到父窗口
|
||
int WIN_SendMsgToPrent(WIN_WindowStruct *win, u32 type, u32 data) {
|
||
WIN_MsgStruct msg1 = {0};
|
||
msg1.msg = WIN_MSG_CHID;
|
||
msg1.data.v = type;
|
||
msg1.data2.v = data;
|
||
return WIN_SendMsg(win, win->baseWin, &msg1);
|
||
}
|
||
|
||
// 清空消息队列
|
||
void WIN_ClearMsgQueue(WIN_WindowStruct *win) {
|
||
WIN_MsgStruct msg = {0};
|
||
while (QUEUE_Out(&win->winMsgQueue, &msg)) {
|
||
switch (msg.msg) {
|
||
// 释放构建消息时申请的内存
|
||
case WIN_MSG_KEY:
|
||
case WIN_MSG_TOUCH:
|
||
case WIN_MSG_EXTMSG:
|
||
case WIN_MSG_MOVE:
|
||
myfree(msg.data.p);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 查找指定消息
|
||
WIN_MsgStruct *WIN_CheckMsg(WIN_WindowStruct *win, u32 msgType) {
|
||
WIN_MsgStruct *msg = 0;
|
||
QUEUE_CheckStart(&win->winMsgQueue);
|
||
while (msg = QUEUE_Check(&win->winMsgQueue), msg) {
|
||
if (msg->msg == msgType) {
|
||
return msg;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// 发送按键消息,同时发送给父窗口
|
||
void WIN_SendKeyMsg(WIN_WindowStruct *win, WIN_KeyStruct *k) {
|
||
WIN_MsgStruct msg = {0};
|
||
if (win->keyShield == 0) {
|
||
msg.msg = WIN_MSG_KEY;
|
||
// 要保证数据一直有效,消息读取后要free这段内存,否侧内存溢出
|
||
msg.data.p = mymalloc(sizeof(WIN_KeyStruct));
|
||
mymemcpy(msg.data.p, k, sizeof(WIN_KeyStruct));
|
||
WIN_SendMsg(0, win, &msg);
|
||
}
|
||
|
||
if ((win->baseWin) && (win->baseWin != WIN_GetBaseWindow()) &&
|
||
(win->intercept == 0)) {
|
||
WIN_SendKeyMsg(win->baseWin, k);
|
||
} else if (win->baseWin) {
|
||
// 所有按键消息都要发送到基础窗口
|
||
if (WIN_GetWinStruct()->BlockWinNum == 0)
|
||
WIN_SendKeyMsg(WIN_GetBaseWindow(), k);
|
||
}
|
||
}
|
||
|
||
// 发送触摸消息,同时发送给窗口所在的父窗口
|
||
void WIN_SendTouchMsg(WIN_WindowStruct *win, int lcd_x, int lcd_y) {
|
||
WIN_TouchStruct t = {0};
|
||
WIN_MsgStruct msg = {0};
|
||
if (win->keyShield == 0) {
|
||
msg.msg = WIN_MSG_TOUCH;
|
||
// 要保证数据一直有效,消息读取后要free这段内存,否侧内存溢出
|
||
msg.data.p = mymalloc(sizeof(WIN_TouchStruct));
|
||
int x, y, xs, ys;
|
||
WIN_GetWinPosOnLcd(win, &x, &y, &xs,
|
||
&ys); // 把屏幕上的绝对坐标转化为窗口的相对坐标
|
||
t.x[0] = lcd_x - x;
|
||
t.y[0] = lcd_y - y;
|
||
mymemcpy(msg.data.p, &t, sizeof(WIN_TouchStruct));
|
||
WIN_SendMsg(0, win, &msg);
|
||
}
|
||
|
||
if ((win->baseWin) && (win->intercept == 0)) {
|
||
WIN_SendTouchMsg(win->baseWin, lcd_x, lcd_y);
|
||
}
|
||
}
|
||
|
||
// 发送滑动信息,同时发送给父窗口
|
||
void WIN_SendTouchMove(WIN_WindowStruct *win, int move_x, int move_y) {
|
||
WIN_MoveStruct m = {0};
|
||
WIN_MsgStruct msg = {0};
|
||
|
||
if (win->keyShield == 0) {
|
||
msg.msg = WIN_MSG_MOVE;
|
||
msg.data.p = mymalloc(sizeof(WIN_MoveStruct));
|
||
m.moveType = MOVE_DATA_MOVED;
|
||
m.x_move = move_x;
|
||
m.y_move = move_y;
|
||
mymemcpy(msg.data.p, &m, sizeof(WIN_MoveStruct));
|
||
WIN_SendMsg(0, win, &msg);
|
||
}
|
||
|
||
if ((win->baseWin) && (win->intercept == 0)) {
|
||
WIN_SendTouchMove(win->baseWin, move_x, move_y);
|
||
}
|
||
}
|
||
|
||
// 广播触屏消息
|
||
int WIN_TouchMsgBroad(WIN_WindowStruct *base) {
|
||
int have_msg = 0; // 返回值
|
||
WIN_TouchStruct t = {0};
|
||
WIN_KeyStruct k = {0};
|
||
WIN_MoveStruct m = {0};
|
||
WIN_MsgStruct msg = {0};
|
||
WIN_MsgBroadStruct *broad = &WIN_GetWinStruct()->msgBroad;
|
||
while (QUEUE_Out(&WIN_GetWinStruct()->touchQueue, &t) == 1) {
|
||
have_msg = 1;
|
||
// 有触屏数据
|
||
broad->win = WIN_FindTopWinByPos(base, t.x[0], t.y[0]);
|
||
// while(broad->win&&broad->win->keyShield)
|
||
//broad->win=broad->win->baseWin;
|
||
if (broad->win) {
|
||
// 移动检测在两次都是按下的情况下才成立
|
||
if (broad->t_old.pressNum && t.pressNum) {
|
||
if (broad->win_old != broad->win) {
|
||
// 上一个窗口不是现在的窗口
|
||
// 上一个窗口移出,现在的窗口移入
|
||
if (broad->win_old) {
|
||
int x, y, xs, ys;
|
||
msg.msg = WIN_MSG_MOVE;
|
||
msg.data.p = mymalloc(sizeof(WIN_MoveStruct));
|
||
m.moveType = MOVE_DATA_MOVEOUT;
|
||
WIN_GetWinPosOnLcd(broad->win_old, &x, &y, &xs,
|
||
&ys); // 把屏幕上的绝对坐标转化为窗口的相对坐标
|
||
m.x_move = t.x[0] - x;
|
||
m.y_move = t.y[0] - y;
|
||
mymemcpy(msg.data.p, &m, sizeof(WIN_MoveStruct));
|
||
WIN_SendMsg(0, broad->win_old, &msg);
|
||
|
||
msg.msg = WIN_MSG_MOVE;
|
||
msg.data.p = mymalloc(sizeof(WIN_MoveStruct));
|
||
m.moveType = MOVE_DATA_MOVEIN;
|
||
WIN_GetWinPosOnLcd(broad->win, &x, &y, &xs,
|
||
&ys); // 把屏幕上的绝对坐标转化为窗口的相对坐标
|
||
m.x_move = t.x[0] - x;
|
||
m.y_move = t.y[0] - y;
|
||
mymemcpy(msg.data.p, &m, sizeof(WIN_MoveStruct));
|
||
WIN_SendMsg(0, broad->win, &msg);
|
||
broad->Touch_long = WIN_LONGTOUCH_CHECK; // 已经移动了,不再检测长按
|
||
} else {
|
||
// 松开屏幕后的第一次点击
|
||
}
|
||
broad->win_old = broad->win;
|
||
} // if (win_old!=win)
|
||
WIN_WindowStruct *win_move = 0;
|
||
if (win_move = WIN_FindPrent(broad->win_old, broad->win),
|
||
win_move != 0) {
|
||
// 两次触摸值没超过抖动范围
|
||
if (POS_RoundPix(1, broad->t_old.x[0], broad->t_old.y[0], t.x[0],
|
||
t.y[0]) != 0) {
|
||
// 在同一个窗口内移动
|
||
WIN_SendTouchMove(win_move, t.x[0] - broad->t_old.x[0],
|
||
t.y[0] - broad->t_old.y[0]);
|
||
broad->Touch_long =
|
||
WIN_LONGTOUCH_CHECK + 10; // 已经移动了,不再检测长按
|
||
} else {
|
||
// 多次触摸都没有移动,记录长按
|
||
if (broad->Touch_long < WIN_LONGTOUCH_CHECK) {
|
||
broad->Touch_long++;
|
||
if (broad->Touch_long >= WIN_LONGTOUCH_CHECK) {
|
||
// 发送一次长按消息
|
||
msg.msg = WIN_MSG_MOVE;
|
||
msg.data.p = mymalloc(sizeof(WIN_MoveStruct));
|
||
m.moveType = MOVE_DATA_LONG;
|
||
int x, y, xs, ys;
|
||
WIN_GetWinPosOnLcd(
|
||
broad->win, &x, &y, &xs,
|
||
&ys); // 把屏幕上的绝对坐标转化为窗口的相对坐标
|
||
m.x_move = t.x[0] - x;
|
||
m.y_move = t.y[0] - y;
|
||
mymemcpy(msg.data.p, &m, sizeof(WIN_MoveStruct));
|
||
WIN_SendMsg(0, broad->win_old, &msg);
|
||
}
|
||
}
|
||
}
|
||
} // if (win_move=WIN_FindPrent(win_old,win),win_move!=0)
|
||
} // if (t_old.pressNum&&t.pressNum)
|
||
else {
|
||
// 触摸没有移动并且没有触发长按
|
||
if (broad->Touch_long && (broad->Touch_long < WIN_LONGTOUCH_CHECK)) {
|
||
// 发送短按消息
|
||
msg.msg = WIN_MSG_MOVE;
|
||
msg.data.p = mymalloc(sizeof(WIN_MoveStruct));
|
||
m.moveType = MOVE_DATA_SHORT;
|
||
int x, y, xs, ys;
|
||
WIN_GetWinPosOnLcd(broad->win, &x, &y, &xs,
|
||
&ys); // 把屏幕上的绝对坐标转化为窗口的相对坐标
|
||
m.x_move = t.x[0] - x;
|
||
m.y_move = t.y[0] - y;
|
||
mymemcpy(msg.data.p, &m, sizeof(WIN_MoveStruct));
|
||
WIN_SendMsg(0, broad->win_old, &msg);
|
||
}
|
||
// 屏幕松开了,长按检测复位
|
||
broad->Touch_long = 0;
|
||
// 屏幕松开了,窗口间滑动复位
|
||
broad->win_old = 0;
|
||
if (t.pressNum == 0) {
|
||
// 屏幕松开了
|
||
msg.msg = WIN_MSG_MOVE;
|
||
msg.data.p = mymalloc(sizeof(WIN_MoveStruct));
|
||
m.moveType = MOVE_DATA_TOUCHOUT;
|
||
int x, y, xs, ys;
|
||
WIN_GetWinPosOnLcd(broad->win, &x, &y, &xs,
|
||
&ys); // 把屏幕上的绝对坐标转化为窗口的相对坐标
|
||
m.x_move = t.x[0] - x;
|
||
m.y_move = t.y[0] - y;
|
||
mymemcpy(msg.data.p, &m, sizeof(WIN_MoveStruct));
|
||
WIN_SendMsg(0, broad->win, &msg);
|
||
} else {
|
||
// 松开屏幕后的第一次点击
|
||
msg.msg = WIN_MSG_MOVE;
|
||
msg.data.p = mymalloc(sizeof(WIN_MoveStruct));
|
||
m.moveType = MOVE_DATA_TOUCHIN;
|
||
int x, y, xs, ys;
|
||
WIN_GetWinPosOnLcd(broad->win, &x, &y, &xs,
|
||
&ys); // 把屏幕上的绝对坐标转化为窗口的相对坐标
|
||
m.x_move = t.x[0] - x;
|
||
m.y_move = t.y[0] - y;
|
||
mymemcpy(msg.data.p, &m, sizeof(WIN_MoveStruct));
|
||
WIN_SendMsg(0, broad->win, &msg);
|
||
}
|
||
}
|
||
broad->t_old.x[0] = t.x[0];
|
||
broad->t_old.y[0] = t.y[0];
|
||
broad->t_old.pressNum = t.pressNum;
|
||
|
||
// 发送触控消息
|
||
WIN_SendTouchMsg(broad->win, t.x[0], t.y[0]);
|
||
} // if (win)
|
||
else {
|
||
if (broad->t_old.pressNum == 0 && t.pressNum) {
|
||
// 触摸不在指定窗口内
|
||
msg.msg = WIN_MSG_MOVE;
|
||
msg.data.p = mymalloc(sizeof(WIN_MoveStruct));
|
||
m.moveType = MOVE_DATA_OUTSIDE;
|
||
m.x_move = 0;
|
||
m.y_move = 0;
|
||
mymemcpy(msg.data.p, &m, sizeof(WIN_MoveStruct));
|
||
WIN_SendMsg(0, base, &msg);
|
||
}
|
||
broad->t_old.x[0] = t.x[0];
|
||
broad->t_old.y[0] = t.y[0];
|
||
broad->t_old.pressNum = t.pressNum;
|
||
}
|
||
} // while (QUEUE_Out (&g_win_touchQueue,&t)==1)
|
||
|
||
return have_msg;
|
||
}
|
||
|
||
// 广播按键消息
|
||
int WIN_KeyMsgBroad(WIN_WindowStruct *base) {
|
||
int have_msg = 0; // 返回值
|
||
WIN_TouchStruct t = {0};
|
||
WIN_KeyStruct k = {0};
|
||
WIN_MoveStruct m = {0};
|
||
WIN_MsgStruct msg = {0};
|
||
WIN_MsgBroadStruct *broad = &WIN_GetWinStruct()->msgBroad;
|
||
while (QUEUE_Out(&WIN_GetWinStruct()->keyQueue, &k) == 1) {
|
||
have_msg = 1;
|
||
WIN_WindowStruct *win_key = 0;
|
||
if (win_key = WIN_FindTopWin(base), win_key != 0) {
|
||
// 按键没有松开过
|
||
if ((broad->k_old.key == k.key) && k.key) {
|
||
// 按键是按下的
|
||
if (k.state) {
|
||
if (broad->Key_long < WIN_LONGTOUCH_CHECK) {
|
||
broad->Key_long++;
|
||
if (broad->Key_long >= WIN_LONGTOUCH_CHECK) {
|
||
// 触发长按
|
||
k.longPress |= k.key;
|
||
k.shortPress = 0;
|
||
k.firstPress = 0;
|
||
k.unPress = 0;
|
||
WIN_SendKeyMsg(win_key, &k);
|
||
} else {
|
||
// 按键按下中
|
||
k.longPress = 0;
|
||
k.shortPress = 0;
|
||
k.firstPress = 0;
|
||
k.unPress = 0;
|
||
WIN_SendKeyMsg(win_key, &k);
|
||
}
|
||
} else {
|
||
// 已经触发过长按,按键还没有松开,
|
||
broad->Key_long++;
|
||
if (broad->Key_long % WIN_LONGTOUCH_CHECK == 0) {
|
||
k.longPressNum = broad->Key_long / WIN_LONGTOUCH_CHECK;
|
||
if (k.longPressNum != broad->k_old.longPressNum) {
|
||
// 再次触发长按
|
||
broad->k_old.longPressNum = k.longPressNum;
|
||
k.longPress |= k.key;
|
||
k.shortPress = 0;
|
||
k.firstPress = 0;
|
||
k.unPress = 0;
|
||
WIN_SendKeyMsg(win_key, &k);
|
||
}
|
||
}
|
||
}
|
||
} // if (k.state)
|
||
else {
|
||
// 按键从按下变为松开,并且没有触发长按
|
||
if (broad->Key_long < WIN_LONGTOUCH_CHECK) {
|
||
// 短按
|
||
k.shortPress |= k.key;
|
||
k.longPress = 0;
|
||
k.firstPress = 0;
|
||
k.unPress = 0;
|
||
WIN_SendKeyMsg(win_key, &k);
|
||
} else {
|
||
// 松开了按键,并且触发过长按
|
||
// 长按触发次数清零
|
||
broad->k_old.longPressNum = 0;
|
||
}
|
||
k.unPress = k.key;
|
||
k.firstPress = 0;
|
||
k.longPress = 0;
|
||
k.shortPress = 0;
|
||
WIN_SendKeyMsg(win_key, &k);
|
||
broad->Key_long = 0;
|
||
k.key = 0;
|
||
}
|
||
} // if ((k_old.key==k.key)&&k.key)
|
||
else if ((broad->k_old.state == 0) && (k.state)) {
|
||
// 按键第一次按下
|
||
broad->Key_long = 0;
|
||
k.firstPress = k.key;
|
||
k.longPress = 0;
|
||
k.shortPress = 0;
|
||
WIN_SendKeyMsg(win_key, &k);
|
||
}
|
||
broad->k_old.key = k.key;
|
||
broad->k_old.state = k.state;
|
||
} // if (win_key =WIN_FindTopWin(win),win_key!=0)
|
||
}
|
||
return have_msg;
|
||
}
|
||
|
||
// 广播按键和触屏消息,处理过消息,返回1,否则返回0
|
||
int WIN_MsgBroad(WIN_WindowStruct *base) {
|
||
return WIN_KeyMsgBroad(base) | WIN_TouchMsgBroad(base);
|
||
}
|
||
|
||
// 窗口运行
|
||
int WIN_Working(WIN_WindowStruct *win) {
|
||
|
||
WIN_MoveStruct *m = 0;
|
||
RECT_Struct r = {0};
|
||
int run = 0; // 此项为1,则消息没处理完
|
||
// 自己先处理消息
|
||
WIN_MsgStruct msg = {0};
|
||
win->msgLoopEnter++;
|
||
WIN_WindowStruct *winCurrent_old = WIN_GetWinStruct()->winCurrent;
|
||
WIN_GetWinStruct()->winCurrent = win;
|
||
void *msgData = 0;
|
||
while (QUEUE_Out(&win->winMsgQueue, &msg)) {
|
||
run = 1;
|
||
// 先复制一份消息,然后释放消息指针,防止在消息循环中执行窗口删除操作之后产生野指针
|
||
msgData = msg.data.p;
|
||
|
||
switch (msg.msg) {
|
||
// 这些类型的消息在交给窗口处理之前要先设置好环境
|
||
case WIN_MSG_PAINT:
|
||
mymemcpy(&r, &win->invaldRect, sizeof(RECT_Struct));
|
||
|
||
// 窗口不需要重绘
|
||
if (win->invald == 0)
|
||
continue;
|
||
|
||
// 同时窗口位置的子窗口也要重绘
|
||
for (int i = win->chidWinNum; i > 0; i--) {
|
||
// 判断这些窗口是否被遮挡
|
||
// 设置为窗口相对坐标
|
||
RECT_Struct ret = {0};
|
||
RECT_Struct r1 = {0};
|
||
r1.x = win->chidWin[i - 1]->x;
|
||
r1.y = win->chidWin[i - 1]->y;
|
||
r1.x_size = win->chidWin[i - 1]->x_size;
|
||
r1.y_size = win->chidWin[i - 1]->y_size;
|
||
if (POS_RectIntersection(&ret, &r1, &r)) {
|
||
ret.x -= win->chidWin[i - 1]->x;
|
||
ret.y -= win->chidWin[i - 1]->y; // 减去窗口定位坐标,2020.2.26
|
||
WIN_SetInvalidRect(win->chidWin[i - 1], ret.x, ret.y, ret.x_size,
|
||
ret.y_size);
|
||
if (POS_RectSub(&r, &r, &r1) == 0) {
|
||
// 重绘区为0,余下子窗口无需重绘
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 顶端窗口需要重绘
|
||
WIN_TopWinPaint(win);
|
||
|
||
// 清除窗口重绘标志
|
||
win->invald = 0;
|
||
// 需要重绘的窗口-1
|
||
if (WIN_GetWinStruct()->numOfWindowToPrint)
|
||
WIN_GetWinStruct()->numOfWindowToPrint--;
|
||
else
|
||
while (1)
|
||
; // 不可能运行到的位置
|
||
|
||
// 绘图区已经不存在,无需绘制
|
||
if (r.x_size <= 0 || r.y_size <= 0)
|
||
continue;
|
||
|
||
// 设置绘图区域
|
||
WIN_EnterPaint(win);
|
||
// 设置无效区
|
||
WIN_SetWinInvalidRect(win, &r);
|
||
|
||
// 进入绘制缓冲区
|
||
WIN_GetWinStruct()->lcd->enterLayerBuff();
|
||
break; // case WIN_MSG_PAINT:
|
||
} // switch (msg.msg)
|
||
|
||
// 运行窗口消息循环
|
||
win->msgLoop(win, &msg);
|
||
|
||
switch (msg.msg) {
|
||
// 这些类型的消息在发送时使用了malloc,这里释放掉
|
||
case WIN_MSG_KEY:
|
||
case WIN_MSG_TOUCH:
|
||
case WIN_MSG_EXTMSG:
|
||
myfree(msgData);
|
||
break;
|
||
case WIN_MSG_MOVE:
|
||
m = msg.data.p;
|
||
switch (m->moveType) {
|
||
// 把点击的窗口调整到最前面
|
||
case MOVE_DATA_TOUCHIN:
|
||
if (win->baseWin) {
|
||
if (win != win->baseWin->chidWin[win->baseWin->chidWinNum - 1]) {
|
||
// 不是顶端窗口,重绘整个窗口
|
||
if (WIN_SetChidWinTop(win->baseWin, win) == 0)
|
||
WIN_SetInvalid(win);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
myfree(msgData);
|
||
break; // case WIN_MSG_MOVE:
|
||
// 绘图操作已经完成,刷新屏幕
|
||
case WIN_MSG_PAINT:
|
||
if (WIN_GetWinStruct()->numOfWindowToPrint == 0) // LCD_ExitLayerBuff();
|
||
WIN_GetWinStruct()->lcd->exitLayerBuff();
|
||
break;
|
||
// 这些类型的消息需要绘制背景
|
||
case WIN_MSG_DELETE:
|
||
if (win->baseWin) {
|
||
// 父窗口要重绘
|
||
// WIN_SetInvalidRect(win->baseWin,win->x,win->y,win->x_size,win->y_size);
|
||
} // if (win->baseWin)
|
||
break;
|
||
} // switch (msg.msg)
|
||
} // while (QUEUE_Out (&win->winMsgQueue,&msg))
|
||
|
||
// 然后子窗口处理消息
|
||
for (int i = 0; i < win->chidWinNum; i++) {
|
||
run |= WIN_Working(win->chidWin[i]);
|
||
}
|
||
|
||
WIN_GetWinStruct()->winCurrent = winCurrent_old;
|
||
if (win->msgLoopEnter)
|
||
win->msgLoopEnter--;
|
||
// 这是最后一层消息循环,并且窗口已销毁
|
||
if ((win->msgLoopEnter == 0) && (win->memFree)) {
|
||
win->memFree(win);
|
||
}
|
||
|
||
return run;
|
||
}
|
||
|
||
// 以非阻塞方式运行所有窗口
|
||
void WIN_Delay(int ms) {
|
||
WIN_GetWinStruct()->delay_ms = ms;
|
||
WIN_Delay_ms(WIN_GetWinStruct()->delay_ms);
|
||
if (WIN_GetWinStruct()->runCallBack)
|
||
WIN_GetWinStruct()->runCallBack();
|
||
WIN_TimerWork();
|
||
while (WIN_MsgBroad(WIN_GetBaseWindow()))
|
||
;
|
||
while (WIN_Working(WIN_GetBaseWindow()))
|
||
;
|
||
}
|
||
|
||
// 以阻塞方式运行指定窗口
|
||
int WIN_RunBlock(WIN_WindowStruct *win) {
|
||
WIN_WindowStruct *win_save = win;
|
||
|
||
// 是否超出了最大嵌套层数
|
||
if (WIN_GetWinStruct()->BlockWinNum >= WIN_BLOCK_MAXNUM) {
|
||
win->deleteWindow(win);
|
||
return -1;
|
||
}
|
||
|
||
// 窗口栈入栈
|
||
for (int i = WIN_GetWinStruct()->BlockWinNum; i > 0; i--) {
|
||
WIN_GetWinStruct()->BlockWin[i] = WIN_GetWinStruct()->BlockWin[i - 1];
|
||
}
|
||
WIN_GetWinStruct()->BlockWin[0] = win;
|
||
WIN_GetWinStruct()->BlockWinNum++;
|
||
|
||
// 开始运行
|
||
while (WIN_GetWinStruct()->BlockWin[0] == win_save) {
|
||
WIN_Delay_ms(WIN_GetWinStruct()->delay_ms);
|
||
if (WIN_GetWinStruct()->runCallBack)
|
||
WIN_GetWinStruct()->runCallBack();
|
||
WIN_TimerWork();
|
||
while (WIN_MsgBroad(WIN_GetWinStruct()->BlockWin[0]))
|
||
;
|
||
// WIN_Working (WIN_GetBaseWindow());
|
||
while (WIN_Working(WIN_GetBaseWindow()))
|
||
;
|
||
}
|
||
|
||
// 返回窗口的返回值
|
||
return WIN_GetWinStruct()->BlockWinReturn;
|
||
}
|
||
|
||
// 把窗口设置为无效
|
||
void WIN_SetInvalid(WIN_WindowStruct *win) {
|
||
WIN_SetInvalidRect(win, 0, 0, win->x_size, win->y_size);
|
||
}
|
||
|
||
// 当窗口是最顶窗口时,设置为无效
|
||
void WIN_SetInvalidWhenTop(WIN_WindowStruct *win) {
|
||
WIN_SetInvalidRectWhenTop(win, 0, 0, win->x_size, win->y_size);
|
||
}
|
||
|
||
// 把窗口指定区域设置为无效,以窗口的坐标为原点
|
||
void WIN_SetInvalidRect(WIN_WindowStruct *win, int x, int y, int x_size,
|
||
int y_size) {
|
||
RECT_Struct *r;
|
||
if (win->memFree)
|
||
return; // 不给已销毁的窗口发消息
|
||
// 发送paint消息
|
||
WIN_MsgStruct msg = {0};
|
||
msg.msg = WIN_MSG_PAINT;
|
||
r = mymalloc(sizeof(RECT_Struct));
|
||
|
||
WIN_GetWinPosOnLcd(win, &r->x, &r->y, &r->x_size, &r->y_size);
|
||
RECT_Struct r_win = {0};
|
||
r_win.x = r->x;
|
||
r_win.y = r->y;
|
||
|
||
// 设置无效区在窗口范围内
|
||
WIN_WindowStruct *t = win;
|
||
RECT_Struct r_now = {0};
|
||
do {
|
||
WIN_GetWinPosOnLcd(t, &r_now.x, &r_now.y, &r_now.x_size, &r_now.y_size);
|
||
|
||
POS_RectIntersection(r, r, &r_now);
|
||
t = t->baseWin;
|
||
} while (t);
|
||
r->x -= r_win.x;
|
||
r->y -= r_win.y;
|
||
RECT_Struct r_in = {0};
|
||
r_in.x = x;
|
||
r_in.y = y;
|
||
r_in.x_size = x_size;
|
||
r_in.y_size = y_size;
|
||
POS_RectIntersection(r, r, &r_in);
|
||
|
||
if (win->invald == 0) {
|
||
WIN_SendMsg(0, win, &msg);
|
||
mymemcpy(&win->invaldRect, r, sizeof(RECT_Struct));
|
||
win->invald = 1;
|
||
WIN_GetWinStruct()->numOfWindowToPrint++; // 需要绘制的窗口加1
|
||
} else {
|
||
POS_RectContain(&win->invaldRect, &win->invaldRect, r);
|
||
}
|
||
|
||
myfree(r);
|
||
}
|
||
|
||
// 当窗口是最顶窗口时,设置为无效
|
||
void WIN_SetInvalidRectWhenTop(WIN_WindowStruct *win, int x, int y, int x_size,
|
||
int y_size) {
|
||
if (WIN_FindBlock(win) == 0) {
|
||
WIN_SetInvalidRect(win, x, y, x_size, y_size);
|
||
}
|
||
}
|
||
|
||
// 窗口移动
|
||
void WIN_Move(WIN_WindowStruct *win, int x_move, int y_move) {
|
||
|
||
RECT_Struct r1 = {0};
|
||
RECT_Struct r2 = {0};
|
||
r1.x = win->x;
|
||
r1.y = win->y;
|
||
r1.x_size = win->x_size;
|
||
r1.y_size = win->y_size;
|
||
mymemcpy(&r2, &r1, sizeof(RECT_Struct));
|
||
win->x += x_move;
|
||
win->y += y_move;
|
||
r2.x = win->x;
|
||
r2.y = win->y;
|
||
|
||
POS_RectContain(&r1, &r1, &r2);
|
||
|
||
if (win->baseWin)
|
||
WIN_SetInvalidRect(win->baseWin, r1.x, r1.y, r1.x_size, r1.y_size);
|
||
|
||
// WIN_SetInvalid(win);
|
||
}
|
||
|
||
// 设置窗口坐标
|
||
void WIN_SetPos(WIN_WindowStruct *win, int x, int y) {
|
||
RECT_Struct r1 = {0};
|
||
RECT_Struct r2 = {0};
|
||
r1.x = win->x;
|
||
r1.y = win->y;
|
||
r1.x_size = win->x_size;
|
||
r1.y_size = win->y_size;
|
||
mymemcpy(&r2, &r1, sizeof(RECT_Struct));
|
||
win->x = x;
|
||
win->y = y;
|
||
r2.x = win->x;
|
||
r2.y = win->y;
|
||
|
||
POS_RectContain(&r1, &r1, &r2);
|
||
|
||
if (win->baseWin)
|
||
WIN_SetInvalidRect(win->baseWin, r1.x, r1.y, r1.x_size, r1.y_size);
|
||
|
||
// WIN_SetInvalid(win);
|
||
}
|
||
|
||
// 设置窗口尺寸
|
||
void WIN_SetSize(WIN_WindowStruct *win, int x_size, int y_size) {
|
||
RECT_Struct r1 = {0};
|
||
RECT_Struct r2 = {0};
|
||
r1.x = win->x;
|
||
r1.y = win->y;
|
||
r1.x_size = win->x_size;
|
||
r1.y_size = win->y_size;
|
||
mymemcpy(&r2, &r1, sizeof(RECT_Struct));
|
||
win->x_size = x_size;
|
||
win->y_size = y_size;
|
||
r2.x_size = win->x_size;
|
||
r2.y_size = win->y_size;
|
||
|
||
POS_RectContain(&r1, &r1, &r2);
|
||
|
||
if (win->baseWin)
|
||
WIN_SetInvalidRect(win->baseWin, r1.x, r1.y, r1.x_size, r1.y_size);
|
||
|
||
// WIN_SetInvalid(win);
|
||
}
|