Смекни!
smekni.com

Организация интерфейса пользователя (стр. 3 из 4)

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. Реализация пользовательского интерфейса в BorlandC++

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

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

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

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

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

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

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

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

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

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

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

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)

{

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

a=input_float();

break;

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

b=input_float();

break;

//...

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

calculate();

show_results();

break;

case5: //выход

cont_menu_loop=0;

break;

}

} while (cont_menu_loop);

}

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