Отправляет email-рассылки с помощью сервиса Sendsay

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

  Все выпуски  

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


Программирование на DELPHI
Выпуск #79 (16 февраля 2008 г.)

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

Delphi.int.ru

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

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

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

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

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

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

Что сказать... Обычный выпуск рассылки. На сайте никаких существенных изменений не произошло.

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

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

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

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

  • Обучение - урок 18: Работа со строками и символами;
  • Статья: Создание интерфейса с использованием PNG-графики;
  • Файловый архив - новые программы, компоненты и исходники.

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

Количество экспертов: 45 (-2).
Участниками задано вопросов: 1340 (+37).
Экспертами отправлено ответов: 1926 (+44).
Количество сообщений на мини-форумах: 2456 (+77).
Максимальное число разосланных в день писем (за февраль '08): 1578 (04.02.2008).
Максимальное число разосланных в день писем (за всю историю): 1960 (28.10.2007, +0).

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

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

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

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

Количество читателей рассылки (16.02.2008, 10:00):
5587+1646+457= 7690 (+62)

Связь по e-mail:

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


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

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

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

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

3 февраля 2008 г.

Введены новые правила по использованию имён на сайте (ников, ФИО). Имя должно быть уникальным, т.е. не должно повторяться среди нескольких пользователей. Кроме этого описаны общие правила использования имён. У участников, имена которых дублировали друг друга, произведено автоматическое изменение имени путём добавления к имени уникального номера (ID).

6 февраля 2008 г.

Улучшен интерфейс работы с личными сообщениями (добавлены кнопки быстрой навигации между сообщениями и др.) Добавлена опция "Уведомления о новых личных сообщениях".

 

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

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

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

Кол-во вопросов: 14
Кол-ответов: 33
Баллы за ответы: 112
 

Вопрос # 341

Подскажите, пожалуйста, каким образом можно преобразовывать данные из String в Real?

Вопрос задал: Васильев Алексей Александрович (статус: Посетитель)
Вопрос отправлен: 23 февраля 2007, 18:17 (эксперты)
Всего ответов: 3; сообщений в мини-форуме вопроса: 4

 

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

Здравствуйте, Васильев Алексей Александрович!
function StrTofloat(const S: string): Extended;
Пример использования:
var
S: string;
R: real;
begin
S := 3,14;
R := StrToFloat(S);
end;

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

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

var
r:real;
s:string;
i:integer;
begin
r:=strtofloat(s);//разделитель-запятая, если у вас русская Windows. Для английской - точка
Val(s,r,i);
//Разделитель всегда точка. Эта процедура не генерит ошибки в случае невозможности преобразовать. Переменная i равна будет нулю, если при преобразовании небыло ошибок.
В противном случае собержит номер символа, который "непонравился". Содержимое переменной-результата при этом считается неопределённым.

====
Матчасть неучим?

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 23 февраля 2007, 18:42
Оценка за ответ: 5

3. Отвечает эксперт: Лукьяненко Алексей Валериевич

В качестве варианта, чтоб не видеть ошибки и при этом получать хоть что-то, можно использовать StrToFloatEx(Value: String; Default: Extended)
последний параметр - значение по-умолчанию, которое возвращается, если Value не является корректным float значением.

Ответ отправил: Лукьяненко Алексей Валериевич (статус: 1-ый класс)
Ответ отправлен: 23 февраля 2007, 19:27
Оценка за ответ: 5


Вопрос # 342

Дорогі експерти допоможіть будьласка, підскажіть як можна зчитати дані з файла Excel,з розширеням *.xls в Delphi. Дуже потрібно!!!!!!!!!

Вопрос задал: Шарайчук Сергій Олександрович (статус: 1-ый класс)
Вопрос отправлен: 23 февраля 2007, 18:49 (эксперты)
Всего ответов: 3; сообщений в мини-форуме вопроса: 7

 

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

var
Excel: variant;
i, j: word;
S: string;
begin
Excel := CreateOleObject('Excel.Application');
Excel.Workbooks.Open(FileName);
Excel.Visible:=True;
for i := 1 to 5 do
for j := 1 to 5 do
begin
S := Excel.Sheets[1].Cells[i,j].Text;
//Sheets[I] - номер таблицы в файле
ShowMessage(S);
end;
end;

Ответ отправил: Федоров Роман Сергеевич (статус: 2-ой класс)
Ответ отправлен: 23 февраля 2007, 19:06
Оценка за ответ: 3
Комментарий: Excel := CreateOleObject('Excel.Application');Что ето такое'Excel.Application', делфи дайот ошибку???

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

Дополню к предыдущему эксперту.
Ошибка идёт не на 'Excel.Application'
Делфи и знать это не надо - так как это строка, котороую она передаёт в функцию, а на CreateOleObject() - так как она не знает, где искать эту функцию.
Просто добавте в список uses (тот что в вверу, в третей-четвёртой строке) ещё один модуль ComObj. Также не забудьте в качестве FileName написать реальное имя файла (в одинарных кавычках!) или обявить такую переменную и присвоить ей соответстующее значение

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 23 февраля 2007, 19:43
Оценка за ответ: 1

3. Отвечает эксперт: Бубырь Александр Николаевич

Корректнее нужно формулировать вопрос.
Что вы хотите:
1)открыть XLS файл при помощи Excel - Вам привели примеры;
2)Вас не устраивает Excel - можно использовать бесплатный OpenOffice Calc - открыть будет не многим сложнее;
3)Вам необходимо работать с XLS файлами из своей программы даже если в системе не установлет Excel, Calc и им подобные - нужно использовать готовые компоненты для этого, советую поискать на www.torry.ru или www.delphikingdom.com
4)еще какие-то заморочки - формулируйте чего хотите.
Успехов.

Ответ отправил: Бубырь Александр Николаевич (статус: 6-ой класс)
Ответ отправлен: 24 февраля 2007, 00:14


Вопрос # 343

Здравствуйте. MediaPlayer1 проигрывает песню, которая находится в папке проекта.
В этой папке есть ещё песни, как сделать, так что бы после этой песни
он играл следующюю, потом ещё, короче говоря, все песни по очереди
которые находятся в этой папке. Снизу я написал код:
MediaPlayer1.Filename := './Тайна.MP3';
MediaPlayer1.Open;
MediaPlayer1.Play;
И если можно то подскажите, как проиграть все песни один раз, а другой
кнопке дать команду играть бесконечно. Заранее благодарен.

Вопрос задал: Толков Геннадий Викторович (статус: Посетитель)
Вопрос отправлен: 23 февраля 2007, 23:14 (эксперты)
Всего ответов: 3

 

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

Нужно сделать так. Перед началом воспроизведения сканируем каталог и составляем список файлов - список воспроизведения. Запишем его в TStringList
Вот эта процедура составит нужный список для заданого каталога.
procedure TForm1.Button1Click(Sender: TObject);
var fs:TSearchRec;
p:string;
begin
p:='D:\Music\';
if FindFirst(p+'*.mp3',faAnyFile,fs)=0 then
repeat
sl.Add(p+fs.Name);
until FindNext(fs)<>0;
FindClose(fs);
end;
здесь sl - класс типа TStringList
Дальше. Теперь надо иметь номер песни, которая воспроизводиться. Когда оканчивается песенка - просто инкрементируете номер и загружаете с списка имя файла.
Осталось малость - узнать, что кончилося воспроизведение. Для этого нужно в обработчике
OnNotify проверять состояние плеера (Mode и NotifyValye) Только не забудьте установить
MediaPlayer1.Notify:=true; где нибуть в FormCreate, иначе этот обработчик дёргаться не будет

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

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

Здравствуйте, Толков Геннадий Викторович!
Предложу свой вариант немного отличающийся от варианта эксперта Вадим К.

var
Files: TStringList;
Number: Integer;
MRepeat: Boolean;

procedure TForm1.FormCreate(Sender: TObject);
var
MFile: TSearchRec;
Path: String;
begin
Path := '(* Здесь указать путь к директории с файлами *)';
Files := TStringList.Create;
MediaPlayer1.Notify := True;
MediaPlayer1.OnNotify := NotifyProc;
if FindFirst(Path+'*.mp3',faAnyFile,MFile)=0 then
repeat
Files.Add(Path+MFile.Name);
until FindNext(MFile)<>0;
FindClose(MFile);
end;

procedure TForm1.Button1Click(Sender: TObject);
//при нажатии на кнопку Button1
//начнется воспроизведение первой песни
// из каталога
begin
MediaPlayer1.FileName := Files.Stringd[0];
Number := 0;
MediaPlayer1.Open;
MediaPlayer1.Play;
end;

procedure TForm1.NotifyProc(Sender: TObject);
begin
with Sender as TMediaPlayer do
begin
case Mode of
mpStopped: begin
if Number < Files.Count -1
then begin
Inc(Number);
MediaPlayer1.FileName := Files.Strings[Number];
MediaPlayer1.Open;
MediaPlayer1.Play;
end else
if MRepeat then begin
Number := 0;
MediaPlayer1.FileName := Files.Strings[Number];
MediaPlayer1.Open;
MediaPlayer1.Play;
end;
end;
end;
Notify := True;
end;
end;

procedure TForm1.Button2OnClick(Sender: TObject);
//Установка повторения
begin
MRepeat := True;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Files.Free;
end;

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

3. Отвечает эксперт: Дима Гусаков

Здравствуйте, Толков Геннадий Викторович!
Можно на форму поместить компонент ListBox (видимый или нет) в который записать все песни, находящиеся в папке, и указывать их как в MediaPlayer1.Filename поочереди.

Ответ отправил: Дима Гусаков (статус: 2-ой класс)
Ответ отправлен: 24 февраля 2007, 19:54
Оценка за ответ: 5


Вопрос # 344

Приветствую!!!У меня сложный вопрос.Мне нужен новый компонент,но не знаю существует ли такой.Это DBGrid,но должен состоять не из DBEdit,а из DBLookUpComboBox.А в идеале должна быть возможность выбирать тип колонки.Если с чем нибудь подобным сталкивались прошу помочь ссылкой или советом по созданию.Благодарю!!!

Вопрос задал: KilkaMS (статус: Посетитель)
Вопрос отправлен: 24 февраля 2007, 00:27 (эксперты)
Всего ответов: 2

 

1. Отвечает эксперт: Alex Van Glukhman

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

Ну вообще то для того чтобы в гриде появился LookUp Combo достаточно в таблице с которой связан DBGrid создать LookUp поле.
Почитай вот это материал http://www.delphikingdom.com/asp/viewitem.asp?catalogid=806
Удачи!

Ответ отправил: Alex Van Glukhman (статус: 7-ой класс)
Ответ отправлен: 24 февраля 2007, 02:39
Оценка за ответ: 4
Комментарий: Благодарю за ссылочку,но это немного не то.Подобный механизм я уже реализовывал.

2. Отвечает эксперт: Помфюк Владимир Степанович

Здравствуйте, KilkaMS!
Можете создавать свой Grid на базе TDBCtrlGrid, но к сожалению туда нельзя поместить TDBLookupCombobox и TDBLookupListBox, так что Вам надо будет вручную перечитывать данные и записывать их в TDBComboBox.Items

Ответ отправил: Помфюк Владимир Степанович (статус: Абитуриент)
Ответ отправлен: 26 февраля 2007, 09:59


Вопрос # 345

Ещё раз здравствуйте. Хочу задать ещё вопрос? Можно в Delphi
дать команду кнопке отключить компьютер в то время, какое я укажу. Или хотя бы отключить от интернета в нужное мне время.
Конечно лучше было вобще отключить его.
Заранее благодарен.

Вопрос задал: Толков Геннадий Викторович (статус: Посетитель)
Вопрос отправлен: 24 февраля 2007, 03:35 (эксперты)
Всего ответов: 2; сообщений в мини-форуме вопроса: 8

 

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

Здравствуйте, Толков Геннадий Викторович! Вот код необходимый для завершения работы Windows.А для отключения в заданное время нужно просто сравнивать системное время с заданным:
var NewTime,Sdn:TDateTime; если дата у нас в TEdit, то : Snd:=TimeToStr(Edit1.Text); теперь в Sdn у нас время когда мы хотим выключить комп. И по Timer1Timer проверяем: NewTime:=New; if (Sdn-NewTime)< 0 then ... отрубаем. Всё.

Приложение:

Ответ отправил: Роман (статус: 5-ый класс)
Ответ отправлен: 24 февраля 2007, 04:29
Оценка за ответ: 4
Комментарий: Здравствуйте. Мне здесь не сильно понятно где время выставить,ну допустим 6 часов
утра. Запустил свою программу
поставил качать, и спать, а в 6 часов программа отключила бы его. Заранее благодарен.

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

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

Приложение:

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


Вопрос # 346

Шановне панство тут вот какой вопрос:имеем bass.dll,собираю эквалайзер.Нужно сделать так чтобы аудиоданные с stereomix-ера перенаправлялись на эквалайзер и уже после обработки на аудиокарту.Короче надо регулировать тембр всего что воспроизводится.Так вот собственно вопрос как реализовать перенаправление аудиопотока?

Вопрос задал: Роман (статус: 5-ый класс)
Вопрос отправлен: 24 февраля 2007, 05:03 (эксперты)
Всего ответов: 1

 

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

Здравствуйте, Роман!
Используйте бесплатный набор классов AOSDK от Porzillosoft.Inc, http://www.torry.net/authorsmore.php?id=3702. Там уже реализованы функции эквалайзера.
Или можете просто подсмотреть и использовать для себя. Там никакой аудиопоток не перехватывается, а просто меняются параметры аудиодвижка.

Ответ отправил: Матвеев Игорь Владимирович (статус: Студент)
Ответ отправлен: 27 февраля 2007, 10:49
Оценка за ответ: 4
Комментарий: Спасибо за уделённое внимание,но проблема не в реализации эквалайзера или FFT;AOSDK призван просто упростить написание плеера на bass.dll.


Вопрос # 347

Здравствуйте все!!! Если не сложно поскажите плисс...
Нужно сделать следующее
g:=t div 60;
только проблема в том, что t есть не "integer", а "real".

...или как просто от числа откинуть все после комы (например, есть число 3,75, а сделать из него просто 3).
Но чтобы при этом оно не округлилось, а просто откинулся "хвостик"...

Вопрос задал: Pokemonchyk (статус: Посетитель)
Вопрос отправлен: 24 февраля 2007, 18:07 (эксперты)
Всего ответов: 5; сообщений в мини-форуме вопроса: 8

 

1. Отвечает эксперт: Евгений Козаченко

Приветствую!
Используйте функцию trunc(x). Она усекает дробное часть.

Приложение:

Ответ отправил: Евгений Козаченко (статус: 2-ой класс)
Ответ отправлен: 24 февраля 2007, 19:11
Оценка за ответ: 3

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

Здравствуйте, Pokemonchyk!
Есть еще функция Int.
function Int(X: Extended):Extended - Возвращает целую часть параметра X.

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

3. Отвечает эксперт: Alex Van Glukhman

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

В делфях есть очень хороший тип Variant. Можно сделать так.

var
t: Variant;
g: integer;
begin
t:=60.5678;
g:=t div 60
ShowMessage(IntToStr(q));
end;

Удачи!

Ответ отправил: Alex Van Glukhman (статус: 7-ой класс)
Ответ отправлен: 24 февраля 2007, 21:04
Оценка за ответ: 4

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

Вариант с trunc правильный, но не самый быстрый. По моим тестам Round(Int(x)) на 30-40% быстрей.

Вариант с int, предложеный Федоров Роман Сергеевич не подходит, так как он возвращает вещественное число, которое соответственно не может участвовать в операции div.

Вариант с Variant тоже хорош, но нет гарантии, что Делфи всегда будет откидать дробную часть правильно.

Также хочу заметить, что в случае отрицательных чисел есть два варианта отбрасывания дробной части и для них есть свои функции
Как они отличаются - обясняю на примере
Ceil(-2.8) = -2//вправо по оси Х
Ceil(2.8) = 3
Ceil(-1.0) = -1

Floor(-2.8) = -3//влево по оси Х
Floor(2.8) = 2
Floor(-1.0) = -1

Trunc(-2.8) = -2//к нулю
Floor(2.8) = 2
Floor(-1.0) = -1
Но все они возвращают вещественное число, и вам нужно будет функция Round

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 24 февраля 2007, 23:39
Оценка за ответ: 5

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

Попробуй так, роботает 100 процентов!!!!

Приложение:

Ответ отправил: Шарайчук Сергій Олександрович (статус: 1-ый класс)
Ответ отправлен: 26 февраля 2007, 21:23


Вопрос # 348

Приветствую!!!!У меня такой вопрос:можно ли с InterBase работать через ADO???

Вопрос задал: KilkaMS (статус: Посетитель)
Вопрос отправлен: 25 февраля 2007, 00:32 (эксперты)
Всего ответов: 2

 

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

конечно можно - нужно только поставить соответствующий драйвер для ODBC, так как по умолчанию его нет. Скачать можно здесь http://www.ibphoenix.com/main.nfs?page=ibp_60_odbc

Но я не советую использовать по следующим причинам
Вы не получите полной производительности
Вы не сможете получить доступ ко многим "вкусностям"

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

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

Здравствуйте, KilkaMS!
В дополнение к предыдущему ответу. Из своего опыта я не советую использовать ADO вообще, кроме случаев работы с СУБД от Microsoft (Access, MS SQL), т. к. вышеуказанные недостатки присущи не только Interbase/FireBird, но и всем остальным (Oracle, например). Более того, дело не всегда заканчивается ограничением только производительности, но и функциональности тоже.

Ответ отправил: Knjazev (статус: 3-ий класс)
Ответ отправлен: 25 февраля 2007, 10:38


Вопрос # 349

Доброго времени суток, уважаемые эксперты! Пишу программу просмотра статистики использования Интернета с сайта провайдера. Для доступа к статистике необходимо ввести логин и пароль, они совпадают с логином и паролем соединения с Интернетом.
Есть функция RasEnumEntries благодаря которой я получаю список всех соединений, с помощью RasGetEntryDialParams имя пользователя и пароль. С именем пользователя все нормально, а вот пароль получаеться как строчка состоящая из звездочек. Как можно получить нормальный пароль? Я понимаю, что это все похоже на "добывание" паролей, но бывают же случаи когда действительно такая информация испольльзуеться только для положительных целей, т.е. для уменешения количества настраиваемых опций программы и "легкости интерефеса".

Приложение:

Вопрос задал: Spawn (статус: 1-ый класс)
Вопрос отправлен: 25 февраля 2007, 07:58 (эксперты)
Всего ответов: 4; сообщений в мини-форуме вопроса: 2

 

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

Здравствуйте, Spawn!Тут наверно проблема в том что сама винда скрывает таким образом всё что связано с паролями.Поетому надо сделать DLL'ку с хуком (SetWindowsHookEx) и в ней перехватывать мессаги (если есть нужная мессага, то смотрим пароль).

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

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

Microsoft делает всё возможное, что бы "злосные хакеры" не могли так просто получить пароли. В ХР добыть их сложно, а в Vista - с включеным UAC - практически нельзя (нельзя обычными методами.)
Поэтому, наиболее корректным решением будет ввод пароля вручную.

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 25 февраля 2007, 18:33
Оценка за ответ: 4
Комментарий: Спасибо за внимание к вопросу. Но решение уже найдено, и исправно работает, выдает пароли DialUp'а, как семочки.

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

На етом сайте в розделе Исходники есть програма UnPass, она даёот возможность видеть символы под *, Там есть иходник етой програмы, он тебе поможет!!!!

Ответ отправил: Шарайчук Сергій Олександрович (статус: 1-ый класс)
Ответ отправлен: 26 февраля 2007, 20:57
Оценка за ответ: 3
Комментарий: Это абсолютно не то!

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

Здравствуйте, Spawn!
Там никакой пароль и не должен возвращаться - если бы там возвращался пароль в чистом виде, это была бы такая дыра в защите системы - просто дырища..
Вместо пароля там передается ручка (handle) на пароль, эту ручку можно использовать в функциях RasSetEntryDialParams и RasDial.
И не надо нападать на Микрософт - это объективно правильная реализация.

Ответ отправил: Матвеев Игорь Владимирович (статус: Студент)
Ответ отправлен: 27 февраля 2007, 10:35
Оценка за ответ: 4
Комментарий: Спасибо! Но Microsoft Windows все равно потвердила свою "дырявость". Решение на свой вопрос я уже нашел, и оно исправно работает. Немного доработаные функции из модуля RAS API выдают нормальный пароль... ;)


Вопрос # 350

Уважаемые программисты у мня один вопрос к Вам:
Мне необходимо узнать как ставить верхние и нижние индексы: P2O5, 3^2 и ещё при отображение расчётов где-нить в Мемо... показывать деление с числителем и знаменателем (34/23...)

Вопрос задал: Aйрат Гараев (статус: Посетитель)
Вопрос отправлен: 25 февраля 2007, 10:20 (эксперты)
Всего ответов: 1

 

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

Сделать в обычном Memo я даже не знаю как. Наверное единственный способ - перерисовывать вручную. Но это достаточно сложновато. Если вам нужно много такого отображения, то вам прямой путь к HTML. Для отображения вам понадобиться либо встроенный TWebBrouser либо скачать ThtmlViewer (pbeer.com, с недавнего времени - бесплатный).
Например, что бы написать оксид фосфора P2O5 (я так понимаю вы для химии делаете это) нужно написать в текстовом файле приблезительно следующее
P<sub>2</sub>O<sub>5</sub>

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 25 февраля 2007, 19:10


Вопрос # 351

Здравствуйте уважаемые эксперты.
Ответьте на такие вопросы:
1)Как реализовать многопользовательское приложение? Если есть возможность, дайте пример или ссылку в Интернете на литературу.
2) Для пояснения: когда открываешь несколько документов Word-а они появляются на панели задач. Как сделать так, чтобы в MDI приложении как в MYIE ссылки на окна были не на панели задач а, например, на панели MainForm? Надеюсь вы поняли вопрос!!
3)Имеются 2 таблицы в MSAccess. Они связанны внешним ключом через целочисленное поле (таблица1(id(int), name_id(string)), таблица2(id(int), type(string)), связь(по id(int))) Каким образом забить данные в колонку(id(int)) DBGrid(связанна с таблица2) так чтобы в списке были данные из таблица1 поля name_id(string)) и при выборе в списке значения(name_id(string)) в БД вводились не string-овые значения, а целочисленные. P.S. Такая возможность есть в таблицах MSAccess.

Вопрос задал: Ram (статус: Посетитель)
Вопрос отправлен: 25 февраля 2007, 17:26 (эксперты)
Всего ответов: 1; сообщений в мини-форуме вопроса: 2

 

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

Ну сколько просить - не пишите кучу вопросов в одном вопросе. Причём далёких друг от друга.
1) Главная проблема в таких задачах - разграничение доступа и настройки для каждого пользователя.
Настройки под каждого пользователя делаются просто. Перед стартом приложения вам необходимо идентифицировать пользователя - например вывести окошко с запросом имени/пароля. или узнать другим способом (к примеру пользователь обязан вставить флешку, на которой всё записано. Плюс получаем "перемещаемый профиль"). А дальше, зная имя, мы можем определить конфиг файл, с которого нужно подгрузить настройки. Для разграничения прав просто перед входом в основные процедуры проверяем имя и разрешения. Можно даже скрывать элементы интерфейса. Надеюсь обяснил:)
2)
>>Для пояснения: когда открываешь несколько документов Word-а они появляются на панели задач. >>Как сделать так, чтобы в MDI приложении как в MYIE ссылки на окна были не на панели задач а, например, на панели MainForm? Надеюсь вы поняли вопрос!!
Подождите, первое предложение относиться к предыдущему вопросу? Тогда это меняет суть вопроса. Чтобы дополнительные окна отображались на панели задач нужно перекрыть конструктор параметров
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
Params.WndParent := GetDesktopWindow;
end;
Что бы сделать как в MyIE нужно при создании форм делать запись в себя в массиве и о добавлять кнопку или вкладу. При закрытии - удалять
3)По поводу третего - собиритесь с мыслями и почитайте о базах данных. Я очень смутно представляю, что вы хотели узнать. Телепаты к сожалению на Канарах:)

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 25 февраля 2007, 19:26
Оценка за ответ: 5
Комментарий: Спасибо за ответ!!


Вопрос # 352

Хочу задать нестандартный вопрос. Он не относится к програмированию на Делфи, но как ни странно на него могут ответить только програмисты.
Где можно получить хорошее образование по программированию в Киевской области?

Приложение:

Вопрос задал: Pokemonchyk (статус: Посетитель)
Вопрос отправлен: 25 февраля 2007, 21:36 (эксперты)
Всего ответов: 3

 

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

Получите хорошее техничекое образование. А обучить программированию вас сможет только один человек - вы сами. Дело в том, что все известные вузы преподают достаточно устаревший материал - преподаватели не могут и нехотят изучать новые технологии. Курсы, которые обещают сделать с вас программиста - обычные шарлатаны (ну не все, но очень многие). А люди с их дипломами творят "чудеса"
Так что идите в магазин, берите пару книг потолще, в названии которых нет фраз
"Рукодоство для идиотов"
"Язык ХХХ за 21 день"
"Программирование для домохазяек"

Как пример могу посоветовать Рихтера, Шилда (С/С++/С#) Ксавье (Хавьер???) Пачеко, Рей Конопка (Делфи)
Купляем и учим, делаем задачки. Не пиво ходим пить, а решаем. Потом придумываем проект - и начинаем делать. Только так вы станете программистом

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 25 февраля 2007, 21:48
Оценка за ответ: 4

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

Здравствуйте, Pokemonchyk!
Абсолютно согласен с предыдущим ответом, но хочу тоже кое-что добавить. Я бы Вам, да и вообще всем, не советовал бы выбирать профессия "программист". Это сложная и тяжёлая работа и как это ни странно - низкооплачиваемая. Заработать можно только если работаешь сам на себя, напрямую с заказчиком. Но так сложно. А на фирме никаких шансов, только концы с концами сводить. Что касается предприятий - там вообще нечего делать.
Выбирайте сисадминство, зарплата такая же, а часто и больше, но работа попроще на порядок. Времени свободного будет больше - можно для себя программки делать и в Инете продавать. Это добрый бесплатный совет.

Ответ отправил: Knjazev (статус: 3-ий класс)
Ответ отправлен: 25 февраля 2007, 22:32
Оценка за ответ: 3

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

Волне согласен со всеми вами!Я считаю так, где бы ты неучилса тебя никто ненаучит таво чево ти научышса сам, конешно если ты и правда етово хочеш!!!

Ответ отправил: Шарайчук Сергій Олександрович (статус: 1-ый класс)
Ответ отправлен: 26 февраля 2007, 20:28


Вопрос # 353

Приветствую!!!У меня MSSQL Server,соединяюсь через ADO.Как до установки контакта проверить соединение?

Вопрос задал: KilkaMS (статус: Посетитель)
Вопрос отправлен: 25 февраля 2007, 22:52 (эксперты)
Всего ответов: 1; сообщений в мини-форуме вопроса: 2

 

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

А как вы проверете соединение, если ещё не установили соединение? Единственный способ - попытаться установить его. Но вам наверное не нравлятся ошибки, которые выпрыгивают при этом? Это дело легко обходиться с помощью следующей конструкции
try
//пытаеся подключиться
except
//А сюда мы попадаем, если в блоке выше было исключение
end;

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

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 25 февраля 2007, 23:34
Оценка за ответ: 3
Комментарий: Вы пробовали применять этот метод на практике в данной ситуации???Получается как у мелкософта...И ошибка появляется и время тратьиться.Может есть какая нить команда,которую можно послать серверу(MSSQL) и сделать вывод о его работе???


Вопрос # 355

Приветствую!!!Читал статью "Липкие окошки".
Вопрос такой:а можно ли организовать прилепание окошек и к другим окошкам тоже????

Вопрос задал: KilkaMS (статус: Посетитель)
Вопрос отправлен: 25 февраля 2007, 22:59 (эксперты)
Всего ответов: 2; сообщений в мини-форуме вопроса: 1

 

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

Вы хотя бы привели ссылку на статью, а то мне прийдётся догадываться.
Скорее всего липкие окошка реализованы следующим методом. В обработчике WM_MOVE проверяются текущие координаты формы, и если она находиться рядом с краем экрана - то прилипаем. А кто вам мешает проверять, не находитесь ли вы рядом с своим окном? Реализовать прилипание к всем окнам в системе наверное будет не то что сложно, скорее накладно со стороны операционной системы. А вот к окнам своего приложения - просто. Список всех окон (форм) своего приложения можно получить так.
Количество Screen.FormCount
Обратиться к конкретной форме Screen.Forms[номер]

Ответ отправил: Вадим К (статус: Кандидат наук)
Ответ отправлен: 25 февраля 2007, 23:48
Оценка за ответ: 5

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

Здравствуйте, NickStNew!
Попробу написать код для событея ONChange, а Index получить попробуй следуйщим способом:
i:=ComboBox1.item.itemindex

Ответ отправил: Шарайчук Сергій Олександрович (статус: 1-ый класс)
Ответ отправлен: 26 февраля 2007, 20:14
Оценка за ответ: 5


Обучение Delphi

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

15. Подводим промежуточный итог
16. Циклы - общее понятие; цикл с параметром
17. Циклы - цикл с предусловием и цикл с постусловием

Работа со строками и символами

Автор:
© Ерёмин А.А., 2008
Это письмо получилось таким длинным потому, что у меня не было времени написать его короче. (Блез Паскаль)
Номер урока:
18
 

Введение

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

Символы

Символ - это одна единица текста. Это буква, цифра, какой-либо знак. Кодовая таблица символов состоит из 256 позиций, т.е. каждый символ имеет свой уникальный код от 0 до 255. Символ с некоторым кодом N записывают так: #N. Прямо так символы и указываются в коде программы. Так как код символа представляет собой число не более 255, то очевидно, что в памяти символ занимает 1 байт. Как известно, менее байта размерности нет. Точнее, она есть - это бит, но работать с битами в программе мы не можем: байт - минимальная единица. Просмотреть таблицу символов и их коды можно с помощью стандартной утилиты "Таблица символов", входящей в Windows (ярлык расположен в меню Пуск - Программы - Стандартные - Служебные). Но совсем скоро мы и сами напишем нечто подобное.

Строки

Строка, она же текст - это набор символов, любая их последовательность. Соответственно, один символ - это тоже строка, тоже текст. Текстовая строка имеет определённую длину. Длина строки - это количество символов, которые она содержит. Если один символ занимает 1 байт, то строка из N символов занимает соответственно N байт.
Есть и другие кодовые таблицы, в которых 1 символ представлен не одним байтом, а двумя. Это Юникод (Unicode). В таблице Юникода есть символы всех языков мира. К сожалению, работа с Юникодом довольно затруднена и его поддержка пока что носит лишь локальный характер. Delphi не предоставляет возможностей для работы с Юникодом. Программная часть есть, но вот визуальные элементы - формы, кнопки и т.д. не умеют отображать текст в формате Юникода. Будем надеяться, в ближайшем будущем такая поддержка появится. 2 байта также называют словом (word). Отсюда и название соответствующего числового типа данных - Word (число, занимающее в памяти 2 байта, значения от 0 до 65535). Количество "ячеек" в таблице Юникода составляет 65536 и этого вполне достаточно для хранения всех языков мира. Если вы решили, что "1 байт - 256 значений, значит 2 байта - 2*256 = 512 значений", советую вспомнить двоичную систему и принцип хранения данных в компьютере.

Типы данных

Перейдём непосредственно к программированию. Для работы с символами и строками существуют соответствующие типы данных:

Char - один символ (т.е. 1 байт);
String - строка символов, текст (N байт).

Официально строки вмещают лишь 255 символов, однако в Delphi в строку можно записать гораздо больше. Для хранения больших текстов и текстов со специальными символами существуют специальные типы данных AnsiString и WideString (последний, кстати, двухбайтовый, т.е. для Юникода).

Для задания текстовых значений в Pascal используются одинарные кавычки (не двойные!). Т.е. когда вы хотите присвоить строковой переменной какое-либо значение, следует сделать это так:

s:='text';

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

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

var s: string[10];

В скобках указывается максимальная длина строки.

Операции со строками

Основной операцией со строками является сложение. Подобно числам, строки можно складывать. И если в числах стулья с апельсинами складывать нельзя, то в строках - можно. Сложение строк - это просто их объединение. Пример:

var s: string;
 ...
s:='123'+'456';
//s = "123456"

Поскольку каждая строка - это последовательность символов, каждый символ имеет свой порядковый номер. В Pascal нумерация символов в строках начинается с 1. Т.е. в строке "ABC" символ "A" - первый, "B" - второй и т.д.
Порядковый номер символа в строке придуман не случайно, ведь именно по этим номерам, индексам, осуществляются действия над строками. Получить любой символ из строки можно указанием его номера в квадратных скобках рядом с именем переменной. Например:

var s: string; c: char; 
 ...
s:='Hello!';
c:=s[2];
//c = "e"

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

Обработка строк

Перейдём к функциям и процедурам обработки строк.

Длина строки

Длину строки можно узнать с помощью функции Length(). Функция принимает единственный параметр - строку, а возвращает её длину. Пример:

var Str: String; L: Integer; 
{ ... } 
Str:='Hello!'; 
L:=Length(Str);
//L = 6

Нахождение подстроки в строке

Неотъемлемой задачей является нахождение подстроки в строке. Т.е. задача формулируется так: есть строка S1. Определить, начиная с какой позиции в неё входит строка S2. Без выполнения этой операции ни одну обработку представить невозможно.
Итак, для такого нахождения существует функция Pos(). Функция принимает два параметра: первый - подстроку, которую нужно найти, второй - строку, в которой нужно выполнить поиск. Поиск осуществляется с учётом регистра символов. Если функция нашла вхождение подстроки в строку, возвращается номер позиции её первого вхождения. Если вхождение не найдено, функция даёт результат 0. Пример:

var Str1, Str2: String; P: Integer; 
{ ... } 
Str1:='Hi! How do you do?'; 
Str2:='do'; 
P:=Pos(Str2, Str1);
//P = 9

Удаление части строки

Удалить часть строки можно процедурой Delete(). Следует обратить внимание, что это именно процедура, а не функция - она производит действия непосредственно над той переменной, которая ей передана. Итак, первый параметр - переменная строкового типа, из которой удаляется фрагмент (именно переменная! конкретное значение не задаётся, т.к. процедура не возвращает результат), второй параметр - номер символа, начиная с которого нужно удалить фрагмент, третий параметр - количество символов для удаления. Пример:

var Str1: String; 
{ ... } 
Str1:='Hello, world!'; 
Delete(Str1, 6, 7);
// Str1 = "Hello!"

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

Вот пример. Допустим, требуется найти в строке первую букву "a" и удалить следующую за ней часть строки. Сделаем следующим образом: позицию буквы в строке найдём функцией Pos(), а фрагмент удалим функцией Delete().

var Str: String; 
{ ... } 
Str:='This is a test.';
Delete(Str,Pos('a',Str),Length(Str));

Попробуем подставить значения и посмотреть, что передаётся функции Delete. Первая буква "a" в строке стоит на позиции 9. Длина всей строки - 15 символов. Значит вызов функции происходит такой: Delete(Str,9,15). Видно, что от буквы "a" до конца строки всего 7 символов... Но функция сделает своё дело, не смотря на эту разницу. Результатом, конечно, будет строка "This is ". Данный пример одновременно показал и комбинирование нескольких функций.

Копирование (извлечение) части строки

Ещё одной важной задачей является копирование части строки. Например, извлечение из текста отдельных слов. Выделить фрагмент строки можно удалением лишних частей, но этот способ неудобен. Функция Copy() позволяет скопировать из строки указанную часть. Функция принимает 3 параметра: текст (строку), откуда копировать, номер символа, начиная с которого скопировать и количество символов для копирования. Результатом работы функции и будет фрагмент строки.

Пример: пусть требуется выделить из предложения первое слово (слова разделены пробелом). На форме разместим Edit1 (TEdit), в который будет введено предложение. Операцию будет выполнять по нажатию на кнопку. Имеем:

procedure TForm1.Button1Click(Sender: TObject);
var s,word: string;
begin
  s:=Edit1.Text;
  word:=Copy(s,1,Pos(' ',s)-1);
  ShowMessage('Первое слово: '+word);
end;

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

Пример "посерьёзнее"

Примеры, приведённые выше, лишь демонстрируют принцип работы со строками с помощью функций Length(), Pos(), Delete() и Copy(). Теперь решим задачу посложнее, которая потребует комбинированного применения этих функций.

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

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

Интерфейс: Memo1 (TMemo), Button1 (TButton), ListBox1 (TListBox), Label1, Label2 (TLabel).

Сначала перенесём введённый текст в переменную. Для того, чтобы разом взять весь текст из Memo, обратимся к свойству Lines.Text:

procedure TForm1.Button1Click(Sender: TObject);
var Text: string;
begin
  Text:=Memo1.Lines.Text;
end;

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

procedure TForm1.Button1Click(Sender: TObject);
const DelSym = ' .,!?';
var Text: string; i: integer;
begin
  Text:=Memo1.Lines.Text;
  for i := 1 to Length(Text) do
    if Pos(Text[i],DelSym) > 0 then
      Text[i]:=',';
 
  Memo2.Text:=Text;
end;

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

if Text[1] = ',' then
    Delete(Text,1,1);
while Pos(',,',Text) > 0 do
  Delete(Text,Pos(',,',Text),1);
if Text[Length(Text)] <> ',' then
  Text:=Text+',';

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

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

var Word: string;
{...}
Word:=Copy(Text,1,Pos(',',Text)-1);
Delete(Text,1,Length(Word)+1);

Теперь в переменной Word у нас слово из текста, а в переменной Text вся остальная часть текста. Вырезанное слово теперь добавляем в ListBox, вызывая ListBox.Items.Add(строка_для_добавления).

Теперь нам нужно организовать такой цикл, который позволил бы вырезать из текста все слова, а не только первое. В данном случае подойдёт скорее REPEAT, чем WHILE. В качестве условия следует указать Length(Text) = 0, т.е. завершить цикл тогда, когда текст станет пустым, т.е. когда мы вырежем из него все слова.

repeat
  Word:=Copy(Text,1,Pos(',',Text)-1);
  Delete(Text,1,Length(Word)+1);
  ListBox1.Items.Add(Word);
until Length(Text) = 0;

Итак, на данный момент имеем:

procedure TForm1.Button1Click(Sender: TObject);
const DelSym = ' .,!?';
var Text,Word: string; i: integer;
begin
  Text:=Memo1.Lines.Text;
  for i := 1 to Length(Text) do
    if Pos(Text[i],DelSym) > 0 then
      Text[i]:=',';
 
  if Text[1] = ',' then
    Delete(Text,1,1);
  while Pos(',,',Text) > 0 do
    Delete(Text,Pos(',,',Text),1);
 
  repeat
    Word:=Copy(Text,1,Pos(',',Text)-1);
    Delete(Text,1,Length(Word)+1);
    ListBox1.Items.Add(Word);
  until Length(Text) = 0;
end;

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

Количество слов в тексте определить очень просто - не нужно заново ничего писать. Т.к. слова у нас занесены в ListBox, достаточно просто узнать, сколько там строк - ListBox.Items.Count.

Label1.Caption:='Количество слов в тексте: '+IntToStr(ListBox1.Items.Count);

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

var LongestWord: string;
{...}
  LongestWord:=ListBox1.Items[0];
  for i := 1 to ListBox1.Items.Count-1 do
    if Length(ListBox1.Items[i]) > Length(LongestWord) then
      LongestWord:=ListBox1.Items[i];
 
  Label2.Caption:='Самое длинное слово: '+LongestWord+' ('+IntToStr(Length(LongestWord))+' букв)';

Почему цикл до ListBox.Items.Count-1, а не просто до Count, разберитесь самостоятельно :-)

Вот теперь всё готово!

procedure TForm1.Button1Click(Sender: TObject);
const DelSym = ' .,!?';
var Text,Word,LongestWord: string; i: integer;
begin
  Text:=Memo1.Lines.Text;
  for i := 1 to Length(Text) do
    if Pos(Text[i],DelSym) > 0 then
      Text[i]:=',';
 
  if Text[1] = ',' then
    Delete(Text,1,1);
  while Pos(',,',Text) > 0 do
    Delete(Text,Pos(',,',Text),1);
 
  Text:=AnsiReplaceText(Text,Chr(13),'');
  Text:=AnsiReplaceText(Text,Chr(10),'');
 
  repeat
    Word:=Copy(Text,1,Pos(',',Text)-1);
    Delete(Text,1,Length(Word)+1);
    ListBox1.Items.Add(Word);
  until Length(Text) = 0;
 
  Label1.Caption:='Количество слов в тексте: '+IntToStr(ListBox1.Items.Count);
 
  LongestWord:=ListBox1.Items[0];
  for i := 1 to ListBox1.Items.Count-1 do
    if Length(ListBox1.Items[i]) > Length(LongestWord) then
      LongestWord:=ListBox1.Items[i];
 
  Label2.Caption:='Самое длинное слово: '+LongestWord+' ('+IntToStr(Length(LongestWord))+' букв)';
end;

Работа с символами

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

Помните "Таблицу символов"? Давайте сделаем её сами!

Вывод осуществим в TStringGrid. Этот компонент представляет собой таблицу, где в каждой ячейке записано текстовое значение. Компонент расположен на вкладке Additional (по умолчанию следует прямо за Standard). Перво-наперво настроим нашу табличку. Нам нужны всего две колонки: в одной будем отображать код символа, а в другой - сам символ. Количество колонок задаётся в свойстве с логичным названием ColCount. Устанавливаем его равным 2. По умолчанию у StringGrid задан один фиксированный столбец и одна фиксированная строка (они отображаются серым цветом). Столбец нам не нужен, а вот строка очень кстати, поэтому ставим FixedCols = 0, а FixedRows оставляем = 1.

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

Количество символов в кодовой таблице 256, плюс заголовок - итого 257. Зададим число строк программно (хотя можно задать и в Инспекторе Объекта):

procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGrid1.RowCount:=257;
end;

Вывод делается крайне просто - с помощью цикла. Просто проходим числа от 0 до 255 и выводим соответствующий символ. Также выводим надписи в заголовок. Доступ к ячейкам StringGrid осуществляется с помощью свойства Cells: Cells[номер_столбца,номер_строки]. В квадратных скобках указываются номера столбца и строки (начинаются с нуля). Значения текстовые.

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  StringGrid1.RowCount:=257;
  StringGrid1.Cells[0,0]:='Код';
  StringGrid1.Cells[1,0]:='Символ';
  for i := 0 to 255 do
  begin
    StringGrid1.Cells[0,i+1]:=IntToStr(i);
    StringGrid1.Cells[1,i+1]:=Chr(i);
  end;
end;

Запускаем, смотрим.

Специальные символы

Если вы внимательно посмотрите на нашу таблицу, то увидите, что многие символы отображаются в виде квадратиков. Нет, это не значки. Так отображаются символы, не имеющие визуального отображения. Т.е. символ, например, с кодом 13 существует, но он невидим. Эти символы используются в дополнительных целях. К примеру, символ #0 (т.е. символ с кодом 0) часто применяется для указания отсутствия символа. Существуют также строки, называемые null-terminated - это строки, заканчивающиеся символом #0. Такие строки используются в языке Си.
По кодам можно опознавать нажатия клавиш. К примеру, клавиша Enter имеет код 13, Escape - 27, пробел - 32, Tab - 9 и т.д.
Давайте добавим в нашу программу возможность узнать код любой клавиши. Для этого обработаем событие формы OnKeyPress(). Чтобы этот механизм работал, необходимо установить у формы KeyPreview = True.

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  ShowMessage('Код нажатой клавиши: '+IntToStr(Ord(Key)));
end;

Здесь мы выводим окошко с текстом. У события есть переменная Key, в которой хранится символ, соответствующий нажатой клавише. С помощью функции Ord() узнаём код этого символа, а затем функцией IntToStr() преобразуем это число в строку.

Пример "посерьёзнее" - продолжение

Вернёмся к нашему примеру. Пришло время выяснить, откуда в ListBox берутся пустые строки. Дело в том, что они не совсем пустые. Да, визуально они пусты, но на самом деле в каждой из них по 2 специальных символа. Это символы с кодами 13 и 10 (т.е. строка #13#10). В Windows такая последовательность этих двух невизуальных символов означает конец текущей строки и начало новой строки. Т.е. в любом файле и вообще где угодно переносы строк - это два символа. А весь текст, соответственно, остаётся непрерывной последовательностью символов. Эти символы можно (и даже нужно) использовать в случаях, когда требуется вставить перенос строки. Подробнее об этом можно прочитать в статье Что такое #13#10?. Знаний, полученных во всех предыдущих уроках, и в этом в том числе, вполне достаточно для понимания этой статьи - она совсем небольшая.

Доведём нашу программу по поиску слов до логического конца. Итак, чтобы избавиться от пустых строк, нам нужно удалить из текста символы #13 и #10. Сделать это можно с помощью цикла, по аналогии с тем, как мы делали замену двух запятых на одну:

while Pos(Chr(13),Text) > 0 do
  Delete(Text,Pos(Chr(13),Text),1);
 
while Pos(Chr(10),Text) > 0 do
  Delete(Text,Pos(Chr(10),Text),1);

Ну вот - теперь программа полностью работоспособна!

Дополнительные функции для работы со строками - модуль StrUtils

Дополнительный модуль StrUtils.pas содержит дополнительные функции для работы со строками. Среди этих функций множество полезных. Более подробно некоторые из функций рассмотрены в статье Работа со строковыми типами данных. А вот краткое описание часто используемых функций:

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

AnsiReplaceStr, AnsiReplaceText (строка, текст_1, текст_2) - функции выполняют замену в строке строка строки текст_1 на текст_2. Функции отличаются только тем, что первая ведёт замену с учётом регистра символов, а вторая - без него.
В нашей программе можно использовать эти функции для вырезания из строки символов #13 и #10 - для этого в качестве текста для замены следует указать пустую строку. Вот решение в одну строку кода:

Text:=AnsiReplaceText(AnsiReplaceText(Text,Chr(13),''),Chr(10),'');

DupeString(строка, число_повторений) - формирует строку, состоящую из строки строка путём повторения её заданное количество раз.

ReverseString(строка) - инвертирует строку ("123" -> "321").

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

UpperCase(строка) - преобразует строку в верхний регистр; LowerCase(строка) - преобразует строку в нижний регистр.

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

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

Скриншоты программ, описанных в статье

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

Заключение

Длинный получился урок... И как раз афоризм оказался в тему. Что удивительно, афоризм был подобран мной в самом начале, а сам урок написан позже :-)

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


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

Статьи

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

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

Создание интерфейса с использованием PNG-графики

Автор: LanKasper

Нам понадобятся: Photoshop (или подобные редакторы), Delphi.
Кроме того: некоторые навыки работы в графических программах.
Также, для правильной работы приложения, необходим плагин «Прямые руки»,
который Вы можете скачать с этого сайта в виде исходников :-)

На рынке программного обеспечения все больше и больше стало появляться программ с использованием своего стильного интерфейса. WinAMP, Windows Media Player, Nero Smart Start и многие другие. Отличительной особенностью перечисленных мной программ является их способность изменять цвет интерфейса, именно цвет, а не само оформление.

Совсем недавно передо мной встала задача создать в Delphi 7 интерфейс программы в стиле Windows Media Player (WMP), предоставив пользователю выбирать цвет панелей (совсем как в WMP). Проведя несколько часов в Интернете, я нашел лишь готовые скины и компоненты для их использования в приложениях, написанных в Delphi. Использование смены цветовой палитры всех изображений в программе происходило медленно и не очень подходило под мои нужды. Таким образом, я решил подумать своими мозгами :-)

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

Теперь о том, как это сделать самому.

Photoshop

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

Добавление поддержки PNG в Delphi

Для того, чтобы научить программы понимать png-изображения, заходим на сайт http://pngdelphi.sourceforge.net/ и загружаем архив. Достаточно подключить модуль из архива к проекту и Delphi начнёт понимать формат png!

Delphi

Создайте новый проект, поместите на форму компоненты: TColorBox и TPanel, на TPanel установите TShape (он будет являться фоном нашего png-изображения) установите свойство TShape Align равное alClient.

Дальше на ту же панель помещаем TImage, также ставим ему свойство Align равное alClient.

Затем загружаем в TImage наше png-изображение, и, если вы все правильно сделали в фотошопе, то после загрузки изображения Вы ничего не должны увидеть – только белый фон (белый градиент на белом TShape – теперь вам понятно, почему нельзя сделать оформление WMP полностью белым :-) ). Теперь напишем процедуру на изменение TColorBox - OnChange. Совсем просто (в нашем примере):

procedure TForm1.ColorBox1Change(Sender: TObject);
begin
   Shape1.Brush.Color:=ColorBox1.Selected;
end;

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

Данная статья дает пример работы png в приложениях. Вы можете создавать интерфейс целиком на png-изображениях (например, Style XP - его главное окно). Если немного подумать, то можно обеспечить плавное изменение цвета с использованием TTrackBar или подобных регуляторов также как это реализовано в Nero и WMP.

Пример png-изображения и исходники программы, описанной в статье »

Примеры интерфейсов с изменяемыми цветами:

Основное окно Windows Media Player (в синем оттенке) ...
... и это же окно через пару секунд ...
Основное окно Windows Media Player (в синем оттенке) ...
... и это же окно через пару секунд ...
Окно Nero Smart Start ...
И уже в других цветах ...
Окно Nero Smart Start ...
И уже в других цветах ...
Окно проигрывателя Winamp (цветовая схема Blood)
А это цветовая схема Night Vision
Окно проигрывателя Winamp (цветовая схема Blood)
А это цветовая схема Night Vision

А вот эти самые диалоги и элементы для выбора цвета:

Выбор цвета в Windows Media Player
Выбор цвета в Nero Smart Start
Выбор цветовой схемы в Winamp

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

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

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

Название
Описание
Раздел
Объём
Ссылки
AsyncCalls
C помощью AsyncCalls вы можете одновременно запустить на выполнение несколько функций и синхронизировать их из любого места в теле этих функций. Это позволяет запустить какой-либо долговременный процесс, результат которого требуется передать в другую функцию (в другой поток). Пока одна функция работает, другая может выполнять совершенно другие задачи.
22 Кб
Transparent & PNG Support Image Button
Кнопка с поддержкой альфа-канала и изображений PNG. Кнопка поддерживает три состояния.
273 Кб
Press Program
Программа предназначена для запуска программ с помощью клавиш. Список запускаемых программ поддерживает: автоматическую нумерацию и перемещение/копирование элементов списка, показ статуса (запущена или остановлена) и клавиш быстрого запуска программ. При запуске указанной программы есть возможность устанавливать вид окна и приоритет. Настройки программы позволяют устанавливать приоритет самой программы и её язык (по умолчанию программа переведена на русский язык, но есть возможность перевода на любой другой язык). Находится в трее, занимает мало места в оперативной памяти, не нагружает систему, поддерживает Drag&Drop.
334 Кб
TRealList
Класс TStringList в Delphi обеспечивает удобную работу со списком строк. TRealList предоставляет аналогичный функционал для работы со списками вещественных (real) чисел. Методы и свойства позволяют добавлять, удалять, вставлять и искать значения в списке. Свойство Granularity позволяет контролировать работу методов Add, Insert и Find. Содержимое списка может быть легко преобразовано в поток данных (TStream).
260 Кб
Improved Random Number Generator
Случайные числа, генерируемые в Delphi "родной" функцией Random далеки от идеала. По умолчанию при каждом запуске программы последовательность случайных чисел будет одинаковой. Улучшения достигаются добавлением системного таймера к процессу генерации случайных чисел – вызовом процедуры Randomize. Тем не менее, это не приводит к улучшению того простого алгоритма, который используется в генераторе случайных чисел. Алгоритмы большей сложности дают лучшие результаты. Конечно, реальной необходимости в этом нет. Windows предоставляет генератор случайных чисел, вызываемый функцией CoCreateGUID. Данный пример показывает, как его можно использовать при минимуме кодинга для получения действительно качественного генератора случайных чисел.
238 Кб
Professional Screen Camera Delphi Unit v.3.0
Модуль для Delphi для записи происходящего на экране в видео-файл (avi) с кодированием видео кодеками, установленными в системе.
310 Кб
Файлы к статье "Создание интерфейса с использованием PNG-графики"
369 Кб
 
Всего новых файлов: 7  
1.80 Мб
 
 

Юмор

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

Заповеди программиста

1) Чти операционную систему свою и не хай ее разработчиков, ибо им и без тебя икается. А то и сам таким станешь.

2) Если у тебя хакер украл файл, пошли ему еще два по e-mail. В твоем каталоге сроду ничего путного не водилось, а мелкий спам душу согреет.

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

4) Hе укради программы чужой. Да и зачем тебе чужие баги, если ты от своих не знаешь как избавиться?

5) Если жена конфликтует с компьютером, брось жену. Ибо компьютер кормит тебя, удовлетворяет и развлекает лучше. А жену можно подобрать новую, побродив по сайтам знакомств.

6) Возлюби ближнего своего, но через интернет. Ибо СПИДом от этого еще никто не заражался.

7) Лучше компьютера может быть только пиво, но одно другому не мешает.

:))

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




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


В избранное