Руководство по программированию для SEAL

Левицкий Александр (С) 2001

alexandrx@mail.ru

seal.htmlplanet.com

Данное руководство основано на оригинальной документации Introduction into Seal programming, созданной основателем SEAL из Словакии Michal Stencl с доработками и собственными комментариями для лучшего восприятия материала.

К читателю.

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

Содержание:

1.Вступление

2.Основы программирования для SEAL.

3.Создание окон и функции обработки сообщений.

4.Углубление знакомства с объектами и функцией обработки сообщений.

5.Объекты STATTEXT , TEXTLINE и EDITOR. 

6.Объекты LIST, LISTBOX, HISTORY.

7.Объект MENU.

8.Немного о диалоговых окнах.

9.Многозадачные циклы.

 

Вступление

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

Что такое SEAL.

Конечно я не профессиональный писатель, но постараюсь преподать вам материал в наиболее подходящей форме.

Итак, весной 2000 года я обнаружил некую GUI под названием SEAL. Скачать ее не составило труда, так как она занимала всего 1,2 Мб. Набрел я на нее почти случайно (хотя случайностей в жизни не бывает) используя одну из многочисленных ссылок на www.freedos.com. Тогда я еще и подозревать не мог, что вскоре мне станет интересно создавать под SEAL свои программы, и что я очень быстро овладею искусством программирования под SEAL всего за несколько недель абсолютно не напрягаясь.

Что же такое SEAL? В руководстве по программированию в одной из первых строк сказано: Seal is free desktop environment for DOS. It has own graphics vision and can run dynamic libraries and applications. Это переводится примерно как: SEAL - бесплатная графическая оболочка для старого доброго DOS. Имеет свое собственное графическое представление и может запускать динамические библиотеки и приложения. Иными словами, это нечто напоминающее Windows но немного другое и бесплатное.

Написан SEAL от начала до конца на языке C с применением библиотеки Allegro. Но это совсем не означает, что для программирования программ вам понадобится знать ее. Скажу даже больше, знание Allegro вам нужны только в том случае, если вы собираетесь создавать собственный дистрибутив SEAL. А то что именно понадобится вам для программирования под SEAL заслуживает отдельной главы.

Что нужно для программирования под SEAL.

Для программирования под SEAL вам понадобится:

Теперь обо всем по порядку: начальные знания С - это самый главный фактор. От вас совсем не требуется, что бы вы были С-гуру но все таки вы должны знать как программировать на этом языке хотя бы для DOS. Именно с этим багажом можно будет без проблем начать залазить в "новые для вас места". Возможно вам понадобится еще меньше, чем я рассчитываю, просто попробуйте…

Компилятор программ DJGPP v2 - если он у вас есть - это просто здорово, а если нет, тогда вам необходимо его скачать с одного из зеркал Симтела. Я например скачивал с адреса mirror.direct.ca/pub/simtelnet/gnu/djgpp

DJCRX203 ZIP 639 989 13.04.00 12:18 DJCRX203.ZIP

DJDEV203 ZIP 1 538 147 13.04.00 12:37 DJDEV203.ZIP

DJLSR203 ZIP 1 515 665 13.04.00 13:57 DJLSR203.ZIP

DJTST203 ZIP 870 698 13.04.00 19:45 DJTST203.ZIP

DJTZN203 ZIP 422 575 13.04.00 19:49 DJTZN203.ZIP

DJTZS203 ZIP 236 508 13.04.00 19:50 DJTZS203.ZIP

GCC2952B ZIP 1 932 910 13.04.00 22:59 GCC2952B.ZIP

LGP2952B ZIP 494 493 15.04.00 13:46 LGP2952B.ZIP

TXI40B ZIP 646 656 15.04.00 13:38 TXI40B.ZIP

BNU295B ZIP 2 567 839 20.04.00 18:19 BNU295B.ZIP

FAQ230B ZIP 679 865 15.04.00 18:01 FAQ230B.ZIP

GDB418B ZIP 1 180 514 18.04.00 17:52 GDB418B.ZIP

INST01AS ZIP 89 123 07.11.96 13:34 INST01AS.ZIP

MAK379B ZIP 268 863 26.05.01 14:13 MAK379B.ZIP

Объем приблизительно 11 Мб, но не пугайтесь этому сильно. Трафик очень быстрый и выкачка не займет много времени. Можете попробовать скачать с другого зеркала для увеличения трафика. Не забудьте скачать инсталляционную программу. Последние цифры в именах файлов - означают версии, поэтому, если там есть файлы с более новыми версиями, то скачивайте именно их.

Заголовочные файлы SEAL - как правило поставляются вместе с дистрибутивом, но если таковых получить не удалось, то можно зайти на страничку Михала www.home.sk/public/seal и скачать от туда весь исходный код SEAL в котором находятся и библиотеки, и примеры программ. Вот что находится в моей директории для заголовочных файлов SEAL:

ALLEGRO H 114 996 14.02.00 6:26 ALLEGRO.H

APP H 14 073 16.02.00 4:02 APP.H

BUTTON H 13 022 17.02.00 12:41 BUTTON.H

DIALOGS H 13 799 17.02.00 16:54 DIALOGS.H

EDITOR H 8 451 13.02.00 19:40 EDITOR.H

HTMLWIN H 4 389 13.02.00 19:40 HTMLWIN.H

IODLG H 16 477 13.02.00 19:41 IODLG.H

LANG H 2 741 13.02.00 19:41 LANG.H

LOAD_HTM H 13 763 13.02.00 19:42 LOAD_HTM.H

MENUS H 10 346 13.02.00 19:42 MENUS.H

SCROLLER H 7 347 13.02.00 19:44 SCROLLER.H

SEAL H 92 803 17.02.00 11:48 SEAL.H

DESKTOP H 6 344 17.02.00 3:00 DESKTOP.H

Дистрибутив SEAL и библиотеку Allegro можно раздобыть на той же самой страничке SEAL www.home.sk/public/seal . Не смущайтесь что все выглядит немножко устаревшим. Все что опубликовано здесь - очень стабильные версии.

Последний пункт из необходимого вам придется разрабатывать самому.J

2.Основы программирования для SEAL.

Ну вот мы и добрались до второй главы. Эта глава будет содержать массу интересных тем, вы загляните в содержимое seal.h, напишите главную функцию приложения, вы научитесь компилировать программы, узнаете немного об апишных функциях SEAL и даже создадите пресловутую программу 'hello world'. В общем пристегните ремни, включите CD с легкой музыкой и набрасывайтесь на материал второй главы.

Типы данных.

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

l_long

long

l_int

int

l_word

unsigned l_int

l_dword

unsigned l_long

l_big

l_long l_long

l_char

char

l_byte

unsigned l_char

l_ptr

void*

l_rect

l_int

l_color

int

l_font

void*

l_text

char*

Немного объяснений… Если ранее вы писали:

int a;

char *string1 = "Hello World!";

то теперь, чтобы не отходить от принципов SEAL нужно будет записать:

l_int a; l_text string1 = "Hello World!";

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

Я так думаю, что касается типов, вам уже все понятно.

Функции из SEAL API. Немного о DLX.

Стоит теперь рассказать о DLX. Что это за зверь и с чем его едят?… DLX - тема вопросов и споров дистрибьюторов SEAL. Одни из них говорят, что DLX - не самая лучшая технология для SEAL, проще говоря - полный отстой, другие говорят что это наоборот классно и перспективно. Спорить и выражать свою точку зрения на эту тему я не буду, скажу лишь, что DLX - это самый основной механизм запуска программ под SEAL. А теперь поподробнее.

DLX - это технология на основе которой создаются программы и динамические библиотеки для SEAL. По своей сути DLX библиотеки очень похожи на DLL библиотеки в Windows. На основе их создан SEAL API. SEAL API - это вся совокупность объектов и функций в SEAL. Как я уже заметил ранее в предыдущей главе, SEAL очень похож на Windows, хотя во многом создавать программы для него легче чем для пресловутого детища Microsoft. Однако есть и свои подводные камни, о которых я расскажу позднее. А пока я расскажу о функциях из SEAL API.

Стандартный набор апишных функций включает в себя почти весь набор стандартных функций С. Например, вы сможете использовать те самые sscanf, fopen, strcmp… при учете, что включите их родной заголовочный файл директивой #include. Все эти функции постоянно находятся в SEAL и помогают ему выполнять программы. Специальной библиотеки для компиляции функций в ваш EXE не существует, однако все они прошиты в SEAL API и компилятору остается только оставить свой отпечаток в вашем EXE или DLX в котором просто упоминается имя функции и больше ничего. Именно поэтому исполняемые файлы занимают мало места на диске.

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

! Однако есть и исключения. Например, я так и не смог воспользоваться fcvt, gcvt, ecvt из <stdlib.h>. Потом выяснилось, что мистер Stencl просто не знал о существовании таковых.

Если вам что-то не понятно в этом разделе главы, то просто оставьте закладку до лучших времен и переходите к следующему разделу.

 

Специальные функции из SEAL API, или о том как облегчить себе жизнь.

В SEAL есть так же и специальные функции, некоторые из которых можно обойти, но многими можно и умело воспользоваться. Они разделены по группам. Все они хорошо описаны в руководстве по программированию для SEAL, а их прототипы находятся в <seal.h>. Именно поэтому я настоятельно рекомендую заглянуть в эти два места. Но все же не затронуть эту тему вообще я не могу. Мы коснемся ее лишь небольшим краем, потому что мне как можно скорее хочется научить вас делать программу "Hello world".

Первая большая группа именуется String functions. В ней находятся функции для работы со строками.

Затем идет группа Error function, представленная всего лишь одной функцией seal_error .

Далее следуют функции для работы с памятью (Memory fuctions). Это адаптированные версии старых и хорошо известных free, malloc, calloc… Однако можно использовать и стандартные функции С, так что их изучение можно пока опустить.

Следующий раздел Input/output functions - весьма полезные функции для работы с файлами и директориями.

Группа Driver's functions отвечает за работу драйверов, а группа INI's functions сделает удобным доступ к ini файлам.

Последняя группа Application/Libary functions предназначена для запуска файлов и создания библиотек. Без них не обойтись, если вы решили например создать свою библиотеку DLX или запустить из своей программы приложение для DOS.

 

Главная функция.

Всем, кто программировал на С известно, что выполнение программы начинается с некой функции. Например, в Unix и Dos она называется 'main' в Windows она называется 'WinMain'. Подобная функция существует и в SEAL. Давайте составим программу, которая имеет только пустую функцию и больше ничего.

Листинг 2.1 'First.c'


#include "allegro.h"

#include "seal.h"

app_begin ( void ) {

// Эта программа ничего не делает

} app_end;


И это все. Вы можете откомпилировать эту программу. Для этого нужно войти в SEAL, затем запустить приложение Visual DJGPP и выбрать опцию Make EXE. Visual DJGPP - это программа, которая облегчит вам жизнь в отношении компиляции несложных программ, не использующих дополнительные библиотеки. Теперь мы часто будем использовать этот нехитрый инструмент.

Примечание: все примеры представленных здесь программ находятся в архиве simple.zip. Если вы выкачали этот документ не с его родного места, вы можете зайти на мою страничку, посвященную SEAL и выкачать оригинальную последнюю версию, содержащую все файлы примеров. seal.htmlplanet.com

Программа Hello.c и окна сообщений.

После того, как мы изучили с вами главную функцию, самое время написать 'сложнейшую' программу, которая появляется во всех руководствах по языкам программирования и программирования для различных ОС. Имя ей 'Hello world!'. Так как я не рассказывал Вам еще о графических объектах и прочих примудростях, то наш Hello world будет просто выведен в окно сообщений (message box). Для тех, кто имел дело с программированием для Windows, это понятие обычное: окно сообщения выводит информацию в виде маленького окошка с одной - тремя кнопками. Мы используем апишную функцию SEAL для рисования этого окна именуемую 'msgbox'. Она содержится в заголовочном файле <iodlg.h>. Прототип ее таков:

l_dword msgbox ( l_dword wflags, l_dword bflags, l_text in_text, ... );

wflags - тип окна. Используйте следующие константы, определенные в seal.h:

MW_WARNING

просто сообщение (типа "обратите внимание").

MW_ERROR

сообщение об ошибке

MW_INFO

Информация

MW_QUESTION

Вопрос

MW_UNAVAILABLE

недоступное окно сообщения

Bflags - кнопки, которые появятся в окне.

MB_CLOSE

Конпка Close

MB_CANCEL

Конпка Cancel

MB_YES

Конпка Yes

MB_NO

Конпка No

MB_HELP

Конпка Help

MB_OK

Конпка OK

Когда вы выбираете одну из кнопок функция возвращает вам одно из значений:

Нажатая кнопка

Возврашаемое значение

MB_CLOSE

MSG_CLOSE

MB_CANCEL

MSG_CANCEL

MB_HELP

MSG_HELP

MB_YES

MSG_YES

MB_NO

MSG_NO

MB_OK

MSG_OK

Вот кажется и все. Пора приступить к написанию программы.

Листинг 2.2 'Hello.c'


#include "allegro.h"

#include "seal.h"

#include "iodlg.h"

// шаблон главной функции

app_begin ( void ) {

if (ap_process == AP_INIT)

{

// здесь начинается тело программы

msgbox (MW_WARNING, MB_OK, "Hello world");

}

} app_end;


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

Вот мы и пробежали по всем строкам второй главы. Теперь мы умеем уже многое. Но впереди нас ждет еще более интересная глава, так что не стоит расслабляться, а освободите компакт дисковод от музыкального CD и смените обстановку на полную тишину.

 

3. Создание окон и функции обработки сообщений.

В этой главе вы узнаете об нескольких объектах SEAL, о структуре t_rect, Создадите приложение, рисующее окно и имеющее функцию обработки сообщений. 

Размышления об объектах для SEAL.

Шаг за шагом наш марафон усложняется. Но я надеюсь, что ваша отдышка не портит вам настроение на дальнейшее изучение. Пора познакомить вас с объектами.

SEAL был составлен в объектном стиле. Но не нужно путать это с объектно-ориентированным программированием. Здесь используются структуры, указатели на структуры и т.д. Но все это сделано так, что иногда кажется что программируешь на С++ ,а не на С. Для удобства эти структуры называют объектами. Мы тоже не будем отрываться от этого правила.

Объектов в SEAL довольно большое множество. Некоторые используются редко, некоторые почаще, а без некоторых не обходится ни одно мало-мальски сложное приложение.

Самыми главными объектами и иерархии являются объекты t_object.

Запомните: все типы объектов в SEAL начинаются с символов t_, а указатели на них с символов p_. Например, t_object, p_object, t_appwin, p_appwin.

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

Объект APPWIN и структура t_rect.

Давайте мы с вами познакомимся с наиболее часто встречающимся объектом APPWIN. Что это такое? Это объект, отвечающий за рисование обычного окна приложения. Именно его мы рассмотрим первым. Но прежде чем мы сделаем это, я бы хотел познакомить вас со структурой, задающей размеры графических объектов.

Именуется эта структура t_rect. Она задает размеры и местоположение объекта. Для того, чтобы облегчить программирование в SEAL имеется функция, позволяющая до минимума сократить сложность создание такой структуры. Ее прототип расположен в <seal.h> и имеет следующий вид:

t_rect rect_assign (l_rect ax, l_rect ay, l_rect bx, l_rect by);

Из второй главы мы знаем, что l_rect - это не более чем число типа int. Но не путайте его со структурами t_rect. Первый и второй параметр - это положение левого верхнего угла объекта, а третий и четвертый - это положение правого нижнего угла.

Теперь пора поговорить об объекте окна. Для начала его нужно объявить. По традиции объявляется только указатель на объект. Делается это так:

p_appwin main_window;

Теперь объявим переменную t_rect.

t_rect rt;

Заполним структуру значениями, вызвав функцию rect_assign.

rt = rect_assign (100, 100, 200, 200);

 

Функция обработки сообщений.

Функция обработки сообщений может называться функцией обработки событий.

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

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

К примеру: вы создали объект "кнопка". При создании объекта вы выделяете ему номер сообщения, скажем 1000501. Если вы нажали кнопку, то номер сообщения передается в функцию обработки сообщений. Там проверяется условие на совпадение номера сообщения, и, если он совпадает, выполняется код предназначенный для этой кнопки.

Возможно это еще немного сложно для вас, но не расстраивайтесь, скоро вы все поймете.

Функция обработки сообщений должна иметь прототип:

void trans_ev (p_object obj, p_event event);

obj - указатель на объект, который вызвал сообщение

event - структура, содержащая сведения о сообщении.

Замечание: функция обработки сообщений не нуждается в декларировании т.е. писать ее прототип не нужно.

 

Создаем первое оконное приложение.

К этому моменту у нас уже подготовлен указатель, функция обработки сообщений и переменная t_rect. Теперь вызывается функция, которая чертит окно.

main_window = appwin_init(_malloc (sizeof(t_appwin)), rt, "Window application", 2, ap_id, &tarns_ev);

Первый параметер - указатель на структуру APPWIN. В данном случае представлен функцией, которая выделяет память.

Далее следует параметр типа t_rect, определяющий область окна на экране.

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

После создания окна необходимо поместить его на экран. Объект OBJECT содержит функцию 'insert' которая помещает объект в теле другого объекта. Т.к. у наше окно самый старший объект, то мы помещаем его прямо на рабочий стол. Этот объект называется 'desktop'. Выглядит это следующим образом:

OBJECT (desktop)-> insert (OBJECT(desktop), OBJECT (main_win));

Вот и все. Этот тип объявления присущ большинству объектов в SEAL. В следующих главах это будет заметно. А пока давайте соберем программу воедино и откомпилируем ее.

Листинг 3.1 WinApp.c


// включаем заголовочные файлы

#include "allegro.h"

#include "seal.h"

#include "iodlg.h"

 

p_appwin main_win;

t_rect rt;

// прототип функции

void win_paint ();

// функция обработки сообщений

void trans_ev (p_object obj, p_event event) {

}

void win_paint () {

t_rect rt;

rt = rect_assign (100, 100, 300, 300);

main_win = appwin_init(_malloc (sizeof(t_appwin)),

rt,

"Window application",

2,

ap_id,

&trans_ev);

OBJECT (desktop)-> insert (OBJECT(desktop), OBJECT (main_win));

}

// шаблон главной функции

app_begin ( void ) {

if (ap_process == AP_INIT) {

win_paint();

}

} app_end;


Теперь мы получили полноценное оконное приложение. Можно опять включить компакт диск и переходить к следующей главе.

 

4. Углубление знакомства с объектами и функцией обработки сообщений.

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

Объект BUTTON

Что можно сказать, описывая этот объект. Это просто обычная кнопка. Я надеюсь, все знают, что это такое. Когда вы создаете кнопку, вы определяете номер сообщения, которое будет передаваться в функцию обработки сообщений. Если функция знает об этом номере, то она произведет некоторые действия, которые вы определили. Далее вы сможете увидеть, как это реализуется, а пока давайте посмотрим, каким образом создается объект 'BUTTON'.

Создание объекта 'BUTTON' схоже с созданием объекта 'APPWIN'. В прототипе эта функция выглядит следующим образом:

p_button button_init ( p_button o, t_rect r, l_text caption,

l_dword message, l_int flags );

Параметр flags может быть представлен следующими константами:

BF_NORMAL

BF_DEFAULT

BF_PUSH

BF_DARROUND

BF_UNDERSEL

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

Параметр caption - текст на кнопке.

Параметр message - номер сообщения.

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

Теперь воспользуемся уже созданной программой appwin.c и на ее начнем создавать новую.

Для начала создадим два указателя на кнопки:

p_button but_close;

p_button but_about;

Затем воспользуемся ранее описанной функцией и создадим 2 объекта 'BUTTON':

rt = rect_assign ( 30, 30, 120, 60);

but_close = button_init ( _malloc (sizeof(t_button)), rt, "Close", 100010, BF_NORMAL );

rt = rect_assign ( 30, 65, 120, 95);

but_about = button_init ( _malloc (sizeof(t_button)), rt, "About", 100011, BF_NORMAL );

Четвертыми параметрами в каждой из функций являются номера сообщений.

Теперь нужно воспользоваться функцией insert и поместить эти объекты в окно.

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (but_close));

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (but_about));

 

Обработка сообщений.

Вернемся в функции обработки сообщений. Мы определили две кнопки и дали им номера сообщений 100010 и 100011. Теперь посмотрим, как будут обрабатываться эти сообщения.

void trans_ev (p_object obj, p_event event) {

if (obj->process & PH_PREPROCESS) {

if (event->message == 100010){

event->message = MSG_CLOSE;

}

if (event->message == 100011){

msgbox (MW_WARNING, MB_OK, "Message application\nversion 1.0");

clear_event (event);

}

}

}

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

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

Наверное, вам не совсем понятна строка

event->message = MSG_CLOSE;

Дело в том, что большинство номеров сообщений определяете вы, но SEAL имеет собственные номера системных сообщений. MSG_CLOSE - это сообщение на закрытие окна. Мы просто преобразуем сообщение, которое посылает нажатие кнопки в сообщение закрытия окна. Это сообщение обрабатывает сама система, поэтому функция для очистки сообщения clear_event() в данном случае уже не нужна.

Можете посмотреть на номера системных сообщений. Все они определены в <seal.h>.

 

Соберем программу воедино.

 

Настало время все соединить. Наша новая программа будет содержать все то, что мы разработали на протяжении этой главы.

Листинг 4.1 Msgwin.c


#include "allegro.h"

#include "seal.h"

#include "iodlg.h"

#include "button.h"

 

p_appwin main_win;

t_rect rt;

// указатели на кнопки

p_button but_close;

p_button but_about;

 

// прототип функции

void win_paint ();

// функция обработки сообщений

void trans_ev (p_object obj, p_event event) {

if (obj->process & PH_PREPROCESS) {

if (event->message == 100010){

event->message = MSG_CLOSE;

}

if (event->message == 100011){

msgbox (MW_WARNING, MB_OK, "Message application\nversion 1.0");

clear_event (event);

}

}

}

void win_paint () {

t_rect rt;

rt = rect_assign (100, 100, 300, 300);

main_win = appwin_init(_malloc (sizeof(t_appwin)),

rt,

"Window application",

2,

ap_id,

&trans_ev);

OBJECT (desktop)-> insert (OBJECT(desktop), OBJECT (main_win));

rt = rect_assign ( 30, 30, 120, 60);

but_close = button_init ( _malloc (sizeof(t_button)), rt, "Close", 100010, BF_NORMAL );

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (but_close));

 

rt = rect_assign ( 30, 65, 120, 95);

but_about = button_init ( _malloc (sizeof(t_button)), rt, "About", 100011, BF_NORMAL );

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (but_about));

 

}

// шаблон главной функции

app_begin ( void ) {

if (ap_process == AP_INIT) {

win_paint();

}

} app_end;

 


 Теперь откомпилируем ее и посмотрим как она работает. Захватывающе, неправда ли?…

5.Объекты STATTEXT, TEXTLINE и EDITOR.

Настало время поговорить об объектах для ввода вывода текстовых строк.

Объект STATTEXT осуществляет вывод в объекты строк символов. Объекты TEXTLINE и EDITOR отображают поля для ввода текстовой информации с клавиатуры. Мы затронем самые необходимые свойства и методы данных объектов, а затем составим программу, демонстрирующую все три объекта. Начнем с самого простого из этих трех объектов.

Объект STATTEXT.

Зачастую необходимо выводить в окна различные надписи, заголовки и т.д. Для этого в SEAL имеется стандартный объект STATTEXT. Его свойства и методы находятся в заголовочном файле <dialogs.h>. Инициализирующая функция имеет прототип:

p_stattext stattext_init ( p_stattext o, t_rect r, l_int align,

l_text format, ... );

align - константное значение, определенное в <seal.h>. Просмотрите данный файл и изучите все предлагаемые константы. Приведу пример:

TX_ALIGN_LEFT

Текст прижимается к левой стороне.

TX_ALIGN_CENTERX

Текст располагается по центру.

format, ... - точно тоже, что и в 'printf'.

Замечание: Длинна строки в объекте не может превышать 256 символов. 

Для того, чтобы получить текст из объекта необходимо сделать следующее

STATTEXT(p_object obj)->text;

Данная строка возвращает указатель на текстовую строку из объекта obj.

Давайте теперь выведем текст в окно. Пусть это будет окно из программы appwin.c.

Объявим указатель на объект:

p_stattext text1;

Затем вызовем функцию для инициализации объекта

rt = rect_assign (30, 30, 150, 50);

text1 = stattext_init(_malloc(sizeof(t_stattext)), rt, TX_ALIGN_LEFT, "Hello world!");

И не забудем отобразить объект в окно.

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (text1));

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

Стоит сказать, что программистом из Австрии Флорианом уже разработан объект DYNTEXT, похожий на STATTEXT, который позволит изменять текст в объекте. Но поскольку этот объект еще не стал стандартом, описывать его я не буду.

Потомки 'scanf'. Знакомимся с объектам TEXTLINE и EDITOR.

Было время, когда текст приходилось вводить с консоли через функцию scanf. Прошли годы. Операционные системы изменились. Они уже больше не предлагают пользователю мрачный тестовый режим, а вместо функции scanf в них появились мощные и изящные объекты для ввода тестовых данных. В SEAL такими объектами являются TEXTLINE и EDITOR. Внешне они схожи друг на друга по своим принципам, с той разницей, что в TEXTLINE можно ввести только одну строку, а в EDITOR можно вводить столько строк, сколько вам будет угодно. Для удобства EDITOR содержит еще и полосы прокрутки текста. В общем, давайте посмотрим на это программно - составим программу, где будут фигурировать эти два объекта.

В начале разберемся с инициализацией обоих объектов. Для этого объявим два указателя:

p_textline text2;

p_editor text3;

и проинициализируем их. В начале TEXTLINE:

rt = rect_assign (30, 60, 150, 70);

text2 = textline_init ( malloc(sizeof(t_textline)), rt, 0,

TF_NONE);

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (text2));

Параметр номер три - это предельное количество символов в объекте. Если он установлен в 0, то вы можете ввести столько символов, сколько вам будет угодно.

Параметр номер четыре может быть представлен одной из двух констант.

TF_NONE

разрешается ввод символов с клавиатуры

TF_REWRITEUNABLE

ввод символов с клавиатуры запрещен

В нашем примере разрешается ввод неограниченного количества символов.

Теперь сделаем то же самое для объекта EDITOR: 

rt = rect_assign (30, 60, 150, 70);

text3 = editor_init ( malloc(sizeof(t_textline)), rt, EF_FIXEDFONT);

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (text3));

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

EF_REWRITEUNABLE

запрещается ввод символов с клавиатуры

EF_FIXEDFONT

фиксированный шрифт

Для объектов EDITOR необходимо включить заголовочный файл <editor.h>

Программа.

Как всегда соберем нашу программу в единое целое.

Листинг 5.1 textobjs.c


// включаем заголовочные файлы

#include "allegro.h"

#include "seal.h"

#include "iodlg.h"

#include "editor.h" 

 

p_appwin main_win;

t_rect rt;

p_textline text2;

p_editor text3;

p_stattext text1;

 

// прототип функции

void win_paint ();

// функция обработки сообщений

void trans_ev (p_object obj, p_event event) {

}

void win_paint () {

t_rect rt;

rt = rect_assign (100, 100, 300, 300);

main_win = appwin_init(_malloc (sizeof(t_appwin)),

rt,

"Window application",

2,

ap_id,

&trans_ev);

OBJECT (desktop)-> insert (OBJECT(desktop), OBJECT (main_win));

// STATTEXT

rt = rect_assign (30, 30, 150, 50);

text1 = stattext_init(_malloc(sizeof(t_stattext)), rt, TX_ALIGN_LEFT, "Hello world!");

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (text1));

// TEXTLINE

rt = rect_assign (30, 60, 150, 80);

text2 = textline_init ( malloc(sizeof(t_textline)), rt, 0,

TF_NONE);

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (text2));

// EDITOR

rt = rect_assign (30, 90, 150, 150);

text3 = editor_init ( malloc(sizeof(t_textline)), rt, EF_REWRITEUNABLE);

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (text3));

}

// шаблон главной функции

app_begin ( void ) {

if (ap_process == AP_INIT) {

win_paint();

}

} app_end;


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

6.Объекты LIST, LISTBOX, HISTORY.

С радостью могу сообщить вам, что вы уже прошли половину материала. И если вы осилили первую половину этого руководства, то пройти вторую вам не составит большого труда.

Объект LIST.

Настало время рассказать вам об объектах списочного типа. Поясню, что я имею ввиду. Вы наверняка уже пользовались в Windows графическими объектами, где есть возможность выбора из списка предлагаемого. Это так называемые ListBox и ComboBox. Первый из них выглядит как текстовое поле, где щелчком мыши можно выделить одну или несколько строк. Второй - это, например, список с помощью которого вы выбираете тип или размер шрифта в Microsoft Word. Одним словом, я более чем уверен, что вы уже пользовались данными объектами. Теперь я расскажу каким образом можно внедрить их в SEAL программу.

Для начала нам следует познакомиться с объектом LIST. Объект LIST не имеет графического представления на экране. Это промежуточный объект, который хранит в себе тот самый список строк, который впоследствии будет представлен в LISTBOX или HISTORY. Вы не можете напрямую ввести данные прямо в HISTORY или LISTBOX. Эти объекты в качестве источника данных используют именно LIST. С помощью его вы сможете с легкостью добавлять, удалять, перемещать, сортировать строки. В общем, давайте, как всегда, взглянем на это в программе. На этот раз наше знакомое окно будет содержать в себе объекты HISTORY и LISTBOX, которые, в свою очередь требуют по одному объекту LIST на каждого.

Инициализация объекта LIST не вызовет у вас недоумения. Все делается по знакомой нам уже схеме, стой только разницей, что объект невидим на экране, поэтому вам не понадобится ни переменная типа t_rect, ни функция для размещения объекта. Функция для инициализации имеет следующий прототип:

p_list list_init ( p_list o, void (*func_free)(void *), l_big tag );

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

Объявим два указателя на объекты:

p_list list1;

p_list list2;

А теперь проинициализируем их:

list1 = list_init(_malloc(sizeof(t_list)), &free_listbox_item, 0);

list2 = list_init(_malloc(sizeof(t_list)), &free_listbox_item, 0);

Заполним данными наши объекты. Функция insert выступает здесь в совсем другой роли. Она не выводит объект на экран, а вводит данные в общий список. Для этого так же используется функция new_listbox_item.

list1->insert(list1, new_listbox_item("First", NULL, true, LIF_NONE));

list1->insert(list1, new_listbox_item("Second", NULL, true, LIF_NONE));

list1->insert(list1, new_listbox_item("Third", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("Unix", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("Windows", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("SEAL", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("DOS", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("Linux", NULL, true, LIF_NONE));

collect_by_name(list2, 0); // сортировка по имени

Если вам в процессе выполнения программы захочется удалить одну из нескольких строк, воспользуйтесь функцией free_index.

list2->free_index(list2, 0);

В данном примере удаляется строка с индексом 0.

Или удалите весь список:

list2->free_all(list2);

А затем удалите из памяти и сам объект:

list2->done(list2);

free(list2);

или

dispose_list(p, true);

Объект LIST имеет огромное множество полезных функций, но описывать их у меня нет достаточно времени. Хочется закончить этот документ побыстрее. Если вам не терпится узнать об этом объекте побольше, то загляните в руководство Михала. Я же перечислил самое необходимое, что вам нужно знать.

HISTORY и LISTBOX.

Мы уже создали целых два объекта LIST. Ввели в них данные. Пора представить наши списки на экране. Как обычно объявим указатели на объекты:

p_listbox lbox;

p_history hist;

Все нужные функции для этих объектов находятся в заголовочном файле <dialogs.h>. Инициализировать объекты как всегда не составит особого труда:

// LISTBOX

rt = rect_assign (30, 30, 150, 100);

lbox = listbox_init (_malloc (sizeof (t_listbox)), rt, list2, 0, LF_UNDERSEL);

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (lbox));

// HISTORY

rt = rect_assign (30, 110, 150, 130);

hist = history_init (_malloc (sizeof (t_history)), rt, list1, 100, HF_NONE);

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (hist));

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

Четвертые аргументы - это количество строк для LISTBOX (имеет тип l_byte) и максимальное количество вводимых символов для HISTORY(имеет тип l_int).

Пятыми аргументами являются флаги:

Флаги для LISTBOX:

LF_NONE

обычный объект

LF_UNDERSEL

объект выбирается синхронно с мышью

LF_SELECTABLE

возможность выбора нескольких объектов

LF_SELFLIST

объект LIST удаляется, когда удаляется объект LISTBOX

Флаги для HISTORY:

HF_NONE

обычный объект

HF_REWRITEUNABLE

запрещен ввод данных с клавиатуры

HF_SELFLIST

объект LIST удаляется, когда удаляется объект HISTORY

 

Оконное приложение с объектами LISTBOX и HISTORY.

Создаем программу с нашими объектами. По традиции нам нужно просто добавить ранее написанные строки, а затем откомпилировать и запустить труд этой главы.

Листинг 6.1 listobjs.c


// включаем заголовочные файлы

#include "allegro.h"

#include "seal.h"

#include "iodlg.h"

#include "dialogs.h"

p_appwin main_win;

p_list list1;

p_list list2;

p_listbox lbox;

p_history hist;

t_rect rt;

// прототип функции

void win_paint ();

// функция обработки сообщений

void trans_ev (p_object obj, p_event event) {

}

void win_paint () {

t_rect rt;

rt = rect_assign (100, 100, 300, 300);

main_win = appwin_init(_malloc (sizeof(t_appwin)),

rt,

"Window application",

2,

ap_id,

&trans_ev);

OBJECT (desktop)-> insert (OBJECT(desktop), OBJECT (main_win));

list1 = list_init(_malloc(sizeof(t_list)), &free_listbox_item, 0);

list2 = list_init(_malloc(sizeof(t_list)), &free_listbox_item, 0);

list1->insert(list1, new_listbox_item("First", NULL, true, LIF_NONE));

list1->insert(list1, new_listbox_item("Second", NULL, true, LIF_NONE));

list1->insert(list1, new_listbox_item("Third", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("Unix", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("Windows", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("SEAL", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("DOS", NULL, true, LIF_NONE));

list2->insert(list2, new_listbox_item("Linux", NULL, true, LIF_NONE));

collect_by_name(list2, 0); // сортировка по имени

// LISTBOX

rt = rect_assign (30, 30, 150, 100);

lbox = listbox_init (_malloc (sizeof (t_listbox)), rt, list2, 0, LF_NONE);

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (lbox));

// HISTORY

rt = rect_assign (30, 110, 150, 130);

hist = history_init (_malloc (sizeof (t_history)), rt, list1, 100, HF_NONE);

OBJECT (main_win)-> insert (OBJECT(main_win), OBJECT (hist));

}

// шаблон главной функции

app_begin ( void ) {

if (ap_process == AP_INIT) {

win_paint();

}

} app_end;


В заключении этой главы я должен сказать, что это только азы объектов-списков. Для более полной информации следует изучить заголовочный файл "dialogs.h" и описание для программиста на английском языке, входящее в состав практически всех дистрибутивов, где отлично описан объект LIST. Хотя для большинства случаев эта глава содержит достаточно сведений.

7.Объект MENU (Краткое описание).

Да-с. Нелегкое это дело писать руководства. Еще несколько глав и я уже буду думать о том, как поскорее сделать аплоад этого материала в интернет.

Добрались мы с вами до очень далекой главы, которая расскажет вам о таком элементе программирования как MENU. С чего бы начать? Пожалуй с того, что в SEAL существует 2 стандартных объекта MENU. Это вертикальные меню и горизонтальные меню. Мы познакомимся с обоими. Сделано это будет по традиции с помощью общего обзора объектов, а потом мы как обычно составим простенькую программу для реализации всего прочитанного в жизнь.

Создание меню.

Наверное ни одна современная операционная система или десктопная среда не обходятся без этих элементов. Они есть в Windows, KDE, X-Window, BeOS… короче говоря везде, где есть графическое представление рабочего стола. Не избежал этого и SEAL.

Все необходимые функции для создания меню и работе с ним находятся в заголовочном файле <menus.h>.

Меню в SEAL бывают вертикальные (MENUVIEW) и горизонтальные (HORMENU). Объявим для начала указатель на меню:

p_menuview menu;

Пусть в нашем меню будут 2 раздела: exit и about. Сделаем для этого следующее:

menu = new_menu ( new_sub_menu ( "File", new_menu (

new_menu_item ("About...", "About program", 0,

100010, NULL,

new_menu_line(

new_menu_item ("Exit", "Quit program", 0,

100011, NULL, NULL))))));

 

Функция new_sub_menu создает верхний элемент меню. new_menu_line - создает сепаратор (разделитель между пунктами меню). new_menu_item - создает пункт меню. Четвертым параметром для этой функции служит номер сообщения, передаваемый в нашу старую знакомую функцию обработки сообщений.

Я не буду описывать, что значит каждый из параметров. Думаю, что все понятно и без описаний. Если вас интересует более подробная информация, загляните в guide.txt. Там вы найдете более чем исчерпывающую информацию.

Мы только что создали меню. Теперь настало время пометить его в окно. Воспользуемся уже созданной программой msgwin.c и пометим наше меню в окно. Для этого нам понадобится поместить наше меню в место определенное переменной t_rect rt.

rt = rect_assign (10, 25, 60, 60);

menu = hormenu_init (_malloc (sizeof(t_menuview)),

rt, menu);

OBJECT (main_win)-> insert (OBJECT (main_win), OBJECT (menu));

В отличии от меню в Windows в SEAL можно пометить меню в любую часть окна. Именно для этого мы используем переменную типа t_rect.

Далее мы добавляем наши строки в программу.

Программа MENU.

Листинг 7.1 menu.c


#include "allegro.h"

#include "seal.h"

#include "iodlg.h"

#include "menus.h"

 

p_appwin main_win;

t_rect rt;

// указатель на меню

p_menuview menu;

 

// прототип функции

void win_paint ();

// функция обработки сообщений

void trans_ev (p_object obj, p_event event) {

if (obj->process & PH_PREPROCESS) {

if (event->message == 100011){

event->message = MSG_CLOSE;

}

if (event->message == 100010){

msgbox (MW_WARNING, MB_OK, "Menu application\nversion 1.0");

clear_event (event);

}

}

}

void win_paint () {

t_rect rt;

rt = rect_assign (100, 100, 400, 300);

main_win = appwin_init(_malloc (sizeof(t_appwin)),

rt,

"Window application",

2,

ap_id,

&trans_ev);

OBJECT (desktop)-> insert (OBJECT(desktop), OBJECT (main_win));

menu = new_menu ( new_sub_menu ( "File", new_menu (

new_menu_item ("About...", "About program", 0,

100010, NULL,

new_menu_line(

new_menu_item ("Exit", "Quit program", 0,

100011, NULL, NULL))))));

rt = rect_assign (10, 25, 60, 60);

menu = hormenu_init (_malloc (sizeof(t_menuview)),

rt, menu);

OBJECT (mainwin)-> insert (OBJECT (mainwin), OBJECT (menu)); 

}

// шаблон главной функции

app_begin ( void ) {

if (ap_process == AP_INIT) {

win_paint();

}

} app_end;


Теперь запустите программу и многое из того, что не было объяснено, будет понятно.

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

 

8.Немного о диалоговых окнах.

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

Функция создания различных диалоговых окон.

Наверняка при составлении программ для SEAL вам понадобится пользоваться диалоговыми окнами для указания файлов, такими как в Windows при выполнении в текстовом редакторе команды OPEN...

Все функции по созданию данного рода объектов находятся в одном заголовочном файле <iodlg.h>. Точнее будет сказано, что функция, собственно, одна, но существуют дополнительные функции, основанные на этой главной в виде переопределений #define. Если вы загляните в "iodlg.h" то сможете это наблюдать своими собственными глазами.

 

Функции создания стандартных диалоговых окон.

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

Итак, разберемся… Таких функций всего 3:

open_dialog

для открытия файла

save_dialog

для записи файла

dir_dialog

для отображения директории (открывается только каталог, а не отдельный файл)

Для примера воспользуемся функцией open_dialog. Она выводит окно для просмотра файлов в директориях, которое имеет кнопку OPEN. Это еще совсем не означает, что она открывает файл. Она просто возвращает имя файла, который вы выбрали в процессе работы с окном или NULL, если вы отказались выбирать что-либо.

Прототип ее таков:

l_text open_dialog (l_text path, l_text file, void (*file_sel)());

path - путь для директории, открываемой по умолчанию

file - имя открываемого файла по умолчанию

*file_sel - указатель на функцию, возвращающую значение p_list.

Теперь разберем все на примере. На этот раз я не буду предъявлять всю программу, а лишь предоставлю только необходимую часть.

p_list list_ret()

{

p_list p = list_init (_malloc (sizeof(t_list)), &free_filehistory_item, 0);

p->insert (p, new_filehistory_item( "All files (*.*)", "*.*"));

p->insert (p, new_filehistory_item( "Executable files (*.EXE)", "*.EXE"));

return (p);

}

void open_funct()

{

l_text filename;

filename = open_dialog ("c:/", NULL, list_ret());

}

При успешном выполнении программы в переменную filename должно возвратится значение выбранного вами имени файла.

Точно такие же аргументы имеет и функция save_dialog.

Функция _file_dialog.

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

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

Взглянем сначала на прототип:

l_text _file_dialog (l_text caption, l_text bname, l_text path, l_text file, p_list hislist, l_int attrib, l_int flags, void *(file_sel)());

Ни фига себе сколько их тута… Так… Давайте попорядку:

caption

заголовок окна

bname

текст на кнопке

path

путь (мы с ним уже знакомы)

file

файл по умолчанию (он нам тоже известен)

hislist

это тоже знакомый нам аргумент списка из open_dialog

attrib

атрибуты файлов. Здесь должна быть одна из констант, определенных в <_iodir.h>. Используйте FA_ALL для всех файлов.

flags

одна из констант (FL_OPEN, FL_SAVE, FL_DIROPEN)

file_sel()

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

Вот пожалуй и все, что касается этой темы. Надеюсь этого вам пока хватит. Если вас заинтересует более детальная информация, то вам придется изучать <iodlg.h>. Иной документации (период 2001 года) пока еще не существует.

9.Многозадачные циклы.

Представте такую ситуацию, когда вам требуется в одном из событий обработать очень большой цикл. Обычное дело… Вы, конечно же, воспользуетесь оператором for или while.

int s;

for (s = 1; s < 1000000; s++)

{

// do something

;

}

Ошибки при выполнении цикла не возникнет. Однако во время выполнения вашего цикла система как бы повиснет, отдав все свободное системное время на его выполнение. В ряде случаев это даже полезно, но что делать когда это совсем неуместно, ведь SEAL - это многозадачная GUI.

Решить эту проблему просто. В заголовочном файле <seal.h> есть такие переопределения как _while и _for. Выполняются они, так же как и стандартные while и for, но они рассчитаны на выполнение в режиме многозадачности.

Если хотите, чтобы ваши программы поддерживали многозадачность, используйте _while и _for вместо while и for.

int s;

_for (s = 1; s < 1000000; s++)

{

// do something

;

}

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

Хотя тут есть и обратная сторона медали: этот цикл будет выполняться медленнее. Делать этот цикл многозадачным или нет - решать вам.

 

Заключение.

Фух… Это был нелегкий марафон, который мы начали с вами с маленькой примитивной программы hello.c и постигли почти все азы программирования для SEAL. Надеюсь, вам было несложно понимать написанный здесь материал. В любом случае, я всегда готов выслушать ваше мнение по этому поводу и внести изменения. Я всегда рад вашему визиту на мой сайт seal.htmlplanet.com.Теперь вы можете приступать к программированию для SEAL. Уверяю вас, что ваши программы не останутся без внимания общественности, потому что любая программа написанная для SEAL вызывает достаточно большой интерес у его любителей этой GUI. Для вас открыты все направления в программировании. Найдите свою тему для программы, создайте ее и не забудьте опубликовать ее в интернете.