Программирование на Delphi

  Все выпуски  

Программирование на Delphi (выпуск 81)


Программирование на DELPHI
Выпуск #81 (01 мая 2008 г.)

Разделы сайта:

Delphi.int.ru

Новости сайта
Регистрация »
Файловый архив
Статьи
Компоненты
Plug-in's
Документация
Исходники
Изображения
Игры
Программы
Рассылки сайта
F.A.Q.

IRC-каналы сайта:

Сервер: irc.dalnet.ru
Порт: 6667
Канал: #delphiintru
(основной)

Сервер: irc.rus.net
Порт: 6667
Канал: #delphi.int.ru
(тестовый)

Ждём Вас на нашем канале!

Доброго времени суток, уважаемые читатели!

Прежде всего, хочется поздравить всех с праздником 1 мая!

К сожалению, рассылка давно не выходила из-за нехватки времени... Тем не менее, не забывайте, что задать свой вопрос на нашем сайта Вы можете 24 часа в сутки - в системе Delphi.int.ru Expert. Система постоянно развивается, и в большой степени благодаря участникам - все предложения выслушиваются и хорошие идеи никогда не остаются без внимания. Присоединяйтесь!

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

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

В этом выпуске:

Статистика Delphi.int.ru Expert на 01.05.2008, 09:00 (предыдущий подсчёт - 15.03.2008, 12:00):

Количество экспертов: 49 (+2).
Участниками задано вопросов: 1538 (+123).
Экспертами отправлено ответов: 2166 (+152).
Количество сообщений на мини-форумах: 2833 (+244).
Максимальное число разосланных в день писем (за всю историю): 1960 (28.10.2007, +0).

До встречи в следующем выпуске!

Разделы рассылки:

» Авторское слово
» Обучение Delphi
» Delphi.int.ru Expert
» Статья по Delphi
» Файловый архив
» Юмор

Delphi.int.ru Expert
Сообщество программистов: общение, помощь, обмен опытом.

Количество читателей рассылки (01.05.2008, 12:00):
5610+1818+491= 7919 (+169)

Связь по e-mail:

admin@delphi.int.ru
support@delphi.int.ru


Если Вы хотите где-либо разместить материалы, представленные на www.delphi.int.ru или в данной рассылке, свяжитесь, пожалуйста, с их автором или ведущим рассылки.

Delphi.int.ru Expert
Сообщество программистов: общение, помощь, обмен опытом
(текущая версия системы: 2.35; последнее обновление: 26.04.2008)

Последние новости

В начале каждого месяца проходит голосование за лучший ответ месяца и самый интересный вопрос. Победителям вручаются почётные медали.
За март медали получили: Feniks (лучший ответ) и bzfar_77 (лучший вопрос).

23 марта 2008 г.

∙ Создана возможность выставления оценки "-1" (против) за ответ.
∙ Добавлено автоматическое скрытие боковой информационной панели на страницах вопросов и страницах информации об участниках.
∙ Увеличен срок хранения прикрепляемых к ответам файлов до 60 дней.

26 апреля 2008 г.

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

 

Архив: вопросы и ответы

В архив попадают вопросы, срок действия которых истёк. Каждый заданный вопрос действителен в течение одной недели, т.е. ответы на него принимаются именно в этот период. В сегодняшнем выпуске опубликованы вопросы # 371 - 385. Вопросы, на которые не было дано ни одного ответа, не публикуются.
Так как темп поступления вопросов от пользователей намного выше темпа их публикации, в рассылке публикуются вопросы, заданные довольно давно. Тем не менее, вопросы публикуются по порядку, без пропусков. Просмотреть любые вопросы и ответы Вы всегда можете на сайте.

Статистика по выпуску:

Кол-во вопросов: 15
Кол-ответов: 24
Баллы за ответы: 90
 

Вопрос # 372

Здравствуйте. Как мне сделать так, что бы нажав на кнопку
запустить "exe" файл (например, с программой), и
сразу хочу спросить ещё? Как мне напечатать текст в Memo1
сохранить его, и не просто сохранить а "сохранить как....."
то есть указать путь, где я хочу его сохранить, ну и если можно
то в конце хочу спросить, как кинуть Label1 на Form1,
чтобы в ней отображалось (и работало) переключение
Русского и Английского языков. Заранее благодарен.

Вопрос задал: Толков Геннадий Викторович (статус: Посетитель)
Вопрос отправлен: 03 марта 2007, 23:31
Всего ответов: 4

 

1. Отвечает эксперт: Федоров Роман Сергеевич

1)uses ShellApi;
ShellExecute(0,nil, 'Путь к фалу',nil, 'Директория', SW_SHOWNORMAL);
2)Помести на форму компонент SaveDialog
procedure TForm1.Button1Click(Sender: TObject);
begin
if SaveDialog1.Execute then Memo1.Lines.SaveToFile(SaveDialog1.FileName);
end;

Ответ отправил: Федоров Роман Сергеевич (статус: 2-ой класс)
Ответ отправлен: 3 марта 2007, 23:52
Оценка за ответ: 5

2. Отвечает эксперт: Вадим К

По поводу языков.
Узнать, какой язык активен можно так
function GetLangId:string;
var s: array [0..63] of char;
begin
GetKeyboardLayoutName(s);
result :=s;
end;
Правда возвращается на текстовое название языка, а его код
к примеру 409 - английский,
419 - русский
422 - украинский
Для остальных - ищете.
Сразу предупрежу вопрос о переключении языка
Включить русский язык
ActivateKeyboardLayout(LoadKeyboardLayout('00000419', 0), 0);
Переключить на следующий язык в списке
ActivateKeyboardLayout(HKL_NEXT, 0);

Как же отследить переключение? Ставите таймер и каждую секунду запрашивайте.

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 4 марта 2007, 00:17
Оценка за ответ: 5

3. Отвечает эксперт: min@y™

Мог дать ответы на все вопросы, но опоздал. :)
Добавлю ещё вот что: не ст0ит отслеживать переключение по таймеру, ибо раскладка клавы для каждого приложения индивидуальна. Лучше отслеживать в обработчике события Application.OnIdle. См. приложение.

Приложение:

Ответ отправил: min@y™ (статус: Студент)
Ответ отправлен: 5 марта 2007, 08:49

4. Отвечает эксперт: Шарайчук Сергій Олександрович

Сохранить текст ты можеш используя компонент SaveDialog, например
if SaveDialog1.Execute then
begin
AssignFile(SaveDialog.FileName,f)
write(f, memo.line.add);
closefile(f);
end;
где f файл в который ты сохраняеш текст!

Ответ отправил: Шарайчук Сергій Олександрович (статус: 1-ый класс)
Ответ отправлен: 5 марта 2007, 13:52


Вопрос # 373

Здравствуйте! Мне необходимо написать два класса, один - класс "линия", второй - класс "объект". Класс объект состоит из массива линий. Вот задача заключается чтобы обеспечить безопасный доступ к каждому экземпляру линии через класс объект. Например, обращение должно быть примерно таким как идет обращение к строке в компоненте Memo:
Memo.Lines.Add
Memo.Lines[i] := 'string'
i := Memo.Lines.Count
Memo.Lines.Clear
Т.е. мне нужен простенький примерчик, как релизовать подобное обращение...

Вопрос задал: SMaks (статус: 1-ый класс)
Вопрос отправлен: 04 марта 2007, 00:17
Всего ответов: 1; сообщений в мини-форуме вопроса: 1

 

1. Отвечает эксперт: Вадим К

Я надеюсь, что объект линия вы в состоянии написать. А вот что бы написать объект, который будет их "содержать" воспользуемся стандарным классов TList (модуль Classes) или TObjectList (Contrls). Во втором случае вам не прийдётся думать о удалении объектов линия. Тоесть вам просто нужно написать наследника. В приложении есть наследник на базе TList
При этом я предполагаю, что клас TLine уже написан

Приложение:

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 4 марта 2007, 00:57
Оценка за ответ: 5
Комментарий: Я просил написать два новых класса, т.е. не использовать стандартные.
В данно примере я не могу получить количество линий таким вызовом:
ArrayLine.Items.Count
и добавить элемент:
ArrayLine.Items.Add


Вопрос # 374

Здравствуйте ув. эксперты. Существует замкнутый полигон из N количества линий, соотвественно все вершины данны. Как опередить попадает ли данная точка в полигон или нет? (без использования регионов)

Вопрос задал: SMaks (статус: 1-ый класс)
Вопрос отправлен: 04 марта 2007, 00:23
Всего ответов: 2; сообщений в мини-форуме вопроса: 1

 

1. Отвечает эксперт: Матвеев Игорь Владимирович

Здравствуйте, SMaks!

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

Я подготовил для Вас демонстрационную программу, использующую другой алгоритм:
1. Случайным образом выбирается точка A
2. Проверяется число пересечений отрезка, образованного точками A и исследуемой точки со всеми гранями многоугольника
3. Если число пересечений = 0 => переход к пункту 1
4. Если число пересечений четное - точка вне многоугольника, если нечетное - внутри.

(прикреплённый файл)

И еще замечания: Данный метод работает для любых многоугольников, но могут быть проблемы с перекрещеными многоугольниками. В таких случайх алгоритм выдает результат, будто при образовании многоугольника используется операция xor, т.е. если на площадь многоугольника еще раз накладывается площадь многоугольника - эта область не считается многоугольником.
Если это положение для Вас критично, Вы можете делать проверку несколько раз, а затем делать вывод.
К ответу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки ответа)

Ответ отправил: Матвеев Игорь Владимирович (статус: Студент)
Ответ отправлен: 4 марта 2007, 06:58
Оценка за ответ: 5
Комментарий: Огромное спасибо, особенно за пример! Обратите внимание - можно увести точку за канву, нужно при перетаскивании ограничивать область курсора.

2. Отвечает эксперт: Роман

Здравствуйте, SMaks!Привожу вам функцию которая определяет находится ли точка внутри многоугольника или нет.TestPolygon : array of TPoint - многоугольник;P : TPoint - точка положение которой нужно определить.Работает с любыми замкнутыми многоугольниками.

Приложение:

Ответ отправил: Роман (статус: 5-ый класс)
Ответ отправлен: 4 марта 2007, 12:07
Оценка за ответ: 5
Комментарий: То что нужно, Спасибо!


Вопрос # 375

Здравствуйте. Что делают даные API функции (в прилож) и для чего используются?

Приложение:

Вопрос задал: SMaks (статус: 1-ый класс)
Вопрос отправлен: 04 марта 2007, 00:28
Всего ответов: 3

 

1. Отвечает эксперт: Вадим К

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

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 4 марта 2007, 00:46
Оценка за ответ: 5

2. Отвечает эксперт: Виталий Лещенко

Здравствуйте, SMaks!
1. получает область на экране в которой может перемещаться мышь.
2. устанавливает некую юобласть в которой может перемещаться мышь.
Переменные типа TRect "задают прямоугольник".

Ответ отправил: Виталий Лещенко (статус: 4-ый класс)
Ответ отправлен: 4 марта 2007, 02:00
Оценка за ответ: 5

3. Отвечает эксперт: Федоров Роман Сергеевич

Здравствуйте, SMaks!
getClipCursor - возвращает прямоугольник, описывающий текущую область отсечения курсора, заданную функцией SetClipCursor
Возвращаемое значение: Long - ненулевое значение в случае успеха, ноль при неудаче.

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

Ответ отправил: Федоров Роман Сергеевич (статус: 2-ой класс)
Ответ отправлен: 4 марта 2007, 14:32
Оценка за ответ: 5


Вопрос # 376

Здравствуйте! Вопрос, быстрее ли осуществляется вызов из библиотеки dll функции на прямую, чем если, вызов происходит через Com-сервер, расположенный в библиотеке, т.е. через интерфейс?

Вопрос задал: SMaks (статус: 1-ый класс)
Вопрос отправлен: 04 марта 2007, 00:35
Всего ответов: 2

 

1. Отвечает эксперт: Вадим К

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

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 4 марта 2007, 01:01
Оценка за ответ: 5

2. Отвечает эксперт: Виталий Лещенко

Здравствуйте, SMaks!
Работа с чем-либо напрямую всегда быстрее... или во всяком случае не медленнее.
И этот случай не исключение.

Ответ отправил: Виталий Лещенко (статус: 4-ый класс)
Ответ отправлен: 4 марта 2007, 02:02
Оценка за ответ: 5


Вопрос # 377

Здравствуйте! Продолжая вопрос 373 напишу новый. У меня есть три класса. Класс TDocument содержит в себе массив "объектных векторов" - ObjectsVector.
Итак первый ворос как мне получить колисчество этих "объектных векторов", таким образом:
Document.ObjectsVectors.Count, чтобы одновремено можно было обратиться к каждому "объектному вектору"?: Document.ObjectsVectors[i] := TObjectsVector.create (Document.ObjectsVectors.Add)
И одновременно с этим получить количество линий в "объектном векторе"?:
Document.ObjectsVectors[i].Count
Заметьте, что я использую список линий, т.е. мне нужно реализовать только "интерфейс" к каждой линии:
Document.ObjectsVectors[i].VectorPoint.Count (получить количество точек в линии в i объектном векторе)
И последнее, получить доступ и изменить точку в линии:
Document.ObjectsVectors[i].VectorPoint[j].x := X
Document.ObjectsVectors[i].VectorPoint[j].y := Y
Я пробовал реализовывать через наследование, используя абстрактные методы, ничего не получилось, уже главу про класса прочил не один раз, не могу понять как это реализовано, например в tmemo (memo.Lines.count, memo.lines[i] := s).
Может кто-нибудь объяснить как это реализуется?

Приложение:

Вопрос задал: SMaks (статус: 1-ый класс)
Вопрос отправлен: 04 марта 2007, 19:11
Всего ответов: 2; сообщений в мини-форуме вопроса: 2

 

1. Отвечает эксперт: Вадим К

У вас в голове откровенно каша. Вы хотите использовать абстракный класс, не реализовав эти методы.
К примеру, у вас ест
procedure Add(Point: TPoint); virtual; abstract;
Этот метод вызвать нельзя.!
Его можно вызвать только в наследнике, который его реализует.
Во вторых, непонятно ваше желания использовать списки. Это даст медленый произвольный доступ к элементам и подсчёт общего количества элементов.
Также мне непонятен метод procedure AddObject();
Куда он добавляет? Что добавляет?
Назначение TVectorPoint, которому нужно реализовать заданую функциональность, вообще стоит боком Его назначение для меня загадка. Он как 5 колесо для воза. Ещё раз скажу, у вас большие проблемы с проектированием классов.
К тому же я не понимаю разницу между методами
procedure AddVector(Point: TPoint);
procedure AddPoint(index: word; Point: TPoint);
А также фунциональность, которая на них положена.
Нужно перепроектировать классы.
А потом реализовать методы.

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 4 марта 2007, 22:57
Оценка за ответ: 4
Комментарий: Да я все перепробовал, этот код - уже переделывался много раз, а также я прекрасно знаю, что абстрактные методы нельзя вызывать, я лишь пытался его перекрыть в потомке. Используя списки - я выгрываю в добавлении, удалении в середину элементов. Посчет элементов производиться заранее. Вот я этим и занимаюсь: пытаюсь спроектировать удобный и защищенный класс. Вообщем я задал конкретный вопрос! Я не прошу писать здоровые классы, мне нужно всего лишь небольшой примерчик, полностью поясняющий суть.

2. Отвечает эксперт: min@y™

Набросал ОЧЕНЬ сильно упрощённый примерчик, буквально на коленке. Это не руководство к действию, но я работаю уже много лет именно так. См. приложение.

Приложение:

Ответ отправил: min@y™ (статус: Студент)
Ответ отправлен: 5 марта 2007, 09:11
Оценка за ответ: 4


Вопрос # 379

Приветствую!!Как програмно нажать на клавиши на клавиатуре?(Во время выполнения программы)

Вопрос задал: KilkaMS (статус: Посетитель)
Вопрос отправлен: 06 марта 2007, 01:30
Всего ответов: 3; сообщений в мини-форуме вопроса: 1

 

1. Отвечает эксперт: Вадим К

Я думаю это поможет
К сожалению работает хорошо, только когда фокус у вызывающего окна, в противном случае может глючить



procedure TForm1.SetKey(Key:Integer);
begin
keybd_event(Key,0,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0);
keybd_event(Key,0,KEYEVENTF_EXTENDEDKEY,0);
keybd_event(Key,0,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0);
end;

Применение

SetKey(VK_SCROLL);
SetKey(VK_CAPITAL);
SetKey(ord('A'));

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 6 марта 2007, 01:53
Оценка за ответ: 4

2. Отвечает эксперт: Николай Рубан

Данные манипуляции можно произвести при помощи таких не хитрых действий (смотрите приложение).

В приложении используется такие команды:
keybd_event(Key,0,KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0);
keybd_event(Key,0,KEYEVENTF_EXTENDEDKEY,0);
где Key - код символа (кнопки) на который нужно нажать.

Вот еще несколько констант клавиш (их можно найти в справке):
VK_ESCAPE Escape
VK_SPACE Пробел
VK_PRIOR PageUp
VK_NEXT PageDown
VK_END клавиша End
VK_HOME клавиша Home
VK_LEFT клавиша влево
VK_UP клавиша вверх
VK_RIGHT клавиша вправо
VK_DOWN клавиша вниз
.....

В приложении идет обработка события нажатия на кнопку (Button1) форму, после чего в поле (Edit1) будет написано слово "hello".

Good Luck!!!

Приложение:

Ответ отправил: Николай Рубан (статус: 9-ый класс)
Ответ отправлен: 6 марта 2007, 01:58
Оценка за ответ: 4

3. Отвечает эксперт: Роман

Здравствуйте, KilkaMS!Щёлкнуть можно по разному;посмотрите на delphiworld.narod.ru/_os_.html в части клавиши,там с десяток разных вариантов реализации.

Ответ отправил: Роман (статус: 5-ый класс)
Ответ отправлен: 6 марта 2007, 02:08
Оценка за ответ: 5


Вопрос # 380

Приветствую!!!Как можно работать с удаленным реестром??

Вопрос задал: KilkaMS (статус: Посетитель)
Вопрос отправлен: 06 марта 2007, 23:57
Всего ответов: 1; сообщений в мини-форуме вопроса: 4

 

1. Отвечает эксперт: Роман

Здравствуйте, KilkaMS!Вообще для этого надо написать клиента и сервера.А так перейдите в архив рассылки http://www.delphi.int.ru/subscribes,скачайте zip и в выпуске 42 (26 февраля 2006 г.) посмотрите ответы на вопрос 232.

Ответ отправил: Роман (статус: 5-ый класс)
Ответ отправлен: 7 марта 2007, 09:03
Оценка за ответ: 5


Вопрос # 382

Приветствую!!!Можно-ли заставить все процессы в программе не блокировать друг друга??

Вопрос задал: KilkaMS (статус: Посетитель)
Вопрос отправлен: 07 марта 2007, 00:18
Всего ответов: 1; сообщений в мини-форуме вопроса: 5

 

1. Отвечает эксперт: Вадим К

А процессы а программе не могут блокировать друг дружку, так как В программе может быть только один процесс. А то что вы назвали процессами называется потоками.
Что же делать, что бы они не блокировали друг дружку?
Правильно проектировать.

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 7 марта 2007, 13:02


Вопрос # 383

Здравствуйте!Вопрос:
Если это возможно, интересует информация о потоках, т.е. создание потоков, работа с ними, ну мож еще что полезное.Спасибо

Вопрос задал: HotMan (статус: Посетитель)
Вопрос отправлен: 07 марта 2007, 12:38
Всего ответов: 3; сообщений в мини-форуме вопроса: 1

 

1. Отвечает эксперт: Вадим К

Вы так спрашиваете, вроде это одна-две строчки.
На тему работы с потоками люди десертации защищают.
На wingrad.ru был цикл статей на эту тему, но от сейчас что то недоступен.
Если допишу свою статью на тему "Введение в потоки" - выложу.

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 7 марта 2007, 12:54
Оценка за ответ: 3

2. Отвечает эксперт: Роман

Здравствуйте, Kardonsky Roman Viktorovich!Посмотрите на http://www.delphimaster.ru/articles9.html статью «DELPHI в примерах для начинающих» - Изучение простейших приемов работы с файлами и потоками на примере программы «Монитор каталогов»,на http://www.delphikingdom.com/ - "Параллельные потоки";поищите книжку М.Фленова "Библия для программиста в среде Delphi" (17 глава "Потоки").

Ответ отправил: Роман (статус: 5-ый класс)
Ответ отправлен: 7 марта 2007, 14:30
Оценка за ответ: 4

3. Отвечает эксперт: Knjazev

Здравствуйте, Kardonsky Roman Viktorovich!
Очень странный вопрос задаёшь. Учебники читаешь?
Наиболее полное описание работы с потоками я встречал в книге С. Тейксейра и К. Пачеко "Delphi 5 Руководство разработчика том 1". Правда, там невнятно было описано применение Synhronyze (синхронизация VCL), а она наиболее употребительна.

Ответ отправил: Knjazev (статус: 3-ий класс)
Ответ отправлен: 7 марта 2007, 16:41
Оценка за ответ: 1


Вопрос # 384

Проведём эксперемент (delphi 6, но скорее всего и в других версиях будет точно также): создадим новый проэкт и добавим ещё одну форму. Пусть form1 - главная - кинем на неё кнопку Button1 и form1.formstyle="fsMDIForm." В обработчике нажатия кнопки Button1 напишем
form2.show;
В oncreate второй формы form2 напишем:
WindowS.SetParent(handle, Form1.Handle)

Запускаем приложение, нажимаем на кнопочку, внутри появляется form2. А теперь нажимаем alt+tab и видим что наше тестовое приложение там отсутствует! Т. е. на него нельзя переключиться через alt+tab. Вот и вопрос: нужно от этого избавиться

И пару комментариев (все имеют основание, поэтому просьба не спрашивать почему):
1) Использовать form2.ParentWindow := ... вместо аналогичной (хотя врядли) ф-ии API setParent нельзя (она не обращает внимание на клиентскую обл.);
2) Использовать именно form1.clientHandle, т. к. иначе, если использовать form1.handle, опять не обращается внимание на клиентскую обл.;
3) form2.formstyle не должен быть fsMDIChild (если так, то форму нельзя нормально закрыть - она в уголочек сворачивается)
P. S. Есть и другие обоснования, почему должны выполняться п. п. 1-3, но я уже все не помню :)

Спасибо

Вопрос задал: mvp (статус: 4-ый класс)
Вопрос отправлен: 07 марта 2007, 19:17
Всего ответов: 2; сообщений в мини-форуме вопроса: 7

 

1. Отвечает эксперт: Вадим К

А если form2.formstyle="fsMDIChild"
тогда отображается?
А проблема с сворачиванием решается просто.
в вторую форму добавим
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;

А также в главной форме перед строкой
form2.Show;
добавим
form2:=TForm2.Create(Form1);

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

З.Ы.
Циклические ссылки между двумя формами - ошибки проектирования, источник потенциальных глюков

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 7 марта 2007, 19:37
Оценка за ответ: 3
Комментарий: Читаем внимательнее P. S. Из-за этого Ваш ответ не подходит. У меня эти формы создаются при запуске и удаляются только при закрытии приложения (так надо). А по поводу циклических ссылок - это просто пример, чтобы не отвлекать от сути. А у меня вообще формы друг к другу обращаются только через интерфейсы, находящиеся в промежуточном модуле - в нём формы регистрируются и дополнительно указывают, какие оп-ии к ним можно преминить. Также промежуточный модуль проводит обработку ошибок и т. п. Т. е., очень легко сильно переработать одну из форм не трогая всё приложение. P. S. А показ второй формы вообще из обычного unit'а вызывается

2. Отвечает эксперт: Knjazev

Здравствуйте, mvp!
1. Всё же plan 3
object Form1: TForm1
...
Formstyle="fsMDIForm"
...
end
и
object Form2: TForm2
...
Formstyle="fsMDIChild"
...
end
2. в приложении как открывать и закрывать form2 (ничего нового - всё, как учат отцы)
3. на fsMDIForm-формах обычно кнопки не держат, делают фон clAppWorkSpace, вся работа через меню и тулбар

Приложение:

Ответ отправил: Knjazev (статус: 3-ий класс)
Ответ отправлен: 7 марта 2007, 21:18
Оценка за ответ: 3
Комментарий: формы должны существовать всегда и не mdichild. И хоть кнопки на mdi-формах не держат, но всякие там toolbar'ы кидают. А вообще - вопрос решён - конает parentWindow, просто был глюк в другом месте.


Обучение Delphi

» Найти все предыдущие уроки можно на www.delphi.int.ru в разделе "Статьи". Последние 3 урока:

17. Циклы - цикл с предусловием и цикл с постусловием
18. Работа со строками и символами
19. Подпрограммы (часть 1)

Подпрограммы (часть 2)

Автор:
© Ерёмин А.А., 2008
Готовой работающей программой называют код, содержащий пока еще не обнаруженные ошибки.
Номер урока:
20
 

Решение домашнего задания из урока №19

Для начала разберём домашнее задание, которое было предложено в прошлом уроке. Задание было следующим:

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

  1. Функция, считающая, сколько раз буква встречается в тексте.
  2. Функция, вычисляющая объём цилиндра.
  3. Функция, проверяющая, является ли параллелепипед кубом.
  4. Процедура, делающая 3 кнопки, расположенные на форме, недоступными для нажатия.
  5. Процедура, изменяющая разрешение экрана.

1. Необходимо указать текст, в котором будет выполняться поиск буквы и сама буква для поиска.
2. Как известно, объём цилиндра равен произведению площади основания на высоту, а площадь основания - произведение числа ПИ на квадрат радиуса. Итак, параметрами будут радиус основания цилиндра и его высота.
3. Параллелепипед будет кубом тогда, когда все его три измерения (т.е. длина, ширина, высота) равны. И параметров будет соответственно 3.
4. Если процедура работает с какими-то конкретными кнопками, то входные параметры не потребуются. Другой вариант - процедуре передаются 3 параметра - какие именно кнопки следует сделать недоступными.
5. Чтобы изменить разрешение экрана, нужно задать новые параметры - ширину и высоту - всего 2 параметра.

Введение

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

Структура подпрограммы

Заголовок представляет собой строку, в которой содержится вся необходимая информация о подпрограмме: её тип, имя, список аргументов, выходное значение. Заголовок является обязательной частью подпрограммы. Тело подпрограммы, т.е. блок, содержащий все команды, выполняемые подпрограммой, записывается после заголовка. Если быть более точным, под заголовком размещается раздел описаний (переменные, константы и т.д.), а уже затем блок реализации. Таким образом, общая структура подпрограммы напоминает любую самостоятельную программу.
С подпрограммами вы уже сталкивались много раз - любой обработчик любого события - это подпрограмма. Помните, когда мы создаём обработчик нажатия кнопки, появляется заготовка кода, где есть заголовок с именем вроде Button1Click, ниже идёт блок begin .. end - блок реализации, а выше него мы вписываем свои собственные переменные, константы и другие необходимые элементы. (Подробнее - см. урок №11 "События")

Описание заголовка

Итак, мы решили создать свою подпрограмму. Чтобы программа могла её вызывать, подпрограмму нужно описать. Описание обычно начинается с заголовка. Как мы отметили ранее, в заголовке содержится основная информация о подпрограмме. Разберёмся отдельно с каждой из составляющей заголовка.

Тип подпрограммы

Ранее мы установили, что существуют два типа подпрограмм - процедуры и функции. Их различие в том, что функция возвращает какой-то результат после завершения работы, а процедура этого не делает. Значит, мы должны явным образом указать, чем является наша подпрограмма - процедурой или функцией. Указывается это в самом начале заголовка соответствующим зарезервированным словом - procedure или function.

Название подпрограммы

Чтобы иметь возможность вызывать подпрограмму, нужно присвоить ей имя. Имя подпрограммы составляется по тем же правилам, что и имя любого идентификатора (переменной). Кто забыл - смотрите урок №8 "Pascal - первое знакомство", там эти правила подробно рассмотрены. Итак, вы придумали имя своей подпрограмме. Куда его написать? А всё просто - сразу же за словом procedure или function через пробел:

procedure MyProcedure

или

function MyFunction
Иногда подпрограмме не присваивают осмысленного имени и используют именно такие названия, как указано выше. Ещё применяются сокращения вроде MyFunc или MyProc. Если подпрограмма пишется в тестовых целях, то такие названия вполне подойдут, но если разрабатывается "серьёзное" приложение, следует избегать таких названий. Представьте, легко ли будет вам ориентироваться в коде, если подпрограммы будут имена имена MyFunc1, MyFunc2, ..., MyProc1, MyProc2, ... ? Именно поэтому давайте подпрограммам (а также и переменным, константам) какие-то осмысленные имена. Впоследствии разобраться в коде будет гораздо проще.

Окончание заголовка

Тип подпрограммы указан, название тоже... Что дальше? А дальше следует подумать над тем, требует ли ваша подпрограмма какие-то входные параметры (аргументы) или она работает без них. Окончание заголовка как и окончание любой команды указывается символом точки с запятой (";"). Допустим, ваша процедура скрывает на форме какие-то элементы и при этом не требует входных параметров. Тогда её заголовок будет выглядеть так:

procedure HideElements;
На этом описание заголовка такой простой процедуры заканчивается. Независимо от того, принимает ли подпрограмма входные параметры или нет, является ли она функцией или процедурой - точка с запятой в конце быть должна.

Описание входных параметров

Теперь разберёмся, как описать входные параметры. Делается это ни чуть не сложнее, чем описание обычных переменных. Всё, что вам нужно сделать - это открыть круглую скобку после имени подпрограммы, перечислить параметры как обычные переменные, т.е. в формате "имя: тип_данных" и закрыть скобку. При этом переменные одного типа можно перечислять как через запятую, так и отдельно. Сами параметры отделяются друг от друга точкой с запятой, что вполне логично.

function Sum(A,B: Integer)

или

function Sum(A: Integer; B: Integer)

Возвращаемое значение (только у функций)

Остался последний штрих: если мы описываем функцию, то должны указать, каково будет её выходное значение. А точнее, какой тип данных это значение имеет. Само значение, конечно, мы установим в процессе выполнения функции. Если функция возвращает всё время одно и то же значение, то у неё нет смысла и её можно заменить на процедуру, а само значение сделать константой.
Итак, нам нужно задать тип данных выходного значения функции. Как это сделать? А вполне логичным, как всегда, способом - как при описании переменной. Только представьте теперь, что имя переменной - это имя вашей подпрограммы. На входные параметры внимания не обращайте - считайте, что это всё является именем переменной. Итак, ставим в конце двоеточие и далее указываем тип данных. Вот и всё.
Для нашего примера:

function Sum(A,B: Integer): Integer;
Сумма двух целых чисел, очевидно, тоже целое число. На этом описание нашей функции закончено.

Тело подпрограммы

Заголовок написан, дальше дело за малым - написать тело подпрограммы. Здесь ничего особенного - всё пишется также, как и раньше. Входные параметры становятся самостоятельными переменными и к ним можно обращаться обычным образом. Итак:

procedure|function имя_подпрограммы [входные_параметры] [: тип_данных_выходного_значения];
  {раздел описаний}
begin
  {раздел реализации}
end;

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

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

Указать выходное значение функции очень легко. Существует 2 способа сделать это, и оба заключаются в присвоении значения "воображаемой" переменной. Первый способ - можно присвоить значение самой функции, т.е. использовать её название как имя переменной и выполнить присвоение. Второй способ - присвоить значение переменной Result. Эта переменная существует только в рамках данной функции, но описывать её нигде не нужно. Вернёмся к нашему примеру функции, выполняющей сложение двух чисел. Ниже представлены оба способа задания возвращаемого значения:

function Sum(A,B: Integer): Integer;
begin
  Sum:=A+B
end;
function Sum(A,B: Integer): Integer;
begin
  Result:=A+B
end;

Эти записи эквивалентны и означают абсолютно одно и то же.

Где располагать подпрограмму?

Наверняка, у вас возник вопрос, в каком месте писать подпрограмму? Давайте разбираться. Во-первых, её нужно писать в таком месте, чтобы программа могла её найти. Подпрограммы можно описывать в разделе описаний. Да, именно там, где описываются переменные, только над ними (т.е. выше). Например, если ваша подпрограмма используется только в обработчике нажатия кнопки и больше нигде, то её можно поместить в раздел описаний этого обработчика. Тогда из других обработчиков подпрограмма видна не будет. Второе правило - любая подпрограмма должна быть описана выше того места, где она вызывается. Т.е. нельзя вызывать подпрограмму, которая расположена ниже - компилятор на этот момент времени о подпрограмме знать ничего не будет. Собственно, это правило применимо и к переменным, и к константам и к любым другим элементам - описание должно идти ранее первого обращения к этому элементу.
Чтобы подпрограмма была видна из любого места текущего модуля (т.е. текущей формы), её следует описать в разделе implementation выше всех обработчиков событий:

{...}
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure MyProc1;
procedure MyProc2;
{...}
function MyFunc1: Integer;
function MyFunc2: Real;
{...}
 
{обработчики}
 
end.

Пример

Пусть требуется найти максимальное из трёх введённых чисел с использованием подпрограммы. Числа будут вводиться в 3 текстовых поля TEdit, результат будет появляться при нажатии на кнопку в текстовой метке TLabel.
Подпрограмма будет принимать на вход 3 параметра - 3 числа и возвращать максимальное из этих чисел. Её заголовок будет приблизительно таким:

function Max3(A,B,C: Integer): Integer;

Реализация тоже довольно проста: например, принимаем первое число за максимальное, а далее смотрим - если второе/третье больше него, то максимальным будет это второе/третье. Итак, полное описание функции:

function Max3(A,B,C: Integer): Integer;
begin
  Result:=A;
  if B > Result then
    Result:=B;
  if C > Result then
    Result:=C
end;

Ну а далее то, что вы уже прекрасно знаете и умеете:

procedure TForm1.Button1Click(Sender: TObject);
 
function Max3(A,B,C: Integer): Integer;
begin
  Result:=A;
  if B > Result then
    Result:=B;
  if C > Result then
    Result:=C
end;
 
var N1,N2,N3: Integer;
 
begin
  N1:=StrToInt(Edit1.Text);
  N2:=StrToInt(Edit2.Text);
  N3:=StrToInt(Edit3.Text);
  Label1.Caption:='MAX = '+IntToStr(Max3(N1,N2,N3));
end;

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

Важно: обратите внимание, что имена переменных, передаваемых в качестве параметров, не обязаны быть одинаковыми. В данном случае передаются только значения (числа). В объявлении функции указаны имена A, B, C, а значения подставляются из переменных N1, N2, N3. При этом, вместо переменных можно указать вполне конкретные значения, например Max3(N1,10,N3).

Заключение

На этом изучение подпрограмм не закончено. Есть ещё важные моменты и приёмы, о которых нужно знать. Их мы рассмотрим в следующем уроке.

Домашнее задание

Составить подпрограммы:

  1. Для вычисления факториала указанного числа.
  2. Для преобразования текста, содержащего русские буквы, в верхний регистр.
  3. Для вычисления результата импликации двух логических выражений (A -> B).

Примечание к заданию 1: Факториалом числа n называется произведение 1*2*3*...*n и обозначается факториал "n!". Факториал числа 0 равен 1.
Примечание к заданию 3: Импликация (лат. implico - тесно связываю) - логическая операция, образующая сложное высказывание из двух высказываний посредством логической связки, соответствующей союзу "если ..., то ...". Импликация ложна лишь в случае истинности первого выражения и ложности второго и истинна во всех остальных случаях. Обозначается импликация стрелкой вправо (A -> B).


Оцените данный урок (1 - плохо, ..., 5 - отлично): -1- -2- -3- -4- -5-. Комментарии в тексте письма приветствуются.
 

Статьи

Самые популярные статьи на сайте:

Работа с приложениями Microsoft Office. Excel
Конвертирование графических форматов
Работа с приложениями Microsoft Office. Word
Как можно из Delphi отслеживать все события Windows?
Написание инсталлятора на Delphi
Работа с реестром и INI-файлами в Delphi
Работа со строковыми типами данных
Создание непрямоугольных форм в Delphi
Как прочитать ID3-Tag'и из MP3-файла?
Работа с HTML-справкой в программах

Рефакторинг

Автор: Вадим К

Сложность программы растет до тех пор, пока не превысит способности программиста... (из законов Мерфи)

Вступление

Очень часто, когда проект разрастается, наступает такой момент, когда он начинает разваливаться. Так умирали многие хорошие проекты – их создатели проигрывали схватку с горой кода. Странно было бы, если бы никто ничего не придумал для упрощения "разгребания кода".

И действительно, такая технология существует и называется Рефакторинг. На английском пишется "Refactoring" и мне кажется, что лучше переводить как "повторная движущая сила". Вполне оправданное название.

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

Так что же такое рефакторинг? Wikipedia даёт длинный ответ: "Рефакторинг или Реорганизация — процесс полного или частичного преобразования внутренней структуры программы при сохранении её внешнего поведения. В его основе лежит последовательность небольших эквивалентных (т.е., сохраняющих поведение) преобразований. Поскольку каждое преобразование маленькое, программисту легче проследить за его правильностью, и в то же время, вся последовательность может привести к существенной перестройке программы и улучшению её согласованности и четкости. Рефакторинг позволяет разрабатывать архитектуру программы постепенно, откладывая проектные решения до тех пор, пока не станет более ясной их необходимость».

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

Переименование

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

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

Выбираем подопытную функцию, в которой находим переменную для переименования. Оставляем просто на ней текстовый курсор и идём в меню Refactor » Rename (или комбинацию клавиш Ctrl+Shift+E). Появится окошко:

Окно "Rename variable"

В поле "New name" вводим новое имя. Галочку "View reference before refactoring" (показать, что изменится перед самим изменением) на первое время рекомендую оставлять – будете видеть, что меняется; потом её обычно снимают. Жмём ОК и видим, как в нижней части редактора появилось небольшое окно:

Окно со списком изменений при переименовании переменной (Rename variable)

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

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

Попробуйте выделить в редакторе кода имя кнопки или формы и попробовать его переименовать. В окошке Refactoring в самом низу можно будет увидеть фразу VCL Designer Update – компонент будет переименован не только в коде, но и на форме. По-моему, очень удобно.

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

Для того, чтобы сделать всё это, Delphi делает лексический/синтаксический анализ кода. Что-то вроде компиляции на лету. Наверное, вы уже заметили, что неверные участки кода подчёркиваются волнистой линией (хотя иногда и неверно).

Извлечение методов

А теперь представим такую ситуацию. Есть очень большая процедура. Надо из неё выделить кусочек кода в отдельную процедуру ("разделяй и властвуй"). Маленькие куски кода проще поддаются анализу. Существует негласное правило, что процедуры больше 30 строк – это очень плохо. Процедура извлечения в меню называется Extract Method.

Выделите у себя в коде небольшой участок кода и нажмите Ctrl+Shift+M (или выберите в меню Refactor » Extract Method). Появится следующее окно:

Окно "Extract Method"

Теперь достаточно ввести имя процедуры и нажать "ОК". При этом анализируются переменные, переносятся в новую подпрограмму, организовывается список параметров.

Правда, у этого метода есть пара недостатков. Delphi не может извлечь метод, если в нём есть команда Exit или оператор Continue/Break и мы находимся внутри цикла, которому они принадлежат. Но и мы не всегда сходу можем выделить в таком коде процедуру.

Также замечен один баг – если в функции после извлечения не остаётся своих локальных переменных, то список их очищается (что ожидалось), но слово var не удаляется. Что ж поделаешь...

Объявление переменных

Как иногда не хочется перемещаться в блок объявления переменных и вписывать туда новую переменную... Хорошо, если это процедура и всё просто. А если это новый метод класса?

Всё предельно просто. Пишем код, но переменную не объявляем. Потом, оставив курсор на ней, выбираем в меню Refactor » Declare variable (Ctrl+Shif+V).

Окно "Declare Variable"

К сожалению, Delphi иногда не может "угадать" тип переменной, и подставляет TObject, но курсор сразу оказывается в поле Type, следовательно, можно сразу ввести имя типа и нажать Enter. Отметив галочку Set Value (установить начальное значение), будет добавлен код инициализации нашей новой переменной.

Аналогичным способом можно объявлять новые поля для классов. А для объявления ручками иногда приходится скроллить сотни строк...

Уточнение имени типа

Иногда помнишь имя типа, но немного забыл. Или обявляешь переменную какого-то типа, а оно не хочет с ней компилироваться, ругается (причина проста – есть ещё один класс/тип с таким же именем). Как найти эти типы? Очень просто. Для этого вызываем в меню пункт Refactor » Find Unit (Ctrl+Shift+A).

Окно "Find Unit"

Как видно, я написал часть имени и были найдены все типы и функции, которые содержат это слово. Вот только мне непонятно, почему выделенное не вставляется по нажатию Ок. А то было бы очень удобно. Но этот диалог употребляется в другом месте – там он отрабатывает по полной программе.

Изменение параметров функции/метода

Иногда нужно добавить в функцию новый параметр или удалить старый. В этом случае Delphi тоже предоставляет инструмент. Для этого нужно, чтобы текстовый курсор был на имени процедуры в её объявлении (в той строке должно быть слово procedure или function). А потом в меню выбираем Refactor » Change Params... Дальнейшее изучение этого метода оставляю как домашнее задание.

А что делать с младшими версиями Delphi?

Здесь на помощь придут такие инструменты как Castalia (http://www.twodesk.com/castalia/index.html). У них на сайте можно посмотреть демонстрацию возможностей. Как по мне, то некоторые вещи реализованы очень хорошо. Но автодополнения кода иногда вызывает неконтролируемую агрессию с моей стороны – я его просто отключаю. Но есть один существенный недостаток – продукт платный.

Также на помощь может прийти MMX (http://www.modelmakertools.com/code-explorer/index.html). Вначале он вызывает непонятные чувства, но потом помогает находить спорные участки кода, сортировать процедуры, управлять комментариями к процедурам.

Вывод

Используя рефакторинг, вы можете дать своему продукту вторую жизнь. Но также он очень помогает ускорить процесс написания кода, ведь вначале можно написать, потом улучшить. Конечно, откровенно неверный код рефакторинг не улучшит, но работающий код в руках опытного программиста может превратиться в красивый и легкосопровождаемый. Если вас заинтересовала эта тема и вы хотите узнать о рефакторинге больше – поищите книги/статьи Мартина Фаулера.

Файловый архив

Разделы: Статьи | Компоненты | Plug-in's | Документация | Исходники | Программы | Игры | Изображения

Уважаемые читатели! Отправляйте полезные компоненты/модули, исходники, собственные программы/игры, документацию - книги, учебники и они будут размещены на сайте.

Название
Описание
Раздел
Объём
Ссылки
PlayList
Модуль для чтения популярных форматов плей-листов мультимедиа-плееров.
Поддерживаемые форматы:
- PLS;
- M3U;
- BSPlayer плей-листы (незашифрованные);
- плей-листы Light Alloy;
- плей-листы Media Player Classic;
- Windows Media плей-листы.
2 Кб
Delphi HTML Help Kit
Просто добавьте 3 строки кода в модуль главной формы приложения и система помощи будет автоматически переведена из WinHelp в HTMLHelp.
31 Кб
MIDI I/O Components
Компоненты для низкоуровнего управления звуковым MIDI входом и выходом с использованием функций Windows для работы с MIDI.
40 Кб
ID3Engine Component
Компонент для извлечения информации о MP3-тегах ID3v2.

56 Кб

TID3v1 Class
Класс TID3v1 - для управления ID3v1 тегами. Полная поддержка ID3v1.0 и ID3v1.1 тегов (чтение и запись).

11 Кб

TID3v2 Class
Класс TID3v2 служит для извлечения информации из тегов ID3v2. Имеется поддержка тегов ID3v2.3.x (чтение). Информация, хранимая в тегах: название, исполнитель, альбом, трек, год выпуска, жанр, комментарии.

10 Кб

TWAVFile Class
Класс TWAVFile предназначен для извлечения информации из заголовка WAV-файла.
Информация: канальный режим, сэмпловая частота, битовая частота, объём файла, длительность.

7 Кб

KGrid

Хорошая замена компонент из модуля Grids.pas (т.е. TStringGrid и TDrawGrid). Компоненты просты в использовании, но работают быстро и имеют довольно много возможностей.
Основные возможности и преимущества перед стандартными компонентами:
- 95% совместимости с TDraw(String)Grid;
- строки, столбцы и ячейки - классы, которые могут быть изменены для осуществления дополнительных функций, либо добавления новых свойств;
- любой компонент TWinControl может быть использован как редактор в ячейке, причём для разных ячеек редактор можно назначить разный;
- поддержка Юникода;
- разносторонняя настройка интерфейса;
- обрезание ячеек и двойная буферизация;
- дополнительные строка/столбец в конце для исключения случая появления полосы прокрутки;
- виртуальная сетка - размещение данных не ограничивается текущей сеткой;
- разнообразная отрисовка ячеек;
- индексация строк/столбцов заданием специального уникального значения;
- универсальная и унифицированная система событий;

Примечание: для установки требуется наличие библиотеки JEDI (JCL).

Совместимость: D2005 D2006 D2007 D6 D7.
Исходный код: есть.
Программа-пример: есть.

519 Кб

Run-time Object Inspector
Object Inspector, очень похожий на соответствующий из оболочки Delphi. Показывает иерархию объектов в приложении, а также published свойства объектов. И всё это - в runtime.

120 Кб

TIEHTTP - The Internet Explorer HTTP/HTTPS GET/POST component

Компонент осуществляет соединение с web-сервером POST или GET запросом с помощью HTTP/HTTPS механизма браузера Internet Explorer. Поддерживаются режимы multipart и urlencoded.
Имеется поддержка multipart-содержимого, декомпрессии данных, неверных или истёкших сертификатов. Для соединения используется текущий прокси-сервер. Соответственно, всё, что нужно сделать - это указать адрес (URL) и вызвать метод, осуществляющий соединение.
Компонент поддерживает Юникод и корректно работает с кодировками UTF-8, UTF-16 и ANSI.
Также имеется поддержка gunzip (gzip) с помощью бибилотеки zlib.

Совместимость: D2005 D2006 D2007 D6 D7.
Исходный код: есть.

73 Кб

Справочник по инструкциям и функциям InterBase SQL Данный документ является частичным переводом документации InterBase4.2. Документ содержить перевод книги SQL Statement And Function Reference, которая описывает синтаксис и использование каждой функции и инструкции InterBase SQL, дополненный главами из других разделов документации.
95 Кб
Oracle - Руководство разработчика Документация по установке Oracle, его настройке, основах языка SQL, архитектуре Oracle, способах оптимизации. В комплекте множество примеров.
2.04 Мб
 
Всего новых файлов: 12  
3 Мб
 
 

Юмор

Ведущий раздела: Bruder

Если бы WINDOWS была написана в Одессе...

1. После загрузки Windows появляется надпись "Таки я загрузилась!" и в течение 15 минут играет мелодия "Семь сорок", которую нельзя ни приостановить, ни отменить.

2. При нажатии на клавишу «Старт» появляется сообщение "Ну, шо ты тут клацаешь, пошел бы лучше в футбол поиграл...".

3. Клавиатурный драйвер автоматически преобразовывает букву "г" в букву "х", а букву "ч" в букву "ш".

4. При открытии нового документа по умолчанию ему присваивется название "Шоб ты был здоров.doc".

5. При подсоединении к Интернету появляется надпись: "Шо ты занимаешь линию? А вдруг мама позвонит?"

6. При открытии любой папки или файла появляется предупреждающее сообщение: "И оно тебе туда надо?"

7. При инсталяции любой программы появляется сообщение: "Ну и куда ты собираешься писать, поц? Ты купил новый харддрайв?"

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

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

10. Каждые 30 минут автоматически включается screensaver с надписью: "Ой-вей, я устала..."

:))

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




Ведущий рассылки: Ерёмин Андрей


В избранное