
//описание курсора
struct Cursor_Data
{
enum Object id; //идентификатор объекта
uint8_t y; //координаты верхнего левого угла кнопки
uint8_t x; //координаты верхнего левого угла кнопки
uint8_t height; //высота кнопки
uint8_t width; //ширина кнопки
uint8_t to_redraw; //флаг "отрисовать"
void (*Draw_Cursor)(Cursor_Data *curs_struct, uint8_t clear);
}; 
//описание курсора
struct Cursor_Data
{
enum Object id; //идентификатор объекта
uint8_t y; //координаты верхнего левого угла кнопки
uint8_t x; //координаты верхнего левого угла кнопки
uint8_t height; //высота кнопки
uint8_t width; //ширина кнопки
uint8_t to_redraw; //флаг "отрисовать"
void (*Draw_Cursor)(Cursor_Data *curs_struct, uint8_t clear);
}; 
//отрисовка курсора примитивами
//clear: 0 - рисуем нормально, 1 - рисуем цветом фона (BLACK)
void draw_cursor(Cursor_Data *cur_struct, uint8_t clear)
{
uint16_t Color, ColorFr;
Color = WHITE;
ColorFr = PURPLE;
if(clear!=0)
{
Color= BLACK; //очистка примитивами
ColorFr = BLACK;
} 
//центр курсора
uint8_t x_c = cur_struct->x + cur_struct->width/2;
uint8_t y_c = cur_struct->y + cur_struct->height/2;
//ветки
ssd1331_draw_line( cur_struct->x , y_c , x_c-5, y_c , Color); //левый горизонт
//обрамление
ssd1331_draw_line( cur_struct->x , y_c+1 , x_c-5, y_c+1 , ColorFr); //левый горизонт
ssd1331_draw_line( cur_struct->x , y_c-1 , x_c-5, y_c-1 , ColorFr); //левый горизонт
ssd1331_draw_line( cur_struct->x+cur_struct->width, y_c , x_c+5, y_c , Color); //правый горизонт
//обрамление
ssd1331_draw_line( cur_struct->x+cur_struct->width, y_c+1 , x_c+5, y_c+1 , ColorFr); //правый горизонт
ssd1331_draw_line( cur_struct->x+cur_struct->width, y_c-1 , x_c+5, y_c-1 , ColorFr); //правый горизонт
ssd1331_draw_line( x_c , cur_struct->y, x_c, y_c-5 , Color); //верхняя вертикаль
//обрамление
ssd1331_draw_line( x_c+1 , cur_struct->y, x_c+1, y_c-5 , ColorFr); //верхняя вертикаль
ssd1331_draw_line( x_c-1 , cur_struct->y, x_c-1, y_c-5 , ColorFr); //верхняя вертикаль
ssd1331_draw_line( x_c , cur_struct->y + cur_struct->height, x_c, y_c+5 , Color); //нижняя вертикаль
//обрамление
ssd1331_draw_line( x_c+1 , cur_struct->y + cur_struct->height, x_c+1, y_c+5 , ColorFr); //нижняя вертикаль
ssd1331_draw_line( x_c-1 , cur_struct->y + cur_struct->height, x_c-1, y_c+5 , ColorFr); //нижняя вертикаль
//центральная окружность
ssd1331_draw_circle(x_c, y_c, 1, Color);
//обрамление
ssd1331_draw_circle(x_c, y_c, 2, ColorFr); 
//генерируем событие "раз в 100 мс проверка кнопок на плате"
htim1_event_100ms_count_tsw--; //уменьшаем счетчик для события
if(htim1_event_100ms_count_tsw==0)
{//счетчик достиг конца - генерим событие
htim1_event_100ms_count_tsw = HTIM1_EVENT_100ms_tsw; //установим счетчик в изначальное состояние
event_100ms_flag_tsw = 1; //установим флаг события
//обработка нажатий тактовых кнопок, приоритет вниз нарастает
TSW_Event = None; //до проверки считаем не нажатой ни одну кнопку на плате
if(HAL_GPIO_ReadPin(BTN5_GPIO_Port, BTN5_Pin) == GPIO_PIN_RESET)
{//нажали кнопку на плате "влево"
TSW_Event=Left; //флаг нажатия тактовой кнопки на плате
}
if(HAL_GPIO_ReadPin(BTN1_GPIO_Port, BTN1_Pin) == GPIO_PIN_RESET)
{//нажали кнопку на плате "вправо"
TSW_Event=Right; //флаг нажатия тактовой кнопки на плате
}
if(HAL_GPIO_ReadPin(BTN2_GPIO_Port, BTN2_Pin) == GPIO_PIN_RESET)
{//нажали кнопку на плате "вверх"
TSW_Event=Up; //флаг нажатия тактовой кнопки на плате
}
if(HAL_GPIO_ReadPin(BTN4_GPIO_Port, BTN4_Pin) == GPIO_PIN_RESET)
{//нажали кнопку на плате "вниз"
TSW_Event=Down; //флаг нажатия тактовой кнопки на плате
}
if(HAL_GPIO_ReadPin(BTN3_GPIO_Port, BTN3_Pin) == GPIO_PIN_RESET)
{//нажали кнопку на плате "клик"
TSW_Event=Click; //флаг нажатия тактовой кнопки на плате
}
event_100ms_flag_tsw = 0; //сброс флага события - обработали
} 
//перерисовка всех объектов
void redraw_objects(struct Button_Data Object[], uint32_t num_objs, struct Cursor_Data *Cursor_)
{
for(uint32_t i=0; i< num_objs; i++) //перебор всех объектов
{
if(Object[i].to_redraw!=0)
{
Object[i].Draw_Button(&Object[i], 0); //рисуем с новым состоянием
Object[i].to_redraw=0;//сброс флага отрисовки объекта
}
}
if(Cursor_->to_redraw!=0)
{
Cursor_->Draw_Cursor(Cursor_, 0);//рисуем с новым состоянием
Cursor_->to_redraw=0;//сброс флага отрисовки
}
}
//все объекты на перерисовку
void to_redraw_all_objects(struct Button_Data Object[], uint32_t num_objs, struct Cursor_Data *Cursor_)
{
for(uint32_t i=0; i< num_objs; i++) //перебор всех объектов
{
Object[i].to_redraw=1;//устанвока флага отрисовки объекта
}
Cursor_->to_redraw =1; //курсор тоже перерисовываем
} 
//проверка всех объектов
void check_objects(struct Button_Data Object[], uint32_t num_objs, struct Cursor_Data *Cursor_, enum TactSwitch_Event *TSW)
{
//центр курсора
uint8_t x_c = Cursor_->x + Cursor_->width/2;
uint8_t y_c = Cursor_->y + Cursor_->height/2;
//проверяем событие нажатия кнопок на плате
switch(*TSW)
{
case Left:
//нажата кнопка влево
if(x_c-1 >=0 )
{ //можем сдвинуть влево - двигаем
Cursor_->Draw_Cursor(Cursor_, 1); //очистка старого места курсора
check_draw_obj_by_cursor(Object, num_objs, Cursor_); //для объектов, которые перекрывались курсором ставим флаг безусловной перерисовки
Cursor_->x--;//новое положение курсора
Cursor_->to_redraw = 1; // нужно потом перерисовать курсор в новом месте
}
break; 
case Click:
//клик мыши
check_push_obj_by_cursor(Object, num_objs, Cursor_); //для объектов, на которых был центр курсора ставим "нажатыми"
Cursor_->to_redraw=1; //перерисуем потом курсор, т.к. он затрется объектами на которых он был кликнут, которые перерисуются
break;
case None:
//кнопку на плате отжали
check_unpush_obj_by_cursor(Object, num_objs, Cursor_); //для всех объектов ставим "отжата"
break;
default:
break;
} 17. Реализуем три необходимые функции:

//для объектов, которые перекрывались курсором ставим флаг безусловной перерисовки
void check_draw_obj_by_cursor(struct Button_Data Object[], uint32_t num_objs, struct Cursor_Data *Cursor_)
{
for(uint32_t i=0; i< num_objs; i++)
{
if((Object[i].x <= Cursor_->x && Cursor_->x <= Object[i].x + Object[i].width && Object[i].y <= Cursor_->y && Cursor_->y <= Object[i].y + Object[i].height /* левый верхний угол курсора*/) ||
(Object[i].x <= Cursor_->x+Cursor_->width && Cursor_->x+Cursor_->width <= Object[i].x + Object[i].width && Object[i].y <= Cursor_->y && Cursor_->y <= Object[i].y + Object[i].height /* правый верхний угол курсора*/) ||
(Object[i].x <= Cursor_->x && Cursor_->x <= Object[i].x + Object[i].width && Object[i].y <= Cursor_->y + Cursor_->height && Cursor_->y + Cursor_->height <= Object[i].y + Object[i].height /* левый нижний угол курсора*/) ||
(Object[i].x <= Cursor_->x+Cursor_->width && Cursor_->x+Cursor_->width <= Object[i].x + Object[i].width && Object[i].y <= Cursor_->y + Cursor_->height && Cursor_->y + Cursor_->height <= Object[i].y + Object[i].height /*правый нижний угол курсора*/)
)
{
Object[i].to_redraw=1;
}
}
} 
//для объектов, на которых был центр курсора ставим "нажатыми"
void check_push_obj_by_cursor(struct Button_Data Object[], uint32_t num_objs, struct Cursor_Data *Cursor_)
{
//центр курсора
uint8_t x_c = Cursor_->x + Cursor_->width/2;
uint8_t y_c = Cursor_->y + Cursor_->height/2;
for(uint32_t i=0; i< num_objs; i++)
{
if(Object[i].x <= x_c && x_c <= Object[i].x + Object[i].width
&& Object[i].y <= y_c && y_c <= Object[i].y + Object[i].height)
{
//центр курсора в границах объекта
Object[i].current_state = PRESS;
}
}
} 
//для всех объектов ставим "отжата"
void check_unpush_obj_by_cursor(struct Button_Data Object[], uint32_t num_objs, struct Cursor_Data *Cursor_)
{
for(uint32_t i=0; i< num_objs; i++)
Object[i].current_state = NO_PRESS;
} 
| Стартуем! |
| Дальше |
| Проверить |
| Узнать результат |
| Дальше |
| Проверить |
| Узнать результат |
| Дальше |
| Проверить |
| Узнать результат |
| Пройти еще раз |
| Пройти еще раз |
| Пройти еще раз |