/** * @brief 画矩形并填充. * @param x0:矩形左上角 y0:矩形左上角 x1:矩形右下角 y1:矩形右下角 color:显示的颜色. * @retval None. * @verify . */ void GUI_RectangleFill(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, TCOLOR color) { uint32_t i; /* 先找出矩形左上角与右下角的两个点,保存在(x0,y0),(x1,y1) */ if(x0>x1){ i = x0; x0 = x1; x1 = i; } if(y0>y1){ i = y0; y0 = y1; y1 = i; } /* 判断是否只是直线 */ if(y0==y1){ GUI_HLine(x0, y0, x1, color); return; } if(x0==x1) { GUI_RLine(x0, y0, y1, color); return; } while(y0<=y1){ GUI_HLine(x0, y0, x1, color); // 当前画水平线 y0++; // 下一行 } }
/** * @brief 画矩形. * @param x0:矩形左上角 y0:矩形左上角 x1:矩形右下角 y1:矩形右下角 color:显示的颜色. * @retval None. * @verify . */ void GUI_Rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, TCOLOR color) { GUI_HLine(x0, y0, x1, color); GUI_HLine(x0, y1, x1, color); GUI_RLine(x0, y0, y1, color); GUI_RLine(x1, y0, y1, color); }
/**************************************************************************** * 名称:GUI_WindowsDraw() * 功能:显示窗口。根据提供的窗口参数进行画窗口。 * 入口参数:win 窗口句柄 * 出口参数:返回0表示操作失败,返回1表示操作成功 ****************************************************************************/ uint8 GUI_WindowsDraw(WINDOWS *win) { uint8 *str; int32 bak, bak1, bak2; /* 参数过滤,若窗口起出范围,则返回0 */ if( ( (win->with)<20 ) || ( (win->hight)<20 ) ) return(0); // 宽度、高度检查,限制最小窗口 if( (win->x + win->with ) > GUI_LCM_XMAX ) return(0); // 窗口宽度是否溢出 if( (win->y + win->hight ) > GUI_LCM_YMAX ) return(0); // 窗口高度是否溢出 /* 开始画窗口 */ GUI_RectangleFill(win->x, win->y, win->x + win->with - 1, win->y + win->hight - 1, back_color); GUI_Rectangle(win->x, win->y, win->x + win->with - 1, win->y + win->hight - 1, disp_color); // 画窗口 GUI_HLine(win->x, win->y + 12, win->x + win->with - 1, disp_color); // 画标题目栏 GUI_RLine(win->x + 12, win->y, win->y + 12, disp_color); // 画关闭窗号按钮 GUI_Line(win->x, win->y, win->x + 12, win->y + 12, disp_color); GUI_Line(win->x + 12, win->y, win->x, win->y + 12, disp_color); /* 写标题 */ if( win->title != NULL ) { str = win->title; bak = win->x + 15; bak1 = win->y + 3; bak2 = win->x + win->with -1; while(1) { if( (bak+8) > bak2 ) break; // 判断标题是否溢出 if(*str=='\0') break; // 判断字符串是否结束 GUI_PutChar(bak, bak1, *str++); // 显示标题 bak += 6; } } /* 写状态栏 */ if( win->state != NULL ) { if( win->hight < 60) return(0); // 判断是否可以画状态栏 /* 画状态栏 */ GUI_HLine(win->x, win->y + win->hight - 11, win->x + win->with - 1, disp_color); str = win->state; bak = win->x + 3; bak1 = win->y + win->hight - 9; bak2 = win->x + win->with -1; while(1) { if( (bak+8) > bak2 ) break; // 判断标题是否溢出 if(*str=='\0') break; // 判断字符串是否结束 GUI_PutChar(bak, bak1, *str++); // 显示标题 bak += 6; } } return(1); }
/**************************************************************************** * 名称:GUI_MMenuDraw() * 功能:显示主菜单,加上边框。 * 入口参数:men 主菜单句柄 * 出口参数:返回0表示操作失败,返回1表示操作成功 ****************************************************************************/ uint8 GUI_MMenuDraw(MMENU *men) { WINDOWS *mwin; uint8 i; uint8 xx; /* 参数过滤 */ if( (men->no)==0 ) return(0); mwin = men->win; // 取得窗口句柄 /* 判断是否可以显示主菜单 */ if( (mwin->hight)<50 ) return(0); if( (mwin->with)<50 ) return(0); /* 画菜单条,并显示菜主单 */ GUI_HLine(mwin->x, mwin->y + 22, mwin->x + mwin->with - 1, disp_color); xx = mwin->x; for(i=0; i<(men->no); i++) { if( (xx+MMENU_WIDTH) > (mwin->x + mwin->with) ) return(0); GUI_PutNoStr(xx+2, mwin->y + 14, men->str[i], 4); // 书写主菜单文字 xx += MMENU_WIDTH; GUI_RLine(xx, mwin->y + 12, mwin->y + 22, disp_color); // 显示主菜单分界线 } return(1); }
/**************************************************************************** * 名称:GUI_SMenuHide() * 功能:消隐子菜单项。 * 入口参数:men 子菜单句柄 * 出口参数:返回0表示操作失败,返回1表示操作成功 ****************************************************************************/ uint8 GUI_SMenuHide(SMENU *men) { WINDOWS *mwin; uint8 xx, yy; mwin = men->win; /* 判断是否可以显示主菜单 */ if( (mwin->hight)<50 ) return(0); if( (mwin->with)<50 ) return(0); /* 画菜子单项。下拉子菜单,以向左下拉为原则,若右边溢出则以右下拉显示 */ xx = mwin->x; xx += (men->mmenu_no)*MMENU_WIDTH; yy = mwin->y + 22; yy += (men->no) * 11 + 2; if( (xx+SMENU_WIDTH) <= (mwin->x + mwin->with - 1) ) { /* 以左下拉为原则显示子菜单 */ if( (men->mmenu_no) == 0 ) { GUI_RectangleFill(xx+1, mwin->y + 22+1, xx+SMENU_WIDTH, yy, back_color); } else { GUI_RectangleFill(xx, mwin->y + 22+1, xx+SMENU_WIDTH, yy, back_color); } GUI_HLine(xx+1, mwin->y + 22, xx+MMENU_WIDTH-1, disp_color); } else { /* 以右下拉为原则 */ if( (xx+MMENU_WIDTH) == (mwin->x + mwin->with - 1) ) { GUI_RectangleFill(xx-(SMENU_WIDTH-MMENU_WIDTH), mwin->y + 22+1, xx+MMENU_WIDTH-1, yy, back_color); } else { GUI_RectangleFill(xx-(SMENU_WIDTH-MMENU_WIDTH), mwin->y + 22+1, xx+MMENU_WIDTH, yy, back_color); } GUI_HLine(xx+1, mwin->y + 22, xx+MMENU_WIDTH-1, disp_color); } return(1); }
/**************************************************************************** * 名称:GUI_MMenuNSelect() * 功能:取消当前主菜单,去除下划线。 * 入口参数:men 主菜单句柄 * no 所选的主菜单项 * 出口参数:无 ****************************************************************************/ void GUI_MMenuNSelect(MMENU *men, uint8 no) { WINDOWS *mwin; uint8 xx; /* 参数过滤 */ if( (men->no)==0 ) return; if( no>(men->no) ) return; mwin = men->win; // 取得窗口句柄 /* 判断是否可以显示主菜单 */ if( (mwin->hight)<50 ) return; if( (mwin->with)<50 ) return; /* 显示下划线 */ xx = mwin->x + no*MMENU_WIDTH; GUI_HLine(xx+1, mwin->y + 22-1, xx+MMENU_WIDTH- 1, back_color); }
/**************************************************************************** * 名称:GUI_MenuIcoDraw() * 功能:显示图标菜单。 * 入口参数:ico 图标菜单句柄 * 出口参数:返回0表示操作失败,返回1表示操作成功 ****************************************************************************/ uint8 GUI_MenuIcoDraw(MENUICO *ico) { /* 参数过滤 */ if( ( (ico->x)<5 ) || ( (ico->x)>(GUI_LCM_XMAX-37 ) ) ) return(0); // 显示起始地址判断 if( ( (ico->icodat)==NULL ) || ( (ico->title)==NULL ) ) return(0); // 显示数据内容判断 GUI_LoadPic(ico->x, ico->y, (uint8 *) ico->icodat, 32, 32); // 显示ICO图 GUI_HLine(ico->x-5, ico->y+32, ico->x+37, back_color); // 显示一空行 if( (ico->state)==0 ) { GUI_LoadPic(ico->x-5, ico->y+33, (uint8 *) ico->title, 42, 13); } else { GUI_LoadPic1(ico->x-5, ico->y+33, (uint8 *) ico->title, 42, 13); } return(1); }
/**************************************************************************** * 名称:GUI_CircleFill() * 功能:指定圆心位置及半径,画圆并填充,填充色与边框色一样。 * 入口参数: x0 圆心的x坐标值 * y0 圆心的y坐标值 * r 圆的半径 * color 填充颜色 * 出口参数:无 * 说明:操作失败原因是指定地址超出有效范围。 ****************************************************************************/ void GUI_CircleFill(uint32_t x0, uint32_t y0, uint32_t r, TCOLOR color) { int32_t draw_x0, draw_y0; // 刽图点坐标变量 int32_t draw_x1, draw_y1; int32_t draw_x2, draw_y2; int32_t draw_x3, draw_y3; int32_t draw_x4, draw_y4; int32_t draw_x5, draw_y5; int32_t draw_x6, draw_y6; int32_t draw_x7, draw_y7; int32_t fill_x0, fill_y0; // 填充所需的变量,使用垂直线填充 int32_t fill_x1; int32_t xx, yy; // 画圆控制变量 int32_t di; // 决策变量 /* 参数过滤 */ if(0==r) return; /* 计算出4个特殊点(0、90、180、270度),进行显示 */ draw_x0 = draw_x1 = x0; draw_y0 = draw_y1 = y0 + r; if(draw_y0<GUI_LCM_YMAX) { GUI_Point(draw_x0, draw_y0, color); // 90度 } draw_x2 = draw_x3 = x0; draw_y2 = draw_y3 = y0 - r; if(draw_y2>=0) { GUI_Point(draw_x2, draw_y2, color); // 270度 } draw_x4 = draw_x6 = x0 + r; draw_y4 = draw_y6 = y0; if(draw_x4<GUI_LCM_XMAX) { GUI_Point(draw_x4, draw_y4, color); // 0度 fill_x1 = draw_x4; } else { fill_x1 = GUI_LCM_XMAX; } fill_y0 = y0; // 设置填充线条起始点fill_x0 fill_x0 = x0 - r; // 设置填充线条结束点fill_y1 if(fill_x0<0) fill_x0 = 0; GUI_HLine(fill_x0, fill_y0, fill_x1, color); draw_x5 = draw_x7 = x0 - r; draw_y5 = draw_y7 = y0; if(draw_x5>=0) { GUI_Point(draw_x5, draw_y5, color); // 180度 } if(1==r) return; /* 使用Bresenham法进行画圆 */ di = 3 - 2*r; // 初始化决策变量 xx = 0; yy = r; while(xx<yy) { if(di<0) { di += 4*xx + 6; } else { di += 4*(xx - yy) + 10; yy--; draw_y0--; draw_y1--; draw_y2++; draw_y3++; draw_x4--; draw_x5++; draw_x6--; draw_x7++; } xx++; draw_x0++; draw_x1--; draw_x2++; draw_x3--; draw_y4++; draw_y5++; draw_y6--; draw_y7--; /* 要判断当前点是否在有效范围内 */ if( (draw_x0<=GUI_LCM_XMAX)&&(draw_y0>=0) ) { GUI_Point(draw_x0, draw_y0, color); } if( (draw_x1>=0)&&(draw_y1>=0) ) { GUI_Point(draw_x1, draw_y1, color); } /* 第二点水直线填充(下半圆的点) */ if(draw_x1>=0) { /* 设置填充线条起始点fill_x0 */ fill_x0 = draw_x1; /* 设置填充线条起始点fill_y0 */ fill_y0 = draw_y1; if(fill_y0>GUI_LCM_YMAX) fill_y0 = GUI_LCM_YMAX; if(fill_y0<0) fill_y0 = 0; /* 设置填充线条结束点fill_x1 */ fill_x1 = x0*2 - draw_x1; if(fill_x1>GUI_LCM_XMAX) fill_x1 = GUI_LCM_XMAX; GUI_HLine(fill_x0, fill_y0, fill_x1, color); } if( (draw_x2<=GUI_LCM_XMAX)&&(draw_y2<=GUI_LCM_YMAX) ) { GUI_Point(draw_x2, draw_y2, color); } if( (draw_x3>=0)&&(draw_y3<=GUI_LCM_YMAX) ) { GUI_Point(draw_x3, draw_y3, color); } /* 第四点垂直线填充(上半圆的点) */ if(draw_x3>=0) { /* 设置填充线条起始点fill_x0 */ fill_x0 = draw_x3; /* 设置填充线条起始点fill_y0 */ fill_y0 = draw_y3; if(fill_y0>GUI_LCM_YMAX) fill_y0 = GUI_LCM_YMAX; if(fill_y0<0) fill_y0 = 0; /* 设置填充线条结束点fill_x1 */ fill_x1 = x0*2 - draw_x3; if(fill_x1>GUI_LCM_XMAX) fill_x1 = GUI_LCM_XMAX; GUI_HLine(fill_x0, fill_y0, fill_x1, color); } if( (draw_x4<=GUI_LCM_XMAX)&&(draw_y4>=0) ) { GUI_Point(draw_x4, draw_y4, color); } if( (draw_x5>=0)&&(draw_y5>=0) ) { GUI_Point(draw_x5, draw_y5, color); } /* 第六点垂直线填充(上半圆的点) */ if(draw_x5>=0) { /* 设置填充线条起始点fill_x0 */ fill_x0 = draw_x5; /* 设置填充线条起始点fill_y0 */ fill_y0 = draw_y5; if(fill_y0>GUI_LCM_YMAX) fill_y0 = GUI_LCM_YMAX; if(fill_y0<0) fill_y0 = 0; /* 设置填充线条结束点fill_x1 */ fill_x1 = x0*2 - draw_x5; if(fill_x1>GUI_LCM_XMAX) fill_x1 = GUI_LCM_XMAX; GUI_HLine(fill_x0, fill_y0, fill_x1, color); } if( (draw_x6<=GUI_LCM_XMAX)&&(draw_y6<=GUI_LCM_YMAX) ) { GUI_Point(draw_x6, draw_y6, color); } if( (draw_x7>=0)&&(draw_y7<=GUI_LCM_YMAX) ) { GUI_Point(draw_x7, draw_y7, color); } /* 第八点垂直线填充(上半圆的点) */ if(draw_x7>=0) { /* 设置填充线条起始点fill_x0 */ fill_x0 = draw_x7; /* 设置填充线条起始点fill_y0 */ fill_y0 = draw_y7; if(fill_y0>GUI_LCM_YMAX) fill_y0 = GUI_LCM_YMAX; if(fill_y0<0) fill_y0 = 0; /* 设置填充线条结束点fill_x1 */ fill_x1 = x0*2 - draw_x7; if(fill_x1>GUI_LCM_XMAX) fill_x1 = GUI_LCM_XMAX; GUI_HLine(fill_x0, fill_y0, fill_x1, color); } } }
/** * @brief 画任意两点之间的直线 并可设置线宽. * @param x0:直线起点 y0: x1: y1: with: color:显示的颜色. * @retval None. * @verify . */ void GUI_LineWith(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t with, TCOLOR color) { int32_t dx; // 直线x轴差值变量 int32_t dy; // 直线y轴差值变量 int8_t dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向 int8_t dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向 int32_t dx_x2; // dx*2值变量,用于加快运算速度 int32_t dy_x2; // dy*2值变量,用于加快运算速度 int32_t di; // 决策变量 int32_t wx, wy; // 线宽变量 int32_t draw_a, draw_b; /* 参数过滤 */ if(with==0) return; if(with>50) with = 50; dx = x1-x0; // 求取两点之间的差值 dy = y1-y0; wx = with/2; wy = with-wx-1; /* 判断增长方向,或是否为水平线、垂直线、点 */ if(dx>0){ // 判断x轴方向 dx_sym = 1; // dx>0,设置dx_sym=1 }else{ if(dx<0){ dx_sym = -1; // dx<0,设置dx_sym=-1 }else{ /* dx==0,画垂直线,或一点 */ wx = x0-wx; if(wx<0) wx = 0; wy = x0+wy; while(1){ x0 = wx; GUI_RLine(x0, y0, y1, color); if(wx>=wy) break; wx++; } return; } } if(dy>0){ // 判断y轴方向 dy_sym = 1; // dy>0,设置dy_sym=1 }else{ if(dy<0){ dy_sym = -1; // dy<0,设置dy_sym=-1 }else{ /* dy==0,画水平线,或一点 */ wx = y0-wx; if(wx<0) wx = 0; wy = y0+wy; while(1){ y0 = wx; GUI_HLine(x0, y0, x1, color); if(wx>=wy) break; wx++; } return; } } /* 将dx、dy取绝对值 */ dx = dx_sym * dx; dy = dy_sym * dy; /* 计算2倍的dx及dy值 */ dx_x2 = dx*2; dy_x2 = dy*2; /* 使用Bresenham法进行画直线 */ if(dx>=dy){ // 对于dx>=dy,则使用x轴为基准 di = dy_x2 - dx; while(x0!=x1){ /* x轴向增长,则宽度在y方向,即画垂直线 */ draw_a = y0-wx; if(draw_a<0) draw_a = 0; draw_b = y0+wy; GUI_RLine(x0, draw_a, draw_b, color); x0 += dx_sym; if(di<0){ di += dy_x2; // 计算出下一步的决策值 }else{ di += dy_x2 - dx_x2; y0 += dy_sym; } } draw_a = y0-wx; if(draw_a<0) draw_a = 0; draw_b = y0+wy; GUI_RLine(x0, draw_a, draw_b, color); }else{ // 对于dx<dy,则使用y轴为基准 di = dx_x2 - dy; while(y0!=y1){ /* y轴向增长,则宽度在x方向,即画水平线 */ draw_a = x0-wx; if(draw_a<0) draw_a = 0; draw_b = x0+wy; GUI_HLine(draw_a, y0, draw_b, color); y0 += dy_sym; if(di<0){ di += dx_x2; }else{ di += dx_x2 - dy_x2; x0 += dx_sym; } } draw_a = x0-wx; if(draw_a<0) draw_a = 0; draw_b = x0+wy; GUI_HLine(draw_a, y0, draw_b, color); } }
/** * @brief 画任意两点之间的直线. * @param x0:直线起点 y0: x1: y1: color:显示的颜色. * @retval None. * @verify . */ void GUI_Line(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, TCOLOR color) { int32_t dx; // 直线x轴差值变量 int32_t dy; // 直线y轴差值变量 int8_t dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向 int8_t dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向 int32_t dx_x2; // dx*2值变量,用于加快运算速度 int32_t dy_x2; // dy*2值变量,用于加快运算速度 int32_t di; // 决策变量 dx = x1-x0; // 求取两点之间的差值 dy = y1-y0; /* 判断增长方向,或是否为水平线、垂直线、点 */ if(dx>0){ // 判断x轴方向 dx_sym = 1; // dx>0,设置dx_sym=1 }else{ if(dx<0){ dx_sym = -1; // dx<0,设置dx_sym=-1 }else{ // dx==0,画垂直线,或一点 GUI_RLine(x0, y0, y1, color); return; } } if(dy>0){ // 判断y轴方向 dy_sym = 1; // dy>0,设置dy_sym=1 }else{ if(dy<0){ dy_sym = -1; // dy<0,设置dy_sym=-1 }else{ // dy==0,画水平线,或一点 GUI_HLine(x0, y0, x1, color); return; } } /* 将dx、dy取绝对值 */ dx = dx_sym * dx; dy = dy_sym * dy; /* 计算2倍的dx及dy值 */ dx_x2 = dx*2; dy_x2 = dy*2; /* 使用Bresenham法进行画直线 */ if(dx>=dy){ // 对于dx>=dy,则使用x轴为基准 di = dy_x2 - dx; while(x0!=x1){ GUI_Point(x0, y0, color); x0 += dx_sym; if(di<0){ di += dy_x2; // 计算出下一步的决策值 }else{ di += dy_x2 - dx_x2; y0 += dy_sym; } } GUI_Point(x0, y0, color); // 显示最后一点 }else{ // 对于dx<dy,则使用y轴为基准 di = dx_x2 - dy; while(y0!=y1){ GUI_Point(x0, y0, color); y0 += dy_sym; if(di<0){ di += dx_x2; }else{ di += dx_x2 - dy_x2; x0 += dx_sym; } } GUI_Point(x0, y0, color); // 显示最后一点 } }
/**************************************************************************** * 名称:GUI_SMenuDraw() * 功能:显示子菜单,加上边框。 * 入口参数:men 子菜单句柄 * 出口参数:返回0表示操作失败,返回1表示操作成功 ****************************************************************************/ uint8 GUI_SMenuDraw(SMENU *men) { WINDOWS *mwin; uint32 xx, yy; uint8 i; mwin = men->win; /* 判断是否可以显示主菜单 */ if( (mwin->hight)<50 ) return(0); if( (mwin->with)<50 ) return(0); /* 画菜子单项。下拉子菜单,以向左下拉为原则,若右边溢出则以右下拉显示 */ xx = mwin->x; xx += (men->mmenu_no)*MMENU_WIDTH; yy = mwin->y + 22; yy += (men->no) * 11 + 2; if( (xx+SMENU_WIDTH) <= (mwin->x + mwin->with - 1) ) { /* 以左下拉为原则显示子菜单 */ if( (men->mmenu_no) == 0 ) { GUI_RLine(xx+SMENU_WIDTH, mwin->y + 22, yy, disp_color); GUI_HLine(xx, yy, xx+SMENU_WIDTH, disp_color); } else { GUI_Rectangle(xx, mwin->y + 22, xx+SMENU_WIDTH, yy, disp_color); } GUI_HLine(xx+1, mwin->y + 22, xx+MMENU_WIDTH-1, back_color); } else { /* 以右下拉为原则 */ if( (xx+MMENU_WIDTH) == (mwin->x + mwin->with - 1) ) { GUI_RLine(xx-(SMENU_WIDTH-MMENU_WIDTH), mwin->y + 22, yy, disp_color); GUI_HLine(xx-(SMENU_WIDTH-MMENU_WIDTH), yy, xx+MMENU_WIDTH, disp_color); } else { GUI_Rectangle(xx-(SMENU_WIDTH-MMENU_WIDTH), mwin->y + 22, xx+MMENU_WIDTH, yy, disp_color); } GUI_HLine(xx+1, mwin->y + 22, xx+MMENU_WIDTH-1, back_color); xx = xx-(SMENU_WIDTH-MMENU_WIDTH); } /* 显示菜单文字 */ xx++; yy = mwin->y + 22 + 2; for(i=0; i<(men->no); i++) { if( i == (men->state) ) // 判断所选择的菜单项 { /* 显示背景色 */ GUI_RectangleFill(xx, yy, xx+SMENU_WIDTH-2, yy+10, disp_color); /* 显示菜单字符 */ GUI_ExchangeColor(); GUI_PutNoStr(xx+1, yy+1, men->str[i], 8); // 书写子菜单文字 GUI_ExchangeColor(); } else { /* 显示背景色 */ GUI_RectangleFill(xx, yy, xx+SMENU_WIDTH-2, yy+10, back_color); /* 显示菜单字符 */ GUI_PutNoStr(xx+1, yy+1, men->str[i], 8); // 书写子菜单文字 } yy += 11; } return(1); }