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

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

  Все выпуски  

Программирование на DELPHI в вопросах и ответах #11


Информационный Канал Subscribe.Ru

Программирование на Delphi в вопросах и ответах.


Добрый день, уважаемые читатели! Перед вами выпуск №11 от 25.12.04.

Итак, сегодня мы подводим результаты опроса "Есть ли у вас собственный сайт?". Проголосовавших опять не очень много, хотя количество подписавшихся на рассылку 1400+. Результаты:

Есть ли у вас собственный сайт?
Да, есть: 16 (34%)
Нет: 15 (32%)
Нет, но хотелось бы его открыть: 16 (34%)

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

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

Нужно ли публиковать в рассылке имена лидеров по количеству набираемых баллов?
Да, нужно.
Нет, не нужно.

Предлагается создание нового раздела "Новости из мира Delphi". Публиковать в этом разделе хотелось бы ссылки на различные компоненты, плагины и вообще всего для Delphi. Пожалуйста, выскажете своё мнение по данному поводу и предлагайте свои идеи - может быть стоит открыть ещё какой интересный раздел?

ВНИМАНИЕ. Все новые вопросы, ответы и статьи ещё не опубликованы на сайте в момент выпуска данной рассылки. Они появятся там в ближайшие дни.

Правила нашей рассылки:
1. Не присылайте ответов на вопросы вроде "да я не знаю" или "да/нет". Такие ответы не публикуются.
2. Вопросы, не касающиеся Delphi, не принимаются (для этого существуют другие рассылки).
3. Запрещено присылать вложенные файлы, размером более 100 Кб, без предварительной связи с администратором.
4. Письма с "неправильной" темой не публикуются!



Статья по Delphi.

Написание инсталлятора на Delphi (Часть 4).

Копирование - 1

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

Почему?

Потому что операция копирования файлов должна быть идеальной.

Начнём с самого просто случая — копирования одного файла. Для того, чтобы скопировать один файл, вы можете вызвать функцию Windows, которая называется CopyFile:

function CopyFile(lpExistingFileName, lpNewFileName: PChar; bFailIfExists: BOOL): BOOL; stdcall;

Как видим, функции необходимо передать имена двух файлов: исходного и целевого. Третий параметр отвечает за то, как функция будет поступать, если целевой файл уже существует. Значение True говорит о том, что функция не будет копировать файл, значение False — о том, что целевой файл будет перезаписан.

Функция возвращает True, если операция копирования была успешно выполнена. Значение False подсказывает нам, что необходимо вызвать функцию GetLastError для того, чтобы узнать код произошедшей ошибки.

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

if CopyFile(PChar(SourcePath), PChar(TargetPath), False) then
// Выполнилась успешно.
else
// Ошибка. Код ошибки можно получить, вызвав GetLastError.

У этой функции один недостаток, но он способен перекрыть все её достоинства. Мы не имеем доступа к процессу копирования. Это означает, что мы не можем показывать индикатор процесса копирования и не можем прервать функцию CopyFile, если пользователь нажал кнопку "Отмена" или клавишу Escape.

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

В Windows NT 4.0 появилась новая функция — CopyFileEx, которая позволяет снять все появившиеся проблемы, но добавляет ещё одну — она не работает в предыдущих версиях Windows :)

В Delphi для копирования файлов, мы можем воспользоваться объектами класса TFileStream. Например, так:

procedure CopyFile(Source, Target: String);
var
SourceStream: TFileStream;
TargetStream: TFileStream;
begin
SourceStream := TFileStream(Source, fmOpenRead);
try
TargetStream := TFileStream(Target, fmCreate);
try
TargetStream.CopyFrom(SourceStream, 0);
FileSetDate(TargetStream.Handle, FileGetDate(SourceStream.Handle));
finally
TargetStream.Free;
end;
finally
SouceStream.Free;
end;
FileSetAttr(Target, FileGetAttr(Source));
end;

Обработку ошибок, как говорится в таких случаях, я оставляю читателю в качестве упражнения... :)

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

. . .
const
BlockSize = 65536;
. . .
var
ElapsedSize: Integer;
CopySize: Integer;
. . .
ElapsedSize := SourceStream.Size - SourceStream.Position;
while ElapsedSize > 0 do
begin
if ElapsedSize < BlockSize then
CopySize := ElapsedSize
else
CopySize := BlockSize;
TargetSource.CopyFrom(SourceSize, CopySize);
ElapsedSize := SourceStream.Size - SourceStream.Position;
// Здесь какие-то действия, например, модификация индикатора процесса
end;
. . .

Замечательные функции FileGetDate, FileSetDate, FileGetAttr, FileSetAttr выполняют очень важную работу, про которую не надо забывать: копируют дату создания файла и его атрибуты. Сейчас мы не будем углубляться в особенности файловой системы NTFS, в которой есть дата последней модификации файла и расширенные атрибуты, поскольку приведённого кода нам вполне для наших целей хватит.
Примечание:
Корректное копирование предполагает, что у целевого файла обязательно устанавливается флаг Archive. Я не буду углуляться в то, зачем это делается, тем более, что в нашем случае этого делать не обязательно.

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

Отображение округленного окошка подсказок для значка приложения в System Tray

В Windows 2000 и выше, формат структуры NotifyIconData, которая используется для работы с иконками в Трее (которая, кстати, называется "The Taskbar Notification Area" :) значительно отличается от предыдущий версий Windows. Однако, эти изменения НЕ отражены в юните ShellAPI.pas в Delphi 5.

Итак, нам понадобится преобразованный SHELLAPI.H, в котором присутствуют все необходимые объявления:

uses Windows;

type
NotifyIconData_50 = packed record // определённая в shellapi.h
cbSize: DWORD;
Wnd: HWND;
uID: UINT;
uFlags: UINT;
uCallbackMessage: UINT;
hIcon: HICON;
szTip: array[0..MAXCHAR] of AnsiChar;
dwState: DWORD;
dwStateMask: DWORD;
szInfo: array[0..MAXBYTE] of AnsiChar;
uTimeout: UINT; // union with uVersion: UINT;
szInfoTitle: array[0..63] of AnsiChar;
dwInfoFlags: DWORD;
end{record};

const
NIF_INFO = $00000010;

NIIF_NONE = $00000000;
NIIF_INFO = $00000001;
NIIF_WARNING = $00000002;
NIIF_ERROR = $00000003;

А это набор вспомогательных типов:

type
TBalloonTimeout = 10..30{seconds};
TBalloonIconType = (bitNone, // нет иконки
bitInfo, // информационная иконка (синяя)
bitWarning, // иконка восклицания (жёлтая)
bitError); // иконка ошибки (краснаа)

Теперь мы готовы приступить к созданию округлённых подсказок!

Для этого воспользуемся следующей функцией:

uses SysUtils, Windows, ShellAPI;

function BalloonTrayIcon(const Window: HWND; const IconID: Byte; const Timeout: TBalloonTimeout; const BalloonText, BalloonTitle: String; const BalloonIconType: TBalloonIconType): Boolean;
const
aBalloonIconTypes : array[TBalloonIconType] of Byte = (NIIF_NONE, NIIF_INFO, NIIF_WARNING, NIIF_ERROR);
var
NID_50 : NotifyIconData_50;
begin
FillChar(NID_50, SizeOf(NotifyIconData_50), 0);
with NID_50 do
begin
cbSize := SizeOf(NotifyIconData_50);
Wnd := Window;
uID := IconID;
uFlags := NIF_INFO;
StrPCopy(szInfo, BalloonText);
uTimeout := Timeout * 1000;
StrPCopy(szInfoTitle, BalloonTitle);
dwInfoFlags := aBalloonIconTypes[BalloonIconType];
end{with};
Result := Shell_NotifyIcon(NIM_MODIFY, @NID_50);
end;

Вызывается она следующим образом:

BalloonTrayIcon(Form1.Handle, 1, 10, 'this is the balloon text', 'title', bitWarning);

Иконка, должна быть предварительно добавлена с тем же дескриптором окна и IconID (в данном примере Form1.Handle и 1).

Можете попробовать все три типа иконок внутри всплывающей подсказки.

Несколько заключительных замечаний:
1. Нет необходимости использовать большую структуру NotifyIconData_50 для добавления или удаления иконок, старая добрая структура NotifyIconData прекрасно подойдёт для этого.
2. Для callback сообщения можно использовать WM_APP + что-нибудь.
3. Используя различные IconID, легко можно добавить несколько различных иконок из одного родительского окна и работать с ними по их IconID.

[Статью прислал: Feniks, получив за это 10 баллов].


Присылайте свои статьи по адресу delphi-faq@list.ru с темой 'Clause' (без кавычек), и они будут опубликованы в ближайших выпусках рассылки. Большая просьба: статью оформляйте в -txt или -doc формате и используйте -zip или -rar сжатие (без самораспаковки).



Новые вопросы:

30. Пожалуйста помогите. Как можно редактировать реестр с командной строки (файлы *.bat) без участия пользователя? То есть незаметно. Заранее благодарен. [Ответить].

31. Как управлять Exclel'ем и Word'ом (97/2000/XP) из Дельфи7. Спасибо. [Ответить].

32. Помогите люди добрые с глупой проблемой! нигде в екзампелсах не мог найти как в статусбаре текущее время выводить, решил проблему в лоб: секундный таймер пишет строчку с строкой времени. Правильно это, или есть более элегантное решение? [Ответить].

33. Хаюшки! Есть ли в Delphi средства, позволяющие отслеживать поведение дисплея, т.к. частота обновления (Refresh rate), событие начала обновления экрана и т.п. Всё надо для написания качественной анимации (без дёрганья и мерцания). Заранее спасибо. [Ответить].

Вопросы, ждущие ответа:

24. Скажите, где можно найти компоненты типа DelphiX, но (и это важно!), работающие с последней версией DirectX. Заранее благодарен! [Ответить].

26. Добрый вечер всем. Пишу сейчас программу на стыке графики и баз данных. В последних почти не шарю совсем, поэтому спрошу :)
1. Есть БД DB2. И есть набор файлов (txt, xls) да и сама програма выдет много данных. Мне нужно всеми этими даными заполнить соответствующие поля в данной базе. Короче говоря нужно передать данные в базу. Вопрос, естественно, как это сделать? Один из предложенных вариантов - это настроить драйвер ODBC. Но говорят, что это довольно медленный вариант. Подскажите, пожалуйста, как это сделать. Может быть уже есть готовые компоненты для данных целей.
2. Второй вопрос проще. Как из дельфи (D7, XP) создать xls файл (проверить на существование) сохранить туда данные из массива и потом их считать. Все. Спасибо за внимание. [Ответить].

27. Пишу сейчас прогу "Домашний поисковик", типа Google Desktop Search, но с поддержкой туевой хучи типов файлов и не могу найти путного описания устройства HLP и CHM файлов. Можете ли поделиться? А может сами библиотеку напишете? К проге прицепляются плагины (ДЛЛ), которые возвращают ей словарь встреченных в файле осмысленных буквосочетаний, та их заносит в базу, ну и вторая функция - по запросу возвратить осмысленную цитату из файла (опять же типа поисковика в нете). Шаблон библиотеки могу кинуть, программой тож понятно, поделюсь, хотя она и так пишется Open Source - цепляй свои плагины и вперед... [Ответить].

28. Здравствуйте. Пишу тут игру на WinAPI. Мне нужно воспроизводить фоновую музыку и звуки (выстрел, столкновение?), использую функцию PlaySound(address, 0, SND_ASYNC or SND_MEMORY), но при воспроизведении звуков фоновая музыка останавливается и больше не воспроизводится. Подскажите, как нормально воспроизводить фоновую музыку!!! Заранее благодарен. [Ответить].

12. Привет. Может, кому-нибудь из читателей, удалось написать утилиту, показывающую все активные TCP/IP соединения (аналог Netstat) на Delphi без использования Fnugry Netstat Components. Поделитесь пожалуйста исходником, а то дядька Google мне отказался с этим помочь. [Ответить].

14. Скажите, как узнать занятость принтера и передать задачу на другой принтер сети! [Ответить].

15. Здраствуйте.Можете сказат как я могу выбрат компоненть из другого Application? Например в другом App. я использвал с одного Edit-a ( у него ест OnChange(), OnKeyPress() и.др ) или он может бьт не визуальным. И хочу что добавить код в новую Application( первому Form-у OnCreate ) чтобы он автоматически выбрал ту Component-у какую я дам в коде. Заранее блогодорен!!! [Ответить].

21. Задача состоит в следующем: необходимо непрерывно получать изображения со сканера (по крайней мере настолько, насколько это возможно, но без выгрузки основной программы). До сих пор, я работал под twain-библиотекой. Там все идет нормально, но на n-ном BITMAP'е у сканера происходит "крейз" и до перезагрузки WIDOWS, достучаться до него невозможно. Помогите, пожалуйста, решить эту проблему. P.S. Насколько я знаю, при работе со стандартными программами windows (Imaging & Kodak Image), а также при использовании ActiveX TImgScan (кроме того, он очень неудобен), возникают подобные же проблемы. [Ответить].



Ответы на вопросы:

22. (Вывод базы данных Access в программе). [Отвечает: Igor]: Вывести можно разными способами. Привожу пример с помощью компонентов ADO:
Поместите на форму объект ADOConnection, он получит имя ADOConnection1. Задайте ему свойство ConnectionString с помощью построителя выражений. Выберите Use Connection String, далее жмите Build: Поставщик данных будет Microsoft OLE DB Provider for ODBC Drivers, далее источник данных - База Данных MS Access, начальный каталог - полный путь к файлу .mdb, пользователь и пароль вводить не надо. После этого свойство LoginPrompt ставим False, а Connected в True. Далее помещаем на форму ADOTable, его свойство Connection устанавливаем, выбрав из списка ADOConnection1. Задаем TableName - имя таблицы и Active ставим в True. Потом помещаем на форму DataSource, его свойство DataSet ставим в ADOTable1. И самое последнее: цепляем к нашему DataSource DBGrid и DBNavigator для вывода таблицы и перемещения по записям. Если вы хотите просто вывести, то запретите редактирование, установив в ADOTable1 свойство ReadOnly в True.

24. (Компоненты DelphiX и для работы с DirectX). [Отвечает: Садовников Владимир]: Лучше не используй такие компоненты!!! При использовании таких компонент падает скорость воспроизведения и прорисовки. Используй лучше то, что напишешь своими руками.
//От ведущего: ответ на данный вопрос всё ещё ожидается.

25. (Сохранение/загрузка картинки из DLL. Работа с INI-файлами). [Отвечает: Садовников Владимир]: Об INI-файле говорилось в одной из рассылок: посмотри в архиве (класс TINIFile). Теперь о картинке. Создаёшь файл ресурсов, запихиваешь в него картинку, предварительно обозвав её как-нибудь. Потом посмотри во встроенном хелпе Delphi справку по функциям LoadResource и FindResource/FindResourceEx. Остаётся прилинковать к твоей ДЛЛ этот файл ресурсов и скомпилить её. Потом загружаешь ДЛЛ в память функциями LoadRibrary/FreeLibrary, и применяешь на полученном хэндле вышеуказанные функции. Всё, вроде.
//От ведущего: в рассылке действительно была статья по работе с реестром и с INI-файлами. Прочитать её можно здесь:
http://www.delphi-faq.fatal.ru/clauses/10/html/clause5.htm

29. (Индикатор загрузки процессора на кнопке "Пуск"). [Отвечает: Садовников Владимир]: Ищешь окно 'Shell_TrayWnd' функцией FindWindow, в нём ищешь окно 'Button' функцией FindWindowEx. Дальше можешь получить дескриптор экрана этого окна функцией GetDC. После этого на этом DC можешь рисовать, сколько влезет. Можешь слать также сообщения, чтобы нарисовать на кнопке картинку: SendMessage(ButtonWindow,BM_SETIMAGE,0,PictureHandle). Где ButonWindow - хэндл найденной кнопки, а PictureHandle - хэндл твоей картинки (которую ты можешь переодически перерисовывать).


Вы также можете ответить на предыдущие вопросы. Поскольку на них уже ответили как минимум раз, они больше не публикуются в рассылке. Но если вы можете что-то добавить к ответам других, пожалуйста, отвечайте - ответы будут опубликованы. Найти предыдущие вопросы вы можете на нашем сайте: http://www.delphi-faq.fatal.ru/.



Друзья:

Здесь представлены ссылки на дружественные сайты нашего портала. Если вы тоже хотите стать нашим другом, разместите баннер на главной странице своего сайта. Подробнее о том, как стать другом, можно прочитать здесь: http://www.delphi-faq.fatal.ru/banner.htm.

http://www.x-program.narod.ru/ - На нашем сайте Вы найдёте некоторые наши программы. Также мы занимаемся создание ПО для любой версии ОС Windows под заказ.
http://www.basic.webhost.ru/ - Программирование на языках Basic и Visual Basic.
http://www.sashook.nm.ru/ - Игры, флешки, обои, компьютерные приколы.
http://infomania2004.webhost.ru/ - Этот сайт создан для того, чтобы вы могли получить интересующую вас информацию с минимальными затратами сил и времени. Если вы не нашли здесь нужной информации, вы можете оставить заявку на ее поиск. Как только информация будет найдена, она появится на сайте, а вам сообщат об этом.



Юмор:

Спасибо товарищу Гейтсу за славную кнопку RESET.
[Прислал: Иванов Андрей].

- Как три программиста могут организовать бизнес?
- Один пишет виpyсы, а другой антивирусы.
- А третий?
- Операционные системы, под которыми это все работает.

Стоят муж и жена в компьютерном магазине. Жена, внимательно глядя на таблички:
- Мне сказали, что Word нужен, а тут все Pentium'ы и Pentium'ы!

Встречаются два интернетчика:
- Я вчера такую девушку видел! Познакомится не успел, где ее теперь искать? :(
- Ну, ты что? Ее в bookmarks'ы не добавил, что ли?!

Из телевизионной программы: Юмористический сериал 'Гейтс в окне', 95 серия.

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


Присылайте свои "компьютерные" анекдоты по этой ссылке: delphi-faq@list.ru и они обязательно будут опубликованы!


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


Сайт рассылки: http://www.delphi-faq.fatal.ru E-mail: Delphi-FAQ@list.ru


http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.delphifaq
Отписаться

В избранное