#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) { //调用子窗口的销毁函数 // for (int i=0;ichidWinNum;i++) // { // (win->chidWin[i])->deleteWindow(win->chidWin[i]); // } while(win->chidWinNum) { (win->chidWin[0])->deleteWindow(win->chidWin[0]); } //在父窗口的窗口列表中删除 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 (iid==id) {return win;} else { for (int i=win->chidWinNum;i>0;i--) { if (ret=WIN_GetWindowStructById(win->chidWin[i-1],id),ret) { return ret; } } } return ret; } //从子窗口列表中删除指定窗口 int WIN_DelFromChidList (WIN_WindowStruct *win,WIN_WindowStruct *chidWin) { for (int i=0;ichidWinNum;i++) { if (win->chidWin[i]==chidWin) { win->chidWin[i]=0;//删除这一个 for (;ichidWinNum-1;i++)//后面的向前移 { win->chidWin[i]=win->chidWin[i+1]; } win->chidWinNum--;//子窗口个数减一 return 0; } } return -1; } //把指定子窗口设置为最高 int WIN_SetChidWinTop (WIN_WindowStruct *win,WIN_WindowStruct *chidWin) { WIN_WindowStruct *t=0; for (int i=0;ichidWinNum;i++) { if (win->chidWin[i]==chidWin) { t=win->chidWin[i]; win->chidWin[i]=0;//删除这一个 for (;ichidWinNum;i++)//后面的向前移 { win->chidWin[i]=win->chidWin[i+1]; } win->chidWin[win->chidWinNum-1]=t;//设置为最后一个 return 0; } } return -1; } //添加窗口到子窗口列表中 int WIN_AddToChidList (WIN_WindowStruct *win,WIN_WindowStruct *chidWin) { if (win->chidWinNumchidWinMaxSize) { win->chidWin[win->chidWinNum]=chidWin; win->chidWinNum++; return 0; } else { return -1; } } //判断目标窗口是不是子窗口,是返回1 int WIN_CheckChidWin (WIN_WindowStruct *win,WIN_WindowStruct *chid) { for (int i=0;ichidWinNum;i++) { if (win->chidWin[i]==chid) return 1; } 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;ig_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; if (win&&(win->chidWinNum)) { for (int i=win->chidWinNum;i>0;i--) { ret=WIN_FindTopWin (win->chidWin[i-1]); if (ret) return ret; } } //本窗口接受消息处理并且不是子窗口 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; //该窗口被遮挡只可能是其子窗口和其同辈父辈窗口 for (int i=0;ichidWinNum;i++) { top=win->chidWin[i]; 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; } } while(base) { for (int i=base->chidWinNum;i>0;i--) { top=base->chidWin[i-1]; 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; } } base=base->baseWin; } return 0; } //屏蔽和接触屏蔽子窗口的按键和键盘消息 int WIN_SetChildWinkeyShield (WIN_WindowStruct *win,int power) { for (int i=win->chidWinNum-1;i>=0;i--) { win->chidWin[i]->keyShield=power; } 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_GetWinPosOnLcd (win,&win_x_s,&win_y_s,&x_size,&y_size); WIN_WindowStruct *t=0; if (((x>=win_x_s)&&(x=win_y_s)&&(ykeyShield==0)) { //在本窗口内,查找是否有子窗口 //从最后开始查找,因为越最后的显示在越前面 for (int i=win->chidWinNum-1;i>=0;i--) { t=WIN_FindTopWinByPos (win->chidWin[i],x,y); if (t) { ret=t;//找到了最前面的窗口 break; } } } 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(); if (strcmp (win->winTitle,title)==0) { ret=win; } else { for (int i=0;ichidWinNum;i++) { if (ret=WIN_GetWinByTitle (win->chidWin[i],title),ret) break; } } 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;icolor); // 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((yysize)&&(xxsize)) { 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; }