скачать рефераты
  RSS    

Меню

Быстрый поиск

скачать рефераты

скачать рефератыЛабораторная работа: Организация интерфейса пользователя

Под один символ выделяется так называемое знакоместо область экрана, находящаяся на пересечении строки и столбца. Все знакоместа имеют одинаковый размер и составляют прямоугольную матрицу. В одном знакоместе может быть записан только один символ.

На каждое знакоместо в видеопамяти отводится два байта. В один из них записывается ASCII-код символа, который должен выводиться в соответствующем месте экрана. Другой байт называется байтом атрибутов текста и содержит информацию о цвете символа. Младшие 4 бита атрибутов определяют цвет текста, старшие – цвет фона. Коды цветов приведены в табл. 2. Знакоместа записываются в видеопамяти последовательно слева направо, сверху вниз.

Таблица 2

Коды цветов текстового режима

Код Цвет Константа Си Код Цвет Константа Си
0 Черный BLACK 8 Черный DARKGRAY
1 Темно-синий BLUE 9 Светло-синий LIGHTBLUE
2 Темно-зеленый GREEN 10 Светло-зеленый LIGHTGREEN
3 Темно-голубой CYAN 11 Светло-голубой LIGHTCYAN
4 Темно-красный RED 12 Светло-красный LIGHTRED
5 Темно-розовый MAGENTA 13 Светло-розовый LIGHTMAGENTA
6 Коричневый BROWN 14 Желтый YELLOW
7 Светло-серый LIGHTGRAY 15 Белый WHITE

Поскольку на один символ тратится всего два байта, текстовый режим является очень экономным с точки зрения расходования видеопамяти. Своеобразным побочным эффектом такой экономии является значительное упрощение функций работы с экраном и более высокое быстродействие этих функций. Особенно хорошо это заметно на старых компьютерах без аппаратного ускорения графики.

За формирование изображения на экране из ASCII-кодов и атрибутов текста отвечает видеоадаптер. Программисту не приходится затрачивать для этого практически никаких усилий. Преобразование ASCII-кода в растровый образ символа, выводимый на экран, осуществляется «на лету» в процессе развертки кадра. При этом используется шрифт, который либо «прошит» в ПЗУ видеоадаптера, либо заранее загружен из ОЗУ пользователем. Шрифты, используемые по умолчанию в системе MS-DOS, содержат во второй половине таблицы европейские символы. В связи с этим для вывода кириллицы в текстовом режиме требуется настройка системы на 866 кодовую страницу либо установка русификатора перед запуском программы. И в том, и в другом случае с диска подгружается русифицированный шрифт и устанавливается в качестве текущего шрифта для видеоадаптера.

Помимо символов, в текстовом режиме автоматически формируется изображение текстового курсора, который находится в заданной позиции на экране и имеет заданный внешний вид. Под внешним видом понимается высота курсора: он может выглядеть как черточка под символом, может покрывать все знакоместо или вообще быть отключен.

Система координат на экране выглядит так же, как и в графическом режиме: ось X направлена вправо, ось Y – вниз. Левый верхний угол имеет координаты (1; 1), в отличие от графического режима (где он имеет нулевые координаты). Во многих случаях текстовые функции Си работают не непосредственно с экраном, а с некоторой его прямоугольной областью, называемой окном вывода. По умолчанию окно занимает весь экран, но его координаты могут быть изменены программистом. При выводе в окно содержимое экрана за пределами окна не изменяется, а перенос слишком длинных строк производится по границе окна, а не экрана.


4. Функции текстового режима

Для использования описанных ниже функций необходимо подключить заголовочный файл <conio.h>.

4.1 Общие параметры

void textmode(int newmode)

Устанавливает заданный текстовый видеорежим (см. табл. 1).

void window(int left, int top, int right, int bottom)

Устанавливает новое текстовое окно. Задание некорректных координат приводит к игнорированию обращения к функции window. Параметры left и top задают координаты экрана для верхнего левого угла окна, bottom и right определяют координаты экрана для нижнего правого угла окна.

По умолчанию окно занимает весь экран. Например, в режиме 80×25 по умолчанию координаты окна равны 1,1,80,25.

void gettextinfo(struct text_info *pinfo)

Заполняет структуру text_info, на которую указывает pinfo, видеоинформацией о текущем режиме. С помощью этой функции, в частности, можно узнать текущие координаты окна, установленный видеорежим, размеры экрана.

4.2 Управление курсором

void gotoxy(int x, int y)

Перемещает курсор в заданную позицию текстового окна. Левый верхний угол окна имеет координаты (1,1). Если координаты по какой-то причине указаны неверно, то вызов данной функции игнорируется. Примером такой ошибки может служить вызов gotoxy (40,30), когда размер окна равен 35×25.

int wherex(); int wherey()

Возвращают  координаты  текущей позиции курсора (относительно текстового окна).

void _setcursortype(int cur_t)

Задает внешний вид текстового курсора. С помощью этой функции можно отключить курсор (параметр _NOCURSOR), включить сплошной «блочный» курсор (_SOLIDCURSOR) или вернуть стандартный вид курсора (_NORMALCURSOR). Отключение курсора очень часто используется в интерфейсах-меню и интерфейсах со свободной навигацией.

4.3 Управление атрибутами текста

void highvideo(); void lowvideo()

Устанавливают повышенную и пониженную (соответственно) яркость вывода символов. Эти функции не влияют на все символы, отображаемые в данный момент времени на экране. Их вызов влияет только на последующий вывод на консоль в текстовом режиме.

void normvideo()

Устанавливает нормальную яркость для символов путем возврата к тем значениям текстовых атрибутов (символов и фона), которые были в момент запуска программы.

void textcolor(int newcolor)

Устанавливает цвет символов для выводимого на экран текста. В качестве аргумента можно передавать константы цвета, приведенные в табл. 2.

void textbackground(int newcolor)

Устанавливает цвет фона для выводимого на экран текста. В качестве аргумента можно передавать константы цвета со значениями 0 ÷ 7, приведенные в табл. 2.

void textattr(int newattr)

Устанавливает атрибуты выводимого текста. Эта функция дает возможность установить цвет фона и текста за один вызов. Для того чтобы сформировать байт атрибутов, необходимо цвет фона сдвинуть на 4 разряда влево и сложить с цветом текста: attr=back<<4+text.

4.4 Очистка текста

Все перечисленные ниже функции работают внутри текстового окна, не изменяя символы за его пределами.

void clrscr()

Очищает текущее текстовое окно и устанавливает  курсор  в  левый верхний угол (в позицию 1,1).

void clreol()

Стирает все символы от позиции курсора до конца строки без перемещения курсора.

void delline(); void insline()

Функция delline удаляет текущую строку (в которой находится курсор) и поднимает все строки, находящиеся ниже курсора, на одну строку вверх. Функция insline вставляет пустую строку в позицию курсора текстового окна, используя при этом текущий цвет фона. Все строки, лежащие ниже данной, сдвигаются на одну строку вниз, а последняя строка в текстовом окне пропадает.

4.5 Копирование текста

Перечисленные далее функции работают без учета текущего окна. Все параметры задаются относительно левого верхнего угла экрана, имеющего координаты (1,1).

int movetext(int left, int top, int right, int bottom, int destleft, int desttop)

Копирует содержимое прямоугольной области на экране, определяемой значениями left (левая граница), top (верхняя граница), right (правая граница) и bottom (нижняя граница), в новую прямоугольную область, определяемую аналогичным образом. Левый верхний угол нового прямоугольника задается парой параметров destleft и desttop. Копирование для перекрывающихся окон выполняется корректно.

int gettext(int left, int top, int right, int bottom, void *destin)

Заносит содержимое прямоугольной области на экране, заданной значениями параметров left, top, right, bottom в область памяти, на которую указывает destin.

Функция считывает содержимое прямоугольника в память последовательно, слева направо и сверху вниз. Каждая позиция экрана занимает 2 байта памяти. Первый байт соответствует символу данного знакоместа, а второй  его атрибутам.

Пространство, необходимое для прямоугольника в w столбцов шириной и h строк высотой определяется следующим образом:

размер в байтах = (h строк) × (w столбцов) × 2.

int puttext(int left, int top, int right, int bottom, void *source)

Выводит содержимое области памяти, на которую указывает source, в прямоугольник на экране, координаты которого задаются значениями left, top, right и bottom. Функция выводит содержимое области памяти в заданный прямоугольник в последовательности слева направо и сверху вниз.


5. Реализация пользовательского интерфейса в Borland C++

5.1 Общие принципы

При внимательном рассмотрении перечисленных в разделе 2 видов пользовательского интерфейса можно заметить, что во всех случаях ввод и вывод информации производятся отдельно от основных вычислений в программе. Общий подход к проектированию приложений заключается в том, чтобы отделить интерфейсную часть от вычислительной. Вычислительная часть должна быть построена таким образом, чтобы как можно меньше зависеть от пользовательского интерфейса, от способов ввода и вывода информации. Все исходные данные передаются в вычислительное ядро стандартными методами, как правило, через параметры функций. Ядро возвращает результаты и, возможно, информацию о возникших ошибках. Интерфейсная часть самостоятельно интерпретирует эту информацию и сообщает пользователю результаты выполнения.

Вычислительная часть программы не должна самостоятельно выводить на экран какие-либо сообщения (исключение составляют сообщения, выводимые в отладочных целях, но их в финальной версии программы также быть не должно). Кроме того, она не должна завершать работу программы (за исключением ситуаций, когда нормальное продолжение работы в принципе невозможно, например, при сильных повреждениях служебных структур в памяти).

Для отделения одной части от другой в Borland C++ их следует просто вынести в отдельные функции. Основное правило при распределении кода по функциям заключается в том, чтобы для каждой функции определить ее принадлежность к интерфейсу или вычислительной части. По возможности следует не допускать появления функций, которые по поведению можно отнести и в ту, и в другую часть.

Основное требование к интерфейсной части обеспечивать максимальную защиту от ошибок ввода. Контроль сложных зависимостей между вводимыми данными, которые определяются типом выполняемой задачи, обычно выполняется ядром. В то же время интерфейс в состоянии отследить простые ошибки: ввод строки вместо числа, ввод числа за пределами заданного диапазона и т.п. Проверкам «на глупость» должны подвергаться все данные, вводимые пользователем.

5.2 Консольный интерфейс

Консольный интерфейс достаточно просто реализуется с помощью стандартных функций ввода-вывода: printf, scanf, puts, getch. Перед выводом можно очистить экран, чтобы предыдущие сеансы работы с программой не отвлекали пользователя. Для некоторых видов программ, особенно для системных утилит, очистка экрана является нежелательной, т.к. информация о предыдущих запусках может потребоваться пользователю. Впрочем, к учебным программам это отношения не имеет, и экран лучше все-таки очистить.

Перед каждым запросом данных необходимо вывести пользователю приглашение для ввода этих данных, например: «Введите коэффициент a». Если ввод производится по сравнительно сложным правилам, их необходимо также вкратце описать перед вводом (например, при вводе массива нужно сначала спросить число элементов N, а потом указать, что элементы вводятся N раз).

Поскольку после завершения программы на экране появляется оболочка Borland C++ и закрывает результаты расчетов, желательно приостанавливать выполнение программы до нажатия клавиши после вывода результатов. При этом пользователю нужно вывести соответствующее сообщение.

Кроме того, ввод данных можно осуществлять не стандартными функциями, а рассмотренными ниже функциями ввода с редактированием. Это позволит сделать интерфейс более дружественным пользователю, особенно в случае, когда расчеты можно повторить (во второй и последующих итерациях можно предлагать пользователю по умолчанию предыдущие значения параметров).

В соответствии с принципами разделения интерфейса и вычислительного ядра ввод, вывод и вычисления следует размещать в разных функциях. Общую логику работы «ввод – вычисления – вывод» можно также вынести в отдельную функцию:

void run()

{

input_data();

calculate();

show_results();

}

Разумеется, прототипы функций ввода input_data(), вычислений calculate() и вывода show_results() могут быть (и будут) другими, зависящими от конкретной программы и способов передачи данных в ядро. Такой подход позволяет легко организовать циклическое выполнение расчетов. Для этого функцию run() нужно вызывать в do…while-цикле, выход из которого осуществляется при отрицательном ответе на вопрос «продолжить?».

В остальном программирование консольного интерфейса, как правило, не вызывает затруднений.

5.3 Простое меню

Простое меню отличается от консольного интерфейса в первую очередь последовательностью выполнения операций. Программа обязательно зацикливается, условие выхода из цикла – выбор пункта меню «Выход». Внутри цикла размещается запрос номера меню и его обработка. Запрос может производиться функциями scanf, getch и т.п. Обработка обычно реализуется оператором switch, в котором для каждого пункта меню предусмотрена отдельная ветка case, а все остальные значения «тихо» игнорируются. Уведомлять пользователя о выборе неправильного пункта меню необязательно, это может его раздражать (например, при случайном промахе в процессе нажатия клавиши).

Основная интерфейсная функция может выглядеть так:

void run()

{

//... вывод меню на экран

int cont_menu_loop=1;

do

{

int sel_menu;

//... ввод sel_menu любым удобным способом

switch (sel_menu)

{

case 0:     //ввод значения a

a=input_float();

break;

case 1:     //ввод значения b

b=input_float();

break;

//...

case 4:     //вычисления и вывод результатов

calculate();

show_results();

break;

case 5:     //выход

cont_menu_loop=0;

break;

}

} while (cont_menu_loop);

}

Если меню используется как часть более сложного пользовательского интерфейса, то вывод меню и выбор пункта можно вынести в отдельную функцию. Этой функции можно передавать массив строк с названиями отдельных пунктов, а возвращаемое значение (номер выбранного пункта) анализировать в операторе switch. Такой подход в дальнейшем позволяет легко перейти от меню одного типа к меню другого типа, например, от простого (см. рис. 5, а) к меню с перемещением курсора (см. рис. 5, б).

5.4 Меню с перемещением курсора

Основное отличие этого варианта меню от простого заключается в способе ввода переменной sel_menu. Если в простом меню она вводится непосредственно пользователем, то в данном варианте ввод осуществляется косвенно с помощью клавиш управления курсором. Выбор пункта можно организовать следующим образом:

void highlight_menu(int item,int highlight);

void run()

{

//...

int selected=0;

int sel_menu=0;

do

{

highlight_menu(sel_menu,1); //подсвечиваем пункт меню

int key=getch();

highlight_menu(sel_menu,0); //временно гасим пункт меню

switch (key)

{

case 0:

key=getch();

switch (key)

{

case UP:

sel_menu=(sel_menu-1+max_menu)%max_menu;

break;

case DOWN:

sel_menu=(sel_menu+1)%max_menu;

break;

}

break;

case ENTER:

selected=1;

break;

}

} while (!selected);

//...

}

В приведенном фрагменте кода функция highlight_menu выводит элемент меню с заданным номером с включенной (highlight != 0) или выключенной (highlight = = 0) подсветкой. Данную функцию можно реализовать различными способами. Как правило, подсветка производится с помощью установки соответствующих атрибутов текста или вызовом функций highvideo и lowvideo. В зависимости от реализации в highlight_menu может потребоваться передача дополнительных параметров, описывающих меню (например, массив строк с названиями пунктов, размеры меню на экране и т.п.).

5.5 Ввод строки с редактированием

Стандартные средства Си для ввода данных (функция scanf)  предоставляют пользователю очень мало возможностей. Редактирование вводимого текста возможно только путем удаления символов с конца строки, начальное значение установить нельзя (по умолчанию вводится пустая строка), прокрутки строки, если она не влазит в окно, не предусмотрено (точнее, строка просто переносится по границе окна, что не всегда желательно).

В связи с этим очень часто возникает необходимость в разработке своих средств ввода текста, которые обеспечили бы удобный и привычный пользовательский интерфейс. При этом достаточно организовать ввод текстовой строки, а ввод чисел и более сложных значений (например, интервалов) организуется на основе текстового ввода с последующей обработкой введенной строки (например, чтением числа с помощью функции strtol).

Рассмотрим следующую функцию ввода текста с редактированием:

int inputstr(char* str,int maxlen)

{

int x=wherex(),y=wherey(),curlen=strlen(str);

int pos=curlen;

char firstkey=1;

highvideo();

cprintf("%-*s",maxlen,str);

lowvideo();

gotoxy(x+pos,y);

_setcursortype(_NORMALCURSOR);

int exitcode=-1;

while (exitcode<0)

{

int key=getch();

switch (key)

{

case 0:

key=getch();

switch (key)

{

case LEFT:

if (pos>0)

--pos;

break;

case RIGHT:

if (pos<curlen)

++pos;

break;

case DELETE:

if (pos<curlen)

movmem(str+pos+1,str+pos,curlen-pos);

break;

case HOME:

pos=0;

break;

case END:

pos=curlen;

break;

}

break;

case BACKSPACE:

if (pos>0)

{

--pos;

movmem(str+pos+1,str+pos,curlen-pos);

}

break;

case ESC:

exitcode=0;

break;

case ENTER:

exitcode=1;

break;

default:

if (key>=' ')

{

if (firstkey)

{

pos=0;

str[0]=0;

}

if (curlen<maxlen)

{

movmem(str+pos,str+pos+1,curlen-pos+1);

str[pos]=key;

++pos;

}

}

}

curlen=strlen(str);

firstkey=0;

gotoxy(x,y);

cprintf("%-*s",maxlen,str);

gotoxy(x+pos,y);

}

_setcursortype(_NOCURSOR);

gotoxy(x,y);

return exitcode;

}

Данная функция организует ввод строки ограниченной длины с возможностью перемещения курсора клавишами Left, Right, Home, End и удаления символов клавишами Delete и Backspace. Ввод завершается при нажатии Enter либо Esc, при этом возвращаемое значение показывает, какая из клавиш была нажата. Это позволяет в вызывающей функции определить, отказался пользователь от ввода или подтвердил его. Если первая нажатая клавиша приводит к вводу символа, то старое содержимое строки очищается. Такая особенность позволяет легко вводить новые данные вместо старых. В то же время, если первой нажатой клавишей была клавиша редактирования, старое содержимое сохраняется.

Перед началом ввода функция устанавливает нормальный вид курсора, а после окончания ввода скрывает текстовый курсор. Это позволяет использовать функцию в интерфейсах-меню и интерфейсах со свободной навигацией, не прибегая к дополнительным вызовам _setcursortype.

При редактировании строки ее содержимое в буфере str перемещается функцией movmem, которая предназначена для копирования участка памяти. Для использования этой функции необходимо подключить заголовочный файл <mem.h>.

Приведенная функция inputstr может использоваться в качестве замены scanf, при этом интерфейс становится более дружественным, что благоприятно сказывается на впечатлении пользователя от программы. Для ввода чисел различных типов можно написать отдельные функции, преобразующие число в строку, вызывающие inputstr и затем преобразующие полученную строку обратно в число.


6. Практические задания

6.1 Контрастность атрибутов

Написать функцию, получающую байт атрибутов и возвращающую 0, если цвета фона и тона в этом байте совпадают, и ненулевое значение, если они различны.

6.2 Разработка интерфейса

Разработать описание пользовательского интерфейса для программы «Будильник».

Исходными данными для программы являются:

-    время, на которое установлен будильник;

-    флажок, показывающий, включен будильник или выключен;

-    период повторения будильника: однократное срабатывание, включение каждый день, включение раз в неделю.

Для программы требуется разработать консольный интерфейс, интерфейс-меню и интерфейс со свободной навигацией. Результатом разработки является текстовое описание запросов, пунктов меню или компонентов интерфейса соответственно.


7. Лабораторные задания

7.1 Решение квадратного уравнения

Написать программу квадратного уравнения, имеющую консольный интерфейс или интерфейс, основанный на простом меню. Все коэффициенты уравнения вводятся пользователем. При вводе коэффициентов должна предоставляться возможность редактирования вводимого значения.

Если уравнение имеет один корень, то нужно выводить только одно значение. Если уравнение не имеет корней, выводится соответствующее сообщение.

Замечание: при написании программы необходимо обращать внимание на отделение пользовательского интерфейса от вычислительной части.

7.2 Построение графика произвольной функции

Написать программу, строящую график функции, выбранной пользователем. Выбор функции осуществляется из некоторого фиксированного списка жестко заданных функций. Кроме того, программа должна предоставлять возможность ввода функции с клавиатуры.

Помимо выбора функции, требуется организовать ввод координат области, для которой будет строиться график.

Замечание: парсинг введенного текста можно реализовать рекурсией.


8. Дополнительные задания

8.1 Элемент управления «Список»

Реализовать программно элемент управления «Список с прокруткой» для текстового режима. Работа со списком должна сводиться к вызову одной функции, в которую передаются координаты области на экране, которую занимает список, и массив строк, составляющих список. Функция самостоятельно организует интерфейс для выбора элемента.

Каждая строка представляет один элемент списка. В строках не должно быть символов возврата каретки и перевода строки. Элементы должны выводиться в заданном окне. Количество строк в списке может как превышать высоту окна, так и быть меньше ее. В первом случае необходимо предусмотреть прокрутку содержимого в окне, во втором – обеспечить корректный выбор только тех позиций в окне, которые содержат строки списка (другими словами, курсор не должен выходить за пределы и окна, и списка).

Текущий элемент подсвечивается каким-либо цветом, заданным разработчиком. Выбор элемента осуществляется нажатием клавиш «Up» (перемещение курсора вверх) и «Down» (перемещение курсора вниз).

Подтверждение выбора (и выход из функции) осуществляется при нажатии клавиш Enter, Esc, Left, Right, Tab, Shift+Tab. Каждой из этих клавиш должен соответствовать определенный код, который также возвращается функцией выбора из списка. Этот код может использоваться вызывающей функцией для того, чтобы определить дальнейшее действие: переход к предыдущему (Shift+Tab, Left) или следующему (Tab, Right) элементу управления, выполнение основного действия программы (Enter), выход из программы (Esc).

Помимо указанного кода функция должна возвращать индекс выбранного элемента списка.

8.2 Ввод строки с редактированием и прокруткой

Написать функцию ввода текстовой строки с редактированием. При вызове функции ей передается длина поля ввода (максимальная длина отображаемой на экране части строки), а также координаты первого символа поля ввода на экране. Поле ввода однострочное, т.е. имеет высоту, равную 1 знакоместу.

Длина вводимой строки может превышать размеры поля ввода. Если в процессе ввода или перемещения курсора по строке текущая позиция ввода выходит за пределы поля, необходимо производить прокрутку строки в окне.

По усмотрению разработчика максимальная длина строки может либо передаваться в функцию, либо определяться объемом доступной динамической памяти. В первом случае буфер под строку резервирует вызывающая функция, во втором – функция ввода.

Функция ввода должна предоставлять следующие возможности по редактированию текста: перемещение курсора, ввод символа, удаление символа над курсором (клавиша Delete), удаление символа перед курсором (клавиша Backspace).

Если часть строки находится за пределами поля, желательно показывать это каким-либо образом (например, ставить выделенные цветом символы «<» и «>» в начале и конце поля ввода, если есть текст за пределами поля с соответствующей стороны).


Библиографический список

1.         Иванова Г.С. Технология программирования: Учебник для вузов. / Г.С. Иванова. М.: Изд-во МГТУ им. Н.Э. Баумана, 2002.

2.         Фролов А., Фролов Г. Программирование видеоадаптеров / А. Фролов, Г. Фролов. М.: Диалог-МИФИ, 1993.

3.         Подбельский В.В. Программирование на языке Си. Учеб. пособие. / В.В. Подбельский, С.С. Фомин, М.: Финансы и статистика, 2004. – 600 с.

4.         Керниган Б. Язык программирования Си / Б. Керниган, Д. Ритчи. М.: Финансы и статистика, 1992. – 272 с.


Страницы: 1, 2


Новости

Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

  скачать рефераты              скачать рефераты

Новости

скачать рефераты

Обратная связь

Поиск
Обратная связь
Реклама и размещение статей на сайте
© 2010.