#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_WindowStruct *prev; WIN_WindowStruct *next; 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; // 同时窗口位置的子窗口也要重绘 prev = WIN_GetLastChidWin(win); for (int i = win->chidWinNum; i > 0; i--) { // 判断这些窗口是否被遮挡 // 设置为窗口相对坐标 RECT_Struct ret = {0}; RECT_Struct r1 = {0}; r1.x = prev->x; r1.y = prev->y; r1.x_size = prev->x_size; r1.y_size = prev->y_size; if (POS_RectIntersection(&ret, &r1, &r)) { ret.x -= prev->x; ret.y -= prev->y; // 减去窗口定位坐标,2020.2.26 WIN_SetInvalidRect(prev, ret.x, ret.y, ret.x_size, ret.y_size); if (POS_RectSub(&r, &r, &r1) == 0) { // 重绘区为0,余下子窗口无需重绘 break; } } prev = prev->prev; } // 顶端窗口需要重绘 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->chid->prev) { // 不是顶端窗口,重绘整个窗口 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)) // 然后子窗口处理消息 next = win->chid; while(next) { run |= WIN_Working(next); next = next->next; } 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); }