Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту


 
Опции темы
Непрочитано 11.12.2014, 19:35  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 918
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Пишем свое API

В данной статье мы разберемся с базовыми принципами построения пользовательского интерфейса и познакомимся с некоторыми хитростями программирования на языке С.
Итак, любой интерфейс начинается с самого элементарного – кнопки. Как нарисовать кнопку на экране? Как заставить кнопку реагировать на нажатие сенсорной панели? Как вызывать процедуру - обработчик действия? Но, обо всем по порядку:
Чтобы нарисовать кнопку, нам нужно определиться, какими свойствами она должна обладать. Их множество, если кто помнит Windows Form или знает WPF. Но аппаратных мощностей x86 у нас нет, и мы поскромничаем – обойдемся лишь необходимыми. Опишем их некоей структурой:
Код:
typedef struct
{
	unsigned int StartX, StartY;					//location
	unsigned char SizeX, SizeY;						//size
	char * Caption;												//text caption
	int FontColor, BackColor;							//color palete
	void (*Handle)(unsigned char BNum);		//handler void
	FlagStatus Exist;											//attribute exist
	FlagStatus Drawn;											//attribute drawn
	FunctionalState Active;								//attribute active
	FlagStatus isPressed;									//attribute isPressed
	FlagStatus isSelected;
}Button_TypeDef;
Давайте разберемся в них. StartX и StartY, как ясно из названия, определяют расположения верхней левой вершины прямоугольника, коему суждено стать изображением кнопки на дисплее.
Далее идет описание размеров кнопки. Я посчитал, что размер кнопки вряд ли превысят 255 пикселей и оставил по байту на размер по Х и по Y. Указатель Caption представляет собой ссылку на массив элементов типа char, в которых будет храниться надпись на кнопке в виде текста.
Переменные FontColor и BackColor описывают цвет шрифта и цвет фона соответственно в системе кодировки цвета 5-6-5.
Указатель на процедуру Handle() есть обработчик нажатия на кнопку. С ним мы разберемся позже.
Энумерованные типы FlagStatus и FunctionalState я позаимствовал из файла stm32f10x.h, но для партирования на другую платформу их придется определить отдельно. Впрочем, можно обойтись и простой переменной типа byte т.к. кроме сравнения на ноль и не ноль эти свойства не используются. Для них можно было бы применить тип bool, если бы я верил в то, что это чем-то поможет общему делу.
Определившись со структурой, мы создаем отдельно файлы .с и .h, где сразу декларируем локальный массив структур Button_TypeDef:
Код:
Button_TypeDef Buttons[max_buttons];
Где константа max_buttons определена дефайной:
#define max_buttons 5 – количество кнопок, которое вы хотите использовать.
Итак, мы готовы нарисовать нашу первую кнопку:
Код:
FlagStatus ButtonDraw (unsigned char BNum)
{
	char TextLen;
	if (Buttons[BNum].Drawn == SET) return RESET;
	TextLen = StringLen(Buttons[BNum].Caption);
	if (Buttons[BNum].SizeX == 0) Buttons[BNum].SizeX = TextLen * font_width + standart_sizeX;
	if (Buttons[BNum].SizeY == 0) Buttons[BNum].SizeY = standart_sizeY;	
	
	LCD_FillWindow(Buttons[BNum].StartX, Buttons[BNum].StartY, Buttons[BNum].SizeX, Buttons[BNum].SizeY, Buttons[BNum].BackColor);
	GUI_Text(Buttons[BNum].StartX + Buttons[BNum].SizeX/2 - (font_width)*TextLen/2, 
																			Buttons[BNum].StartY + Buttons[BNum].SizeY/2 - font_height/2, 
																			(uint8_t*)(Buttons[BNum].Caption), Buttons[BNum].FontColor, 
																			Buttons[BNum].BackColor);	
	/* Paint Shadow Frame */
	LCD_FillWindow(Buttons[BNum].StartX, Buttons[BNum].StartY + Buttons[BNum].SizeY - frame_width, Buttons[BNum].SizeX, frame_width, Black);
	LCD_FillWindow(Buttons[BNum].StartX + Buttons[BNum].SizeX - frame_width, Buttons[BNum].StartY, frame_width, Buttons[BNum].SizeY, Black);
	if (Buttons[BNum].isSelected == RESET)
	{
		LCD_FillWindow(Buttons[BNum].StartX, Buttons[BNum].StartY, Buttons[BNum].SizeX, frame_width, White);
		LCD_FillWindow(Buttons[BNum].StartX, Buttons[BNum].StartY, frame_width, Buttons[BNum].SizeY, White);
	}
	else
	{
		LCD_FillWindow(Buttons[BNum].StartX, Buttons[BNum].StartY, Buttons[BNum].SizeX, frame_width, Black);
		LCD_FillWindow(Buttons[BNum].StartX, Buttons[BNum].StartY, frame_width, Buttons[BNum].SizeY, Black);
		LCD_FillWindow(Buttons[BNum].StartX, Buttons[BNum].StartY + Buttons[BNum].SizeY - frame_width*2, Buttons[BNum].SizeX, frame_width*2, Black);
		LCD_FillWindow(Buttons[BNum].StartX + Buttons[BNum].SizeX - frame_width*2, Buttons[BNum].StartY, frame_width*2, Buttons[BNum].SizeY, Black);
	}
	Buttons[BNum].Drawn = SET;																			
  return SET;																			
}
Функция получилась не маленькая, но давайте в ней разберемся. Для начала мы убедимся, что кнопка не нарисована. В противном случае рисовать ее никакой необходимости нет и можно вернуть статус SET, сообщающий об успешности процедуры. Получив в ответ SET, мы можем быть уверены, что кнопка нарисована. Далее идет две строки, в которых мы убеждаемся, что размеры кнопки не равны нулю. В противном случае процедура сама рассчитывает длину и ширину кнопки, зная количество символов в строке Caption и ширину каждого символа. Т.к. мы используем шрифт 8x16, то соответствующие значения определены дефайном:
Код:
#define font_width			8
#define font_height			16
#define frame_width	  		1
#define standart_sizeX			20
#define standart_sizeY			30
Где frame_width – ширина рамки с тенью, которая рисуется в конце функции отрисовки.
Как хорошо заметно, я из всех графических методов я использую только два – рисование шрифта GUI_Text и заполнение окна LCD_FillWindow. Последний я считаю наиболее важным и достойным внимания. Он состоит из двух частей. Первое – это определение координат окна. Мы передаем значения координат в регистры контроллера дисплея. И после этого просто заливаем память сплошным потоком, что позволяет не отвлекаться на ногодрыг в случае применения SPI интерфейса или, как в нашем случае, используя модуль управления внешней памятью FSMC, значительно ускоряющего процесс заливки. Еще одним интересным вариантом было бы выделить участок оперативной памяти, построить изображение кнопки в нем и после «вылить» содержимое буфера в GRAM по средствам DMA. Но т.к. я использую простейшую операционную систему FreeRTOS, особой необходимости в этом нет. Все и так прекрасно успевает отрисовываться и обрабатываться.
Теперь у нас есть кнопка, которую мы нарисуем, если определим структуру и вызовем функцию DrawButton(номер кнопки). Но как определить структуру, которая находится в отличном от main.c файле? Разумного было бы воспользоваться методом extern и описать структуру в файле инитиализации. Но это показалось мне не спортивно. Для доступа к процедуре я написал такую функцию:
Код:
Button_TypeDef * ButtonStructPointer (unsigned char BNum)
{
	return &Buttons[BNum];
}
Она возвращает адрес нашего массива структур в памяти. Для определения структуры в другом файле мы декларируем указатель на эту структуру:

Button_TypeDef * Button;

Определяем, что собираемся работать с нулевым элементом нашего массива, т.е. структурой кнопки номер 0:
Код:
Button = AddButton(0);
И далее просто определяем необходимые свойства кнопки, например:
Код:
Button-›Active = ENABLE;
	Button-›BackColor = Grey;
	Button-›Caption = "OK";
	Button-›Exist = SET;
	Button-›FontColor = Black;
	Button-›SizeX = 80;
	Button-›SizeY = 30;
	Button-›StartX = 80;
	Button-›StartY = 100;
	Button-›Handle = Button0_Handle;	
	DrawButton(0);
Хорошо видно, что вызвав функцию DrawButton(0) мы нарисовали серую кнопку с черной надписью «ОК» размером 80х30 где-то в первой половине экрана.
Важный момент здесь – обработчик Button0_Handle. Процедура обработки нажатия на кнопку 0 «ОК». К примеру, поморгать светодиодом:
Код:
void Button0_Handle (void)
{
		GPIOB-›ODR = GPIOB-›IDR ^ GPIO_Pin_1;
}
Так что пришло время поговорить об обработчике. Он вызывается некоторой процедурой ButtonsHandler(int X, int Y), которой мы передаем координаты нажатия на тачпанель. Процедура пробегаем по всем существующим кнопкам и ищет, не попадает ли данная координата в область какой-либо кнопки. В случае попадания, вызывает обработчик Button-›Handle.
Обработчик может быть один на все кнопки сразу т.к. получит в качестве параметра BNum номер нажатой кнопки, либо индивидуальный на каждую кнопку в зависимости от поставленной задачи.
Код:
FlagStatus ButtonsHandler (int X, int Y)
{
	char cnt; 
	FlagStatus res = RESET;
	for (cnt = 0; cnt != max_buttons; cnt++)
		if (ButtonCheck(cnt, X, Y) == SET) res = SET;
	return res;
}
И, собственно, сама процедура поиска:
Код:
FlagStatus ButtonCheck (unsigned char BNum, int X, int Y)
{
	if (Buttons[BNum].Exist == RESET) return RESET;
	if (Buttons[BNum].Active == DISABLE) return RESET; 
	if (Buttons[BNum].Drawn == RESET) return RESET;
	if ((X › Buttons[BNum].StartX) && (X ‹ (Buttons[BNum].StartX + Buttons[BNum].SizeX)) 
	 && (Y › Buttons[BNum].StartY) && (Y ‹ (Buttons[BNum].StartY + Buttons[BNum].SizeY)))
	 {
			if ((Buttons[BNum].Handle != (void*)0) && (Buttons[BNum].isPressed == RESET))
			{
				Buttons[BNum].Handle(BNum);
				Buttons[BNum].isPressed = SET;
				return SET;
			}
			return RESET;
	 }
	  else 
			Buttons[BNum].isPressed = RESET;
	return RESET;
}
Триггер isPressed нужен для того, чтобы обработка события происходила единожды до выхода координат за поле объекта. Иначе говоря, пока палец давит на кнопку, процедура выполняется только один раз.
Так же нам понадобится еще три процедуры:
Код:
void ButtonDelete (unsigned char BNum)
{
	Buttons[BNum].Handle = (void*)0;
	Buttons[BNum].Exist = RESET;
	Buttons[BNum].Drawn = RESET;
	Buttons[BNum].Active = DISABLE;
	Buttons[BNum].isPressed = RESET;
	Buttons[BNum].isSelected = RESET;
}

void ButtonHide (unsigned char BNum, int BackColor)
{
	LCD_FillWindow(Buttons[BNum].StartX, Buttons[BNum].StartY, Buttons[BNum].SizeX, Buttons[BNum].SizeY, BackColor);
	Buttons[BNum].Active = DISABLE;
	Buttons[BNum].Drawn = RESET;
}

void ButtonSelect (unsigned char BNum, FlagStatus Select)
{
	Buttons[BNum].isSelected = Select;
	Buttons[BNum].Drawn = RESET;
	ButtonDraw(BNum);
}
Первая удаляет кнопку и освобождает структуру. Вторая прячет кнопку с экрана. Третья включает прямоугольник выделения, если параметр Select отличен от RESET. Полезно для визуализации нажатия на кнопку.

Ну и наконец просто полезная процедура быстрой инитиализации кнопки с параметрами по умолчанию:
Код:
void ButtonAddStandart (unsigned int StartX, unsigned int StartY, unsigned int SizeX, unsigned int SizeY, unsigned char BNum, char * txt, void (*Handle)(unsigned char BNum))
{
	Buttons[BNum].StartX = StartX;
	Buttons[BNum].StartY = StartY;
	Buttons[BNum].SizeX = SizeX;
	Buttons[BNum].SizeY = SizeY;
	Buttons[BNum].FontColor = Black;
	Buttons[BNum].BackColor = Grey;
	Buttons[BNum].Handle = Handle;
	Buttons[BNum].Exist = SET;
	Buttons[BNum].Drawn = RESET;
	Buttons[BNum].Active = ENABLE;
	Buttons[BNum].Caption = txt;
	Buttons[BNum].isPressed = RESET;
	Buttons[BNum].isSelected = RESET;
	ButtonDraw(BNum);
}
С помощью последней процедуры инитиализация кнопки выглядит так:
Код:
ButtonAddStandart(80,100,0,0,0,"OK",Button0_Handle);
Где 80 и 100 – координаты кнопки, 0, 0 говорят о том, что размер кнопки будет выбран автоматически, «ОК» - текст и Button0_Handle – обработчик.

Дальше я опишу, как нам выделить процедуры и функции, связанные с кнопками API в отдельный класс средствами языка С.

Нам понадобится структура:
Код:
typedef struct
{
	FlagStatus (*Handler) (int X, int Y);
	FlagStatus (*Draw) (unsigned char BNum);
	void (*AddStandart) (unsigned int StartX, unsigned int StartY, unsigned int SizeX, unsigned int SizeY, unsigned char BNum, char * txt, void (*Handle)(unsigned char BNum));
	void (*Delete) (unsigned char BNum);
	void (*Hide) (unsigned char BNum, int BackColor);
	void (*Select) (unsigned char BNum, FlagStatus Select);
}ButtonClass_TypeDef;
Состоящая из указателей на функции, связанные с элементом Кнопка. Далее мы вводим эту структуру в файл проекта:
Код:
const ButtonClass_TypeDef ButtonClass = {ButtonsHandler, ButtonDraw, ButtonAddStandart, ButtonDelete, ButtonHide, ButtonSelect};
Теперь для обращения к функциям класса, надо в файле .с задекларировать класс так:
Код:
extern const ButtonClass_TypeDef ButtonClass;
И теперь при вызове класса ButtonClass после точки будет выпадать список связанных с ним процедур и функций:
Код:
	for (i = 0; i ‹ 4; i++)
		for (j = 0; j ‹ 3; j++)
			ButtonClass.AddStandart(30+j*65,70+i*60,50,50,k++,  (char*)(CaptionMatrix[i][j]),Button_Handle);
Рисует на дисплее матрицу элементов CaptionMatrix:
Код:
const char * CaptionMatrix[4][3] = 
{{"1", "2", "3"},
 {"4", "5", "6"},
 {"7", "8", "9"},
 {"‹", "0", "OK"}};
Проект FreeRTOS под STM32F103VC + SSD1289 на HY32Mini во вложении.
Продолжение следует...
Миниатюры:
Нажмите на изображение для увеличения
Название: IMG_20141211_140811.jpg
Просмотров: 237
Размер:	108.4 Кб
ID:	73031  
Вложения:
Тип файла: rar FreeRTOSV6.1.0.rar (975.3 Кб, 120 просмотров)
Реклама:

Последний раз редактировалось Easyrider83; 11.12.2014 в 20:18.
Easyrider83 вне форума  
Эти 23 пользователя(ей) сказали Спасибо Easyrider83 за это сообщение:
-shiva- (22.06.2015), akegor (11.12.2014), andronio (31.08.2015), Ara41 (11.12.2014), baiderin (11.12.2014), BYZON80 (26.08.2015), dosikus (11.12.2014), Ironium (12.12.2014), Kabron (11.12.2014), lisergin (12.12.2014), makakus (24.12.2015), MisterDi (12.12.2014), pinco (12.12.2014), serg_42 (22.06.2015), shyub (12.12.2014), swat24 (12.12.2014), switch0 (14.12.2014), v4575820 (19.05.2016), Viktor2004 (23.08.2015), Vlad German (12.12.2014), V_Hvost (12.12.2014), Zoosman (17.12.2014), С.М.С (11.12.2014)
Непрочитано 11.12.2014, 19:51  
С.М.С
Гражданин KAZUS.RU
 
Аватар для С.М.С
 
Регистрация: 03.07.2010
Сообщений: 843
Сказал спасибо: 156
Сказали Спасибо 378 раз(а) в 190 сообщении(ях)
С.М.С на пути к лучшему
По умолчанию Re: Пишем свое API

Как то я хотел предложить сообществу написать открытую и понятную GUI, но потом забыл про цветные дисплеи.
С.М.С вне форума  
Непрочитано 11.12.2014, 21:00  
dosikus
Гуру портала
 
Аватар для dosikus
 
Регистрация: 20.11.2004
Сообщений: 10,018
Сказал спасибо: 936
Сказали Спасибо 2,270 раз(а) в 1,565 сообщении(ях)
dosikus на пути к лучшему
По умолчанию Re: Пишем свое API

Цитата:
свое API
Цитата:
понятную GUI
Может все таки "свой" и "понятный" ?
__________________
Осторожно , злой кот
dosikus вне форума  
Непрочитано 11.12.2014, 21:07  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 918
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Пишем свое API

Сообщение от dosikus Посмотреть сообщение
Может все таки "свой" и "понятный" ?
Сначала одно кофе и два булка!
Ладно, Леш, давай тут по делу писать. А то зафлудим тему, а я хотел остальные элементы добавлять потихоньку.
Easyrider83 вне форума  
Непрочитано 12.12.2014, 15:21  
shyub
Прописка
 
Регистрация: 20.08.2008
Сообщений: 263
Сказал спасибо: 305
Сказали Спасибо 85 раз(а) в 45 сообщении(ях)
shyub на пути к лучшему
По умолчанию Re: Пишем свое API

За стаатью спасибо.
Не могли бы вы уточнить, на чём это написано, привести принципиальную схему "железа" и "перезалить" ссылку (не открывается).
shyub вне форума  
Непрочитано 12.12.2014, 15:34  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 918
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Пишем свое API

shyub, написано на С, схема очень простая SSD1289 -› STM32 FSMC (NORSRAM1), хотя в данном случае это не имеет никакого отношения к теме. Процедура заливки может быть любой в зависимости от типа контроллера дисплея и интерфейса, а отрисовка шрифта так же должна проводится через заливку.
Ссылка открывается, я проверил.
Сейчас работаю с отрисовкой шрифтов. Тут работы побольше т.к. хочется сделать универсально и быстро. Поэтому потребуется время на это.
Easyrider83 вне форума  
Непрочитано 12.12.2014, 21:54  
Boba_spb
Почётный гражданин KAZUS.RU
 
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
Boba_spb на пути к лучшему
По умолчанию Re: Пишем свое API

Создать GUI - хорошая мысль, но с такой реализацией, боюсь что могут быть проблемы. Ибо контролы имеют координату Z, которой у Вас нет.
У контрола всегда должен быть родитель ! Контрол никогда не "лезет" раньше "батьки" и знает свое место за "столом". По этому "дереву" производиться отрисовка, обрабока событий и т.д.

Как бы задачку надо решать с другого конца - написать соэдание , изменение этого дерева.Затем процессы отображения, обработки событий по этому дереву.А уж потом создавать контролы.
Boba_spb вне форума  
Непрочитано 12.12.2014, 22:04  
dosikus
Гуру портала
 
Аватар для dosikus
 
Регистрация: 20.11.2004
Сообщений: 10,018
Сказал спасибо: 936
Сказали Спасибо 2,270 раз(а) в 1,565 сообщении(ях)
dosikus на пути к лучшему
По умолчанию Re: Пишем свое API

Сообщение от Easyrider83 Посмотреть сообщение
Ладно, Леш, давай тут по делу писать.
Пока никак, как разгребу предновогодний завал, присоединюсь.
__________________
Осторожно , злой кот
dosikus вне форума  
Непрочитано 12.12.2014, 22:35  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 918
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Пишем свое API

Написал отрисовку текста.
Нам понадобится некоторый дефайн:
Код:
#define MaxFontSizeXY 						21 * 18
Память приходится распределять заранее, поэтому жестко фиксируем его за буфером.
Шрифт у нас будет описан такой структурой:
Код:
typedef struct
{
	const unsigned char StartFrom;
	const unsigned char LastChar;
	const unsigned char SizeX;
	const unsigned char SizeY;
	const unsigned char * Code;
}Font_StructTypeDef;
Ниже добавим 4 шрифта, импортированных при помощи GLCD Font Creator от MikroElektronika
Код:
const Font_StructTypeDef Times_New_Roman13x15_FontStruct = {32, 127, 13, 15, Times_New_Roman13x15};
const Font_StructTypeDef Tahoma10x11_FontStruct = {32, 127, 10, 11, Tahoma10x11};
const Font_StructTypeDef Britannic_Bold10x12_FontStruct = {32, 127, 10, 12, Britannic_Bold10x12};
const Font_StructTypeDef Broadway21x18_FontStruct = {32, 127, 21, 18, Broadway21x18};
Ну и для упрощения вызова понадобится еще одна залипуха:
Код:
const Font_StructTypeDef * Font[4] = {&Times_New_Roman13x15_FontStruct, 
																			&Tahoma10x11_FontStruct, 
																			&Britannic_Bold10x12_FontStruct, 
																			&Broadway21x18_FontStruct};
Теперь процедура отрисовки символа:
Код:
unsigned char DrawChar (unsigned int StartX, unsigned int StartY, char Symbol, char SelectFont, int Color, int BackColor)
{
	extern const Font_StructTypeDef * Font[3];
	char x,y,s, k;
	static int FontPic[MaxFontSizeXY];
	if (Font[SelectFont]-›SizeY ‹ 8) {s = Font[SelectFont]-›SizeX + 1; k = 1;}
	if ((Font[SelectFont]-›SizeY ›=8) && (Font[SelectFont]-›SizeY ‹ 16)) {s = Font[SelectFont]-›SizeX * 2 + 1; k = 2;}
	if (Font[SelectFont]-›SizeY › 16) {s = Font[SelectFont]-›SizeX * 3 + 1; k = 3;}
	Symbol -= Font[SelectFont]-›StartFrom;
	if (Symbol › Font[SelectFont]-›LastChar) return 0;
	for (y = 0; y ‹ Font[SelectFont]-›SizeY; y++)
		for (x = 0; x ‹ Font[SelectFont]-›SizeX; x++)
		{
			if (y ‹ 8)
			{
				if (Font[SelectFont]-›Code[Symbol * s + k*x + 1] & (0x01 ‹‹ y)) FontPic[Font[SelectFont]-›SizeX*y+x] = Color;
				else FontPic[Font[SelectFont]-›SizeX*y+x] = BackColor;
			}
			if ((y ›= 8) && (y ‹ 16))
			{
				if (Font[SelectFont]-›Code[Symbol * s + k*x + 2] & (0x01 ‹‹ (y-8))) FontPic[Font[SelectFont]-›SizeX*y+x] = Color;
				else FontPic[Font[SelectFont]-›SizeX*y+x] = BackColor;				
			}
			if (y ›= 16)
			{
				if (Font[SelectFont]-›Code[Symbol * s + k*x + 3] & (0x01 ‹‹ (y-16))) FontPic[Font[SelectFont]-›SizeX*y+x] = Color;
				else FontPic[Font[SelectFont]-›SizeX*y+x] = BackColor;					
			}
		}
		LCD_DrawPic(StartX, StartY, Font[SelectFont]-›SizeX, Font[SelectFont]-›SizeY, FontPic);	
		return Font[0]-›Code[Symbol * s];
}
Она сложная т.к. кодировка у GLCD Font Creator'a не простая. Первым идет байт длинны символа в пикселях. Но в отличии от нормального шрифта, здесь этот параметр одинаковый на все символы шрифта. Ну так вот мыслят программисты MikroE. Бог им судья. А мы пользуем бесплатную утилиту. Как видно из кода, я вывожу символ на дисплей в виде картинки. Никаких пикселей. Только потоковая заливка.
И, собственно, функция вывода строки:
Код:
unsigned int LCD_PrintText (unsigned int StartX, unsigned int StartY, char * String, char Len, char SelectFont, int Color, int BackColor)
{
	extern const Font_StructTypeDef * Font[3];
	char cnt = 0;
	unsigned int TextLen = 0;
	while (Len--)
		TextLen += DrawChar(StartX + (cnt++) * Font[SelectFont]-›SizeX, StartY, * String++, SelectFont, Color, BackColor);
	return TextLen;
}
Пример:
Код:
	LCD_PrintText(0,0, "TEXT 1 example", 14, 0, Red, Grey);
	LCD_PrintText(0,20, "TEXT 2 example", 14, 1, Blue, Grey);
	LCD_PrintText(0,40, "TEXT 3 example", 14, 2, Green, Grey);
	LCD_PrintText(0,60, "TEXT 4 example", 14, 3, Black, Grey);
Или если использовать энумератор:
Код:
typedef enum {Times_New_Roman1315 = 0, Tahoma1011, Britannic_Bold1012, Broadway2118} FontEnum;
Код:
	LCD_PrintText(0,0, "TEXT 1 example", 14, Times_New_Roman1315, Red, Grey);
	LCD_PrintText(0,20, "TEXT 2 example", 14, Tahoma1011, Blue, Grey);
	LCD_PrintText(0,40, "TEXT 3 example", 14, Britannic_Bold1012, Green, Grey);
	LCD_PrintText(0,60, "TEXT 4 example", 14, Broadway2118, Black, Grey);
Вот так все просто. Проект с шрифтами прилагаю.
Миниатюры:
Нажмите на изображение для увеличения
Название: IMG_20141212_192436.jpg
Просмотров: 102
Размер:	60.5 Кб
ID:	73108  
Вложения:
Тип файла: rar FreeRTOSV6.1.0.rar (998.6 Кб, 54 просмотров)

Последний раз редактировалось Easyrider83; 12.12.2014 в 23:13.
Easyrider83 вне форума  
Эти 4 пользователя(ей) сказали Спасибо Easyrider83 за это сообщение:
-shiva- (22.06.2015), MisterDi (12.12.2014), switch0 (14.12.2014), Zoosman (17.12.2014)
Непрочитано 12.12.2014, 22:36  
MisterDi
Почётный гражданин KAZUS.RU
 
Аватар для MisterDi
 
Регистрация: 13.02.2008
Адрес: Днепр. Украина
Сообщений: 3,294
Сказал спасибо: 442
Сказали Спасибо 1,048 раз(а) в 706 сообщении(ях)
MisterDi на пути к лучшему
По умолчанию Re: Пишем свое API

Цитата:
У контрола всегда должен быть родитель !
Это верно для случая многозадачных систем, где и один и тот же элемент может работать в разных задачах. На МК с ограниченным экраном и фиксированным набором элементов интерфейса, введение дополнительной иерархии ИМХО избыточно.
__________________
misterdi<@>i.ua
MisterDi вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
свое USB устройство ESWANT Микроконтроллеры, АЦП, память и т.д 2 08.09.2009 14:58


Часовой пояс GMT +4, время: 18:54.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot