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

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

  Все выпуски  

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


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

Программирование на Delphi. Выпуск №16: 16.01.05.

Содержание выпуска:

Приветствую Вас, уважаемые читатели!

Я обязательно должен напомнить, что проходит конкурс, первые 10 победителей которого получат 25 баллов. Конкурс будет завершён 31 января. Осталось не так много времени. Спешите найти текст и расшифровать его! На текущий момент только 5 человек прислали правильный ответ! У вас большие шансы попасть в десятку победителей!

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

Количество подписчиков: 1558.

Ну а теперь главная новость сегодняшнего дня! На нашем сайта появился ФОРУМ! Для начала нужно протестировать его работу. Поэтому, уважаемые читатели, заходите и создавайте свои темы. Но только действительно те темы, которые вас интересуют и которые бы вы хотели обсудить. Если что-то не работает, пожалуйста, сразу дайте знать об этом.

Top-10 Readers:

Место
Имя
Кол-во баллов
Место
Имя
Кол-во баллов
1.
105 баллов
6.
35 баллов
2.
89 баллов
7.
25 баллов
3.
78 баллов
8.
25 баллов
4.
58 баллов
9.
20 баллов
5.
38 баллов
10.
18 баллов

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

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


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

49. Подскажите, как сделать, чтобы программа два раза не запускалась? Чтобы, если она уже запущена, активизировалось старое окно. Пробовала проверять перед запуском приложения, оно все равно успевает открыться. [Ответить].

50. Здравствуйте! В программе к каждому рисунку должен отображаться соответствующий текст. подскажите, пожалуйста, как лучше и проще это реализовать на Делфи? Учитывая, что рисунков будет несколько десятков и чтобы ее можно было без проблем установить на других компьютерах. Спасибо. [Ответить].

51. Привет всем и с прошедшими всех праздниками! У меня вот какой вопрос: можно ли в компоненте StringGrid менять в отдельных столбцах шрифт, и, если можно, то как это сделать? Я как не пробовал, у меня ничего не получилось - шрифт если и меняется, то меняется во всем StringGrid-е сразу. Заранее благодарен. [Ответить].

52. Как правильно работать из delphi-приложения с справкой в формате HTML? У меня установлен HTML Help Workshop и в документации есть заглавочный файл для C, но никак не могу вызвать функцию HtmlHelp. Подскажите, в какой библиотеке она находится. [Ответить].

Вопросы, требующие ответа.

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

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

37. Как отправить текст из переменной на сайт в интернете в текстовый или HTML-файл? [Ответить].

40. Как мне определить скорость инета? Почитал msdn, понял, что надо юзать IPHLPAPI.DLL, а вот как? [Ответить].


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

4. (Изменение разрешения экрана). [Отвечает: Iron Monk]: Всем привет!

Иногда требуется, чтобы программа работала при чётко заданных параметрах монитора: разрешение, глубина цвета, частота обновления… Определить текущее разрешение просто, достаточно обратиться к объекту TScreen и посмотреть значения его полей Width и Height. А вот чтобы установить свои значения требуется обратиться к функции Api: ChangeDisplaySettings. Если мы хотим вернуть текущие настройки по завершении работы программы, то перед вызовом изменений надо запомнить эти настройки например таким образом:

uses ShellApi;
var
DefWidth, DefHeight, BPP: word;
//.

procedure SaveSettings;
var
DC: hDC;
begin
DefWidth := Screen.Width;
DefHeight := Screen.Height;
DC := CreateDC('DISPLAY', nil, nil, nil);
BPP := GetDeviceCaps(DC, BITSPIXEL);
end;

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

procedure SetScreen(BPP:byte;width,height,FR:integer);
var
D: TDevMode;
h: HWND;
begin
h:=0;
D.dmDeviceName:='DISPLAY';
D.dmBitsPerPel:=BPP;
D.dmDisplayFrequency:=FR;
D.dmPelsWidth:=Width;
D.dmPelsHeight:=Height;
D.dmFields:=DM_BITSPERPEL+DM_PELSWIDTH+DM_PELSHEIGHT+DM_DISPLAYFREQUENCY;
D.dmSize:=SizeOf(D);
if ChangeDisplaySettings(D,CDS_TEST)=DISP_CHANGE_SUCCESSFUL then
ChangeDisplaySettings(D,CDS_UPDATEREGISTRY)
else
MessageBox(h,'This mode is not supported by your video.',
'Failed to change mode', MB_ICONWarning);
end;

Вызывается так: SetScreen(глубина цвета, разрешение по горизонтали, разрешение по вертикали, частота в герцах); Например:

SetScreen(16,800,600,80); {16 бит цвет, 800х600, 80Гц.}

При завершении программы для восстановления старых параметров вызываем эту процедуру с сохранёнными ранее значениями:

SetScreen(BPP,DefWidth,DefHeight,80);

Я не стал здесь беспокоиться о сохранении/возвращении частоты обновления, а сразу установил 80Гц, но если кто желает, может сохранить и этот параметр при запуске

DefFR:=GetDeviceCaps(DC, VREFRESH);

и восстановить при закрытии программы:

SetScreen(BPP,DefWidth,DefHeight,DefFR);

Взято с www.delphiworld.narod.ru

17. (Копирование URL в TMemo). [Отвечает: Iron Monk]: Всем привет!
Как уже писАл ранее Ершов Денис - по двойному клику это делать не удобно: из пяти раз - два раза у меня запустился браузер.
Насчёт горячих клавиш - тоже не самая удачная мысль. В винде они есть: Ctrl + C - копирование в буфер обмена.
Но для этого текст ссылки необходимо выделить. Самое простое - через контекстное меню - во всех браузерах и почтовых клиентах есть пункт - копировать ярлык, вот им мы и займёмся:

uses Clipbrd;
procedure PasteInMemo;
var
C:TClipboard;
begin
C:=TClipboard.Create;
try
if Clipboard.HasFormat(CF_TEXT) then // проверим Clipboard на наличие текста
if Clipboard.AsText <> Form1.Edit1.Text then // сравним текст в борде и Edit1, если разный, то
if pos('http://', lowercase(ClipBoard.AsText)) <> 0 then // поищем в тексте http:// , чтобы не копировать что зря.
begin // если всё нормально, то
Form1.Edit1.Text:=''; // очищаем Edit1
Form1.Edit1.PasteFromClipboard; // вставляем в Edit1 текст из борда
Form1.Memo1.Lines.Add(Form1.Edit1.Text); // и добавляем его в Memo1
end else
// а если ссылки нет, то можно сделать что нибудь ещё
finally
C.Free;
end;
end;
//с помощью таймера организуем автоматическую проверку содержимого Clipboard

procedure TForm1.Timer1Timer(Sender: TObject);
begin
PasteInMemo;
end;

19. (Прогресс закачки файлов из сети). [Отвечает: Iron Monk]: Программа для закачки файлов по протоколу http. При старте (если в буфере обмена есть ссылка), вставляет ссылку в поле Edit, запрашивает с сайта размер файла и выводит его размер в Label, в качестве ProgressBar используется TGauge. Сохраняет лог в папке Windows, поэтому, при первом запуске программы выдаст ошибку(т.к. файла там пока нет). [Исходники ЗДЕСЬ].

21. (Непреравное получение данных со сканера). [Отвечает: Четвертных В.В.]: Отвечу сам себе:
Во-первых, надо создать сканирующую программу (на любой TWAIN - основе: будь то непосредственное "общение" с twain_32.dll, применение TImgScan или любым другим способом ). Эта программа должна при закрытии создавать временный *.bmp файл.
Во-вторых, воспользоваться, в главной программе, одной из двух функций:
WinExec(IpCmdLine:PAnsichar,uCmdShow:Cardinal):Cardinal;
либо
CreateProcess():boolean; //Функция с неисчислимым количеством параметров, главными из которых являются: LPCTSTR: lpApplicationName, //Название вызываемой программы
LPTSTR: lpCommandLine, //Текст командной строки
LPSTARTUPINFO: lpStartupInfo, // handle для запуска
LPPROCESS_INFORMATION: lpProcessInformation // handle для управления процессом
Далее, необходимо дождаться выполнения и закрытия программы - исполнителя с помощью функции:

WaitForSingleObject(Prc.hProcess,INFINITE):byte ,которая вернет 0 (или константу WAIT_FAILED),
когда выполняемый процесс закончится.
Теперь - открываем сохраненнй временный файл, обрабатываем его и "заметаем следы".

Лично я реализовал это так:
Prct:='Scan.exe'; //Создание виртуального handl'а для программы Scan.exe...
St.cb:=SizeOf(St);
St.lpReserved:=Nil;
St.lpDesktop:=Nil;
St.lpTitle:=Prct;
St.dwFlags:=0;
St.wShowWindow:=SW_NORMAL;
St.cbReserved2:=0;
St.lpReserved2:=Nil;
St.hStdInput:=Integer(Nil);
St.hStdOutput:=Integer(Nil);
St.hStdError:=Integer(Nil);
CreateProcess(Nil,PAnsiChar(GetCurrentDir + '\Scan\Scan.exe'),Nil,Nil,False,NORMAL_PRIORITY_CLASS,Nil,PAnsiChar(GetCurrentDir),St,Prc);
If WaitForSingleObject(Prc.hProcess,INFINITE) = 0 then //.Запуск Scan.exe и ожидание его окончания...
begin
CloseHandle(Prc.hProcess);
CloseHandle(Prc.hThread);
If FileExists(GetCurrentDir+'\ScannedDiag.bmp') Then
begin
If bitmap = nil Then
bitmap:=TBitmap.Create;
Bitmap.LoadFromFile(GetCurrentDir+'\scanneddiag.bmp'); //Загрузка временного файла, созданного Scan.exe...
Image1.Canvas.StretchDraw(rect(0,0,Image1.Width,Image1.Height),Bitmap);
DeleteFile(GetCurrentDir+'\scanneddiag.bmp'); //Удаление временного файла...
end;
end;

По крайней мере около 80-ти сканирований подряд я выдержал (программа бы выдержала и больше, но не выдержал я).
Спасибо за внимание.

24. (Библиотеки DelphiX). [Отвечает: Dron]: На текущий момент, последняя версия DirectX - 9.0c. Найти графические библиотеки, которые будут с этой версией работать - практически невозможно. Так быстро они не адаптируются. Но вот с DirectX 8 - без проблем! Качай UnDelphiX (UnDelphiX - практически тоже самое, что и DelphiX, точно не помню, - но кажется это просто неофициальная версия; сам её использую - всё прекрасно работает). В ReadMe написано, что скачать можно здесь: http://turbo.gamedev.net/undelphix.asp. Также там есть адрес: http://www.ingjapan.ne.jp/hori/. Наверняка, найдёшь без проблем. Удачи! 

25. (Изображения JPG в DLL.). [Отвечает: Iron Monk]: Всем привет! Очень просто. Сначала, с помощью Restoratorа, создаём файл Jpeg.res и загружаем в него Jpg картинки в формате RCData. Создаём библиотеку dll - например J_PG.dll:

library J_PG;

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Dialogs, StdCtrls, ExtCtrls, JPEG;

{$R *.res}
{$R Jpeg.res}// подключаем наш файл с JPG ресурсами в формате RCData

procedure Picture(JPGName:string);
var
Image : TResourceStream;
Can:TCanvas;
Jpeg:TJPEGImage; //class(TGraphic)
begin
Jpeg:=TJPEGImage.Create;
Can:=TCanvas.Create;
Image := TResourceStream.Create(Hinstance,JPGName,RT_RCDATA);
Jpeg.LoadFromStream(Image);
Can.Handle := GetDC(GetWindow(GetDesktopWindow, GW_OWNER));
Can.Draw(0,0,Jpeg); //Рисуем JPG-картинку на рабочем столе (0,0 - координаты)
Image.Free;
Jpeg.Free;
end;
exports
Picture;//Экспортируемая процедура
end.

Библиотека J_PG.dll готова. Создаём новый проект: Кидаем на форму Button1:

uses JPEG;
procedure Picture( JPGName:string); external 'J_PG.dll';//Процедура из нашей dll
//------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
Picture('PICT');// 'PICT'- имя нашей картинки из файла Jpeg.res
end;
end.
Вот и всё.

27. (Создание файлов справки). [Отвечает: Iron Monk]: Есть описание по вопросу создания файлов справки в формате .hlp и .chm ( файл Help.chm 138 Kb). [Скачать]

30. (Редактирование реестра). [Отвечает: Iron Monk]: Всем привет! Посмотрел на сайте ответы на этот вопрос и не увидел самый простой: @ regedit -s file.reg - выполнение .reg файла без запроса (file.reg - ваш .reg файл).

44. (Ссылки на ресурсы по Delphi). [Отвечает: Садовников Владимир]: http://www.delphi-jedi.org/ http://www.vr-online.ru/

[Отвечает: Feniks]: http://www.GoldFAQ.ru
http://www.delphi32.com
http://delphibase.endimus.com
http://delphiworld.narod.ru
http://procoder.ru
http://Delphid.dax.ru
http://club.shelek.com
http://www.BCBDEV.ru
http://codeproject.com
http://www.x-program.narod.ru
http://delphi.hostmos.ru
http://www.sources.ru/delphi
http://Sources.ru
http://www.delphi-faq.fatal.ru
http://www.delphikingdom.com
http://delphi.mtu-net.ru
http://SoftMaker.fatal.ru/sources/delphi
http://delphigfx.mastak.ru/
http://www.progz.ru
http://www.realcoding.net
http://www.delphimaster.ru
http://shelek.com/forum
http://www.xakep.ru
http://www.vcl.ru
http://www.sql.ru
http://www.delphi3000.com
http://www.torry.ru
http://www.torry.net
http://sourceforge.net
http://tdelphi.spb.ru
http://xatka.vov.ru/cgi-bin/read.pl?chapter=source&page=2&limit=4&file=5&found=44&next=0
http://faqs.org.ru
http://CodeGuru.com
http://CodeProject.com
http://delphi.vitpc.com
http://www.vkasoft.narod.ru
http://delphi.softclub.net
http://www.vtktools.ru
http://www.delphi-gems.com

И еще кучу можно найти хотя бы через Гугл.

[Отвечает: Dron]: http://www.torry.net/
http://www.delphiplus.org/
http://www.delphi-faq.fatal.ru/
http://www.delphimaster.ru/
http://www.delphi-jedi.org/
http://delphibase.endimus.com/
http://www.delphikingdom.com/
http://codeproject.com/
http://www.sources.ru/delphi
http://www.realcoding.net/
http://www.codersclub.net/

Да их очень много! Зайди в любой поисковик, да набери "Компоненты для Delphi"...

[Отвечает: Iron Monk]: Всем привет!
ENIN INC WIN32API Library v1.0 (build 11.05.04)
-----------------------------------------------------------------
Online: http://lenininc.narod.ru
E-Mail: lenin@zeos.net
------------------------------------------------------------------
Online: http://www.grundic.narod.ru/
------------------------------------------------------------------
Component for Delphi 16/32

Copyright (c) 1998 by Aleksey Xacker
Idea stolen from Matthias Laschat
Home Page: http://www.angen.net/~xacker/
E-Mail: xacker@phreaker.net
-----------------------------------------------------------------
http://www3.brinkster.com/troels/delphi.asp
-----------------------------------------------------------------
Web: http://people.zeelandnet.nl/famboek/delphi/
Email: jwbsoftware@zeelandnet.nl
----------------------------------------------------------------
MiTeC System Information Component
================================
(aka MSystemInfo)
Revised: 02/14/2003
Copyright # 1997-2003 by Michal Mutl
Aubrechtove 3102, 106 00 Praha 10, Czech republic
<mitec@atlas.cz>
http://www.mitec.d2.cz/
---------------------------------------------------------------
И очень, очень много других,
главное не стесняться спросить у Яндекса...

[Отвечает: Геннадий Самолдин]: www.torry.net, www.delphimaster.ru.

[Отвечает: Андрей Акишин]: попробуй тут http://www.aboutdelphi.w6.ru/janer3.htm.

45. (Запуск и открытие файлов/приложений). [Отвечает: Den]: Это просто, функция Win API - WinExec, запускает исполняемый файл (в хелпе есть все необходимое). Там же описано как создать\запустить процесс (прога-невидимка, без окна) и куча чего еще интересного. Там же в Win API есть способ передавать параметры вызываемому приложению, например если прога при загрузке подключается к БД, и логин с паролем нужно передавать на автомате или скрыто от юзера...

[Отвечает: Садовников Владимир]: Посмотри функции ShellExecute и WinExec. Первая открывает всё, что угодно (вплоть до документов), вторая - запускает приложения. Посмотри во встроенном хелпе Delphi - там есть их описание.

[Отвечает: Dasha]: Это делается функцией ShellExecute, см. хелп Windows SDK. Например, так:
ShellExecute(0,'open', PChar(FileName), PChar(ExtractFileDir(FileName)), nil, SW_SHOWNORMAL);
где FileName соответственно имя файла. Подключить юнит Shellapi.

[Отвечает: Андрей Лучников]: Можно так (простенько и со вкусом):

uses ShellAPI;
...
var
s:string;
...

// Полный путь к запускаемой проге
s:='c:\work\project1.exe';
WinExec(PChar(s),SW_NORMAL);
{
последний параметр - в каком виде открывать
Все константы можно глянуть в хелпе к функции ShowWindow
}

P.S. Есть еще ShellExecute, так там больше параметров.

[Отвечает: Feniks]: Для программного запуска файлов следует использовать функции ShellExecute, ShellExecuteEx. Они прекрасно описаны в хелпе по Делфи. Но там указано, что лучше всего использовать функцию CreateProcess. Но ей очень много специфических параметров надо задавать. Есть еще WinExec для совместимости с 3.51. Так что выбирай сам.

[Отвечает: Dron]: Всё очень просто. ShellAPI - в uses. Дальше - вызываем функцию ShellExecute.
У неё довольно много параметров. Вот описание:
ShellExecute(
hwnd, // handle окна-предка
lpOperation, // выполняемая операция (open, print или explore).
lpFile, // Имя файла или команды (у нас будет команда)
lpParameters, // Параметры, с которыми запуститься файл (если он исполняемый)
lpDirectory, // Рабочий каталог (подобно аналогичному свойству у ярлыка)
nShowCmd // Как будет показано окно (SW_HIDE, SW_NORMAL, SW_MAXIMIZE и т.д.)
);
Данная функция выполнит исполняемый файл (если указан его путь), или откроет произвольный документ, а WinExec - умеет только выполнять программные файлы, а документы открывать - не умеет.
Пример запуска (как и требовалось):
ShellExecute(0,'open','C:\WINDOWS\calc.exe','','','SW_NORMAL);
Кстати, аналогичным образом можно и открывать интернет-страницы:
ShellExecute(0,'open','http://www.mysite.com','','',SW_NORMAL);
ShellExecute(0,'open','mailto:e-mail','','',SW_NORMAL);

[Отвечает: Iron Monk]: Запустить .exe можно так:
------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
S:string; // полный путь к программе (C:\ и т.д.)
begin
S:='notepad'; // запустится Блокнот
WinExec( PChar(Format( '%s %1', [S] )), SW_SHOWNORMAL );
end;
end.
------------------------------------------------------------------------------
Запустить другие файлы:
------------------------------------------------------------------------------
procedure TForm1.Button2Click(Sender: TObject);
var
S:string;// команда
F:string; // полный путь к файлу
begin
S:='C:\Program Files\Windows Media Player\wmplayer.exe %s'; // wmplayer.exe запустит
F:='C:\WINDOWS\Media\town.mid'; // файл town.mid
WinExec( PChar(Format(S, [F] )), SW_SHOWNORMAL );
end;
end.
------------------------------------------------------------------------------
Используя ShellApi:
-----------------------------------
uses ShellApi;

procedure TForm1.Button3Click(Sender: TObject);
begin
ShellExecute(Handle,'open','mailto:Delphi-FAQ@list.ru',nil,nil,SW_SHOW); // написАть в рассылку
end;
//-------------------- // или
procedure TForm1.Button4Click(Sender: TObject);
begin
begin
ShellExecute(Handle,'http://www.delphi-faq.fatal.ru/',nil,nil,SW_SHOW); // попасть на сайт рассылки
end;
end;
end.

[Отвечает: Геннадий Самолдин]: ShellExecute(<файл><файл>);

[Отвечает: Иванов Сергей]: WinExec('c:\proga.exe'),0);

[Отвечает: Lyubimov Pavel]: Запуск внешней программы и ожидание ее завершения:
procedure TForm1.Button1Click(Sender: TObject);
var
si : Tstartupinfo;
p : Tprocessinformation;
begin
FillChar( Si, SizeOf( Si ) , 0 );
with Si do begin
cb := SizeOf( Si);
dwFlags := startf_UseShowWindow;
wShowWindow := 4;
end;
Application.Minimize;
Createprocess(nil,'notepad.exe',nil,nil,false,
Create_default_error_mode,nil,nil,si,p);
Waitforsingleobject(p.hProcess,infinite);
Application.Restore;
end;

ShellExecute() - описание есть в справке!!! по Дельфи (RTFM).

46. (Периодическое выполнение функции, пока из изменится возвращаемое значение). [Отвечает: Садовников Владимир]: Создай нить, в которой в цикле будешь проверять твою функцию. Никакой таймер не понадобится. Тогда код будет выглядеть так:

procedure TMyThread.Execute;
begin
while (InetIsOffline(0)) do
begin
<повторяется вызов>
Sleep(<Промежуток времени в миллисекундах между вызовами>);
end;
<Твой дальнейший код>
end;

[Отвечает: Iron Monk]: У меня функция:
function InetIsOffline(Flag: Integer): Boolean; stdcall; external 'URL.DLL';
не работает (Win XP). Если у кого она работает, то по смыслу:

function InetIsOffline(Flag: Integer): Boolean; stdcall; external 'URL.DLL';

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if InetIsOffline(0) then
{повторяется вызов}
else
begin
Timer1.Enabled:=false;// выключаем таймер
// или Timer1.Interval:=0;
{идёт дальнейшее выполнение кода программы}
end;
end;
end.
------------------
Лично я использую функцию:
function InternetGetConnectedState(lpdwFlags:LPDWORD; dwReserved: DWORD): BOOLEAN;
stdcall; external 'wininet.dll';

47. (Значки веток в TreeView). [Отвечает: Садовников Владимир]: SelectedIndex - номер рисуемой иконки, когда твой элемент выделен. ImageIndex - номер рисуемой иконки, когда твой элемент не выделен. И ничего здесь нет связанного с раскрытием/закрытием. Чтобы поменять картинку при раскрытии/закрытии, воспользуйся этим:

procedure TForm1.TreeView1Expanded(Sender: TObject; Node: TTreeNode);
begin
Node.ImageIndex:=5; //меняем картинку
end;

procedure TForm1.TreeView1Collapsed(Sender: TObject; Node: TTreeNode);
begin
Node.ImageIndex:=3; //меняем картинку
end;

48. (Преобразование BMP в EMF). [Отвечает: Iron Monk]: Всем привет!

implementation

{$R *.dfm}

// процедура конвертирует Canvas в .bmp и далее, в .emf;
// более простого способа я не нашёл...

procedure Canv_Bmp_Emf(const FileName: TFileName);
var
MFile: TMetafile;
MCanv: TMetafileCanvas;
Bitmap: TBitmap;
Rec: TRect;
begin
MFile := TMetaFile.Create;
try
Bitmap := TBitmap.Create;
try
// задаём размеры
Bitmap.Height:=Form1.ClientHeight;
Bitmap.Width:=Form1.ClientWidth;
MFile.Height := Bitmap.Height;
MFile.Width := Bitmap.Width;
//задаём координаты
Rec := Rect(0, 0, Bitmap.Width, Bitmap.Height);
//и записываем
Bitmap.Canvas.CopyRect(Rec, Form1.Canvas, Rec); // вместо Form1.Canvas, любой TCanvas.
MCanv := TMetafileCanvas.Create(MFile, 0);
try
MCanv.Draw(0, 0, Bitmap);
finally
MCanv.Free;
end;
finally
Bitmap.Free;
end;
MFile.SaveToFile(FileName);
finally
MFile.Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Canv_Bmp_Emf('d:\MyMetaFile.emf'); // сохраняем метафайл
end;
end.


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


Статья по Delphi.

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

Деинсталляция

Итак, поговорим немного о деинсталляции.

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

Программа инсталляции должна вести журнал инсталляции, в который должны быть занесены все действия, производимые этой программой: создание разделов в реестре, секций в .INI-файлах, копирование, переименование, регистрация ActiveX-компонентов и многое другое.

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

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

Создать каталог Directory. Удалить каталог Directory.
Копировать файл Source в Target. Удалить файл Target.
Копировать разделяемый файл Sourcr в Target. Увеличить счётчик инсталляций на 1, если он уже существует или присвоить ему 1 в противном случае. Уменьшить счётчик инсталляций на 1. Если он равен 0, то удалить файл Target
Создать раздел Key в реестре. Удалить раздел Key в реестре.
Создать параметр Value в реестре. Удалить параметр Value в реестре.
Изменить значение параметра Value с Old на New. Записать в Value значение Old.
Создать новый INI-файл. Удалить INI-файл.
Создать секцию в INI-файле. Удалить секцию в INI-файле.
Записать параметр в секцию INI-файла. Если параметр уже существует, сохранить его содержимое. Если в журнале сохранено предыдущее содержимое параметра — записываем его. В противном случае удаляем параметр из секции.
В этой таблице записаны некоторые часто встречающиеся операции. Возможно, для ваших целей вам потребуется кое-что ещё.

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

В статье, посвящённой системному реестру, рассказано, как поместить свою программу в список программ деинсталляции (Панель управления/Установка и удаление программ).

Что ещё? Самое главное — вы намучаетесь с удалением самой программы деинсталляции с жёткого диска. Дело в том, что программу невозможно удалить до тех пор, пока она запущена — Windows закрывает к ней доступ. Что делать? Если мы посмотрим, как с этой ситуацией справляются распространённые инсталляторы (например, InstallShield и Wise), то увидим, что они оставляют программу деинсталляции на диске. Она становится разделяемым ресурсом, частью операционной системы (помещается в каталог Windows). Например, у меня на диске находятся C:\WINDOWS\UNINST16.EXE, C:\WINDOWS\UNINST.EXE (InstallShield) и C:\WINDOWS\UNWISE.EXE (Wise). Это достаточно корректное решение, поскольку этими инсталляторами пользуются многие программы. Мы можем сделать то же самое, изменив имя программы деинсталляции (uninst и unwise уже заняты :)

Мы также можем скопировать программу деинсталляции во временный каталог и запустить её оттуда. Она, конечно, не будет уничтожена, однако при следующей чистке временного каталога, пользователь её удалит. Какие проблемы могут возникнуть на этом пути? Обратите внимание, что программу деинсталляции мы должны будем скопировать во временный каталог только во время инсталляции — в ином случае пользователь может удалить её значительно раньше, чем она ему потребуется для деинсталляции (а откуда он знает, что это за файл?). Значит, вариант может быть таким: скопировать программу, запусить её из нового каталога, а текущую копию завершить. Здесь как раз и находится проблема: как только наша программа будет завершена, фокус будет передан назад в окно Установка и удаление программ, а мы как раз начнём запрашивать пользователя, действительно ли он согласен удалить продукт с машины...

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

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


[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\ CurrentVersion\RunOnce]
SomeName="C:\WINDOWS\COMMAND.COM /C DEL C:\TEMP\DEINST.EXE"

При следующей перезагрузке компьютера будет вызван командый процессор, который и удалит ненужный EXE-файл. Затем параметр SomeName будет автоматически удалён из раздела RunOnce.

Командным процессором может быть не только command.com, но и cmd.exe (в NT), 4dos.com, 4nt.exe и другие программы. Переменная окружения COMSPEC содержит полный путь к текущему командному процессору


function GetCommand: String; var szCommandPath: array[0..MAX_PATH - 1] of Char; begin GetEnvironmentVariable('COMSPEC', szCommandPath, MAX_PATH); Result := String(szCommandPath); end;

Вот, видимо, и всё.


Ну вот, закончился цикл статей по написанию инсталлятора на Delphi. Вы прошли подробнейший курс из 9 уроков и рассмотрели каждый этап отдельно. Теперь самое время попробовать всё это на практике. Если вы всё это время были с нами и писали свой собственный инсталлятор, доделывайте его и присылайте нам! Мы оценим ваши труды и опубликуем программу на сайте!


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


Скачать полный архив статей "Написание инсталлятора на Delphi" (с рисунками) вы можете с нашего сайта. Вот здесь.


Документация.

В данном разделе публикуются различные ссылки, причём не только по Delphi но и по OpenGL, WinAPI, DirectX и т.д. (они могут быть на других языках, например, на Си). Присылайте свои ссылки на документацию по программированию.

"Delphi Russian Knowledge Base": http://www.sources.ru/delphi/drkb.zip
"3D programming FAQ": http://www.enlight.ru/faq3d/download/dd3dr2h.rar
"Русская справка по Delphi 5 и Object Pascal V.5.2": http://delphi-help.chat.ru/delphi_help.zip
"Delphi World": http://www.delphiworld.narod.ru/download, в проект входит много файлов; ссылки на них можно найти на данной странице.

[Ссылки прислал: Рудов Антон]


Кладовая.

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

Исходники программ:

WinAPI - программа, которая показывает возможности работы WinAPI. Поиск окон других приложений, изменение заголоков окон, получение информации об окнах, изменение состояния окон и многое другое. Открытые исходники помогут вам быстрее разобраться с возможностями этой могучей системы. [6.32 Кб, ZIP].

Компоненты:

JWBBalloon - "пузыри" - всплывающие подсказки округлой формы, получившие своё распространение большей частью в Windows XP. Придают программе изящный вид. [7.46 Кб, ZIP].

 


Друзья.

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

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


Юмор.

Забрали программиста в армию офицером. Построил он солдат и командует:
- На нулевой-первый рассчитайся!

***

Работа программиста и работа шамана имеют много общего: например, оба произносят непонятные слова, совершают непонятные действия и не могут объяснить, как это все работает.

***

На этом свете 10 типов людей - те, кто понимает двоичную систему счисления и те, кто не понимает ее.

***

Молитва сисадмина:
- Боже, избавь меня от ламеров, а с хакерами я сам управлюсь!

***

Для ухода за пожилым программистом требуется приятная женщина, говорящая на FORTRAN, BASIC и С++.

***

Звонок в фирму по продаже компьютеров и комплектующих:
- Здрасьте, у Вас жидкие мониторы есть?
Продавец нашелся сразу:
- Вам сколько литров: 15, 17, 19?!

***

Вначале был бит, потом байт, и только потом появилось слово.

***

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

[Анекдоты прислала: Dasha].


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

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


Сайт рассылки: http://www.delphi-faq.fatal.ru/
E-mail: Delphi-FAQ@list.ru
Страница рассылки: http://subscribe.ru/catalog/comp.soft.prog.delphifaq


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

В избранное