воскресенье, 8 февраля 2009 г.

Узнать пути к стандартным папкам

В Windows есть специальная функция, позволяющая получить пути к стандартным папкам.
В Delphi это будет выглядеть так:
uses ShlObj;

function GetSpecialPath(CSIDL: word): string;
var s: string;
begin
SetLength(s, MAX_PATH);
if not SHGetSpecialFolderPath(0, PChar(s), CSIDL, true)
then s := '';
result := PChar(s);
end;
Функции нужно передать id папки, путь которой хотим получить. Список id идёт далее.
Следует помнить, что не все id будуть работать в разных версиях Windows. Например папки 'Documents & Settungs' нет в 98-х и бессмысленно пытаться получить путь к ней.
Смысл данного поста скорее не в том, чтобы показать, как пользоваться функцией SHGetSpecialFolderPath, а, скорее, дать перечень CSIDL и описание к ним на русском.

Вот полный код:
uses ShlObj;

const
{
// Следующие идентификаторы имеются в модуле ShlObj:
CSIDL_DESKTOP = $0000;
// Виртуальный каталог, представляющий Рабочий стол. (Корень в проводнике)
CSIDL_INTERNET = $0001;
// Виртуальный каталог для Internet Explorer.
CSIDL_PROGRAMS = $0002;
// Меню Пуск -> Программы
CSIDL_CONTROLS = $0003;
// Виртуальный каталог, содержащий иконки пунктов панели управления
CSIDL_PRINTERS = $0004;
// Виртуальный каталог, содержащий установленные принтеры
CSIDL_PERSONAL = $0005;
// Виртуальный каталог, представляющий папку "Мои документы"
// До Vista ссылался на какталог "Мои документы" на жёстком диске
CSIDL_FAVORITES = $0006;
// Избранное. (обычно C:\Documents and Settings\username\Favorites)
CSIDL_STARTUP = $0007;
// Пуск -> Программы -> Автозагрузка
CSIDL_RECENT = $0008;
// Недавние документы (обычно C:\Documents and Settings\username\My Recent Documents
// Для добавления ссылки документа используйте SHAddToRecentDocs
CSIDL_SENDTO = $0009;
// Папка, содержащая ярлыки меню "Отправить" (Sent to...) (обычно C:\Documents and Settings\username\SendTo)
CSIDL_BITBUCKET = $000a;
// Виртуальный каталог, содержащий файлы в корзине текущего пользователя
CSIDL_STARTMENU = $000b;
// Элементы меню Пуск текущего пользователя (обычно C:\Documents and Settings\username\Start Menu)
CSIDL_DESKTOPDIRECTORY = $0010;
// Рабочий стол текущего пользователя (обычно C:\Documents and Settings\username\Desktop)
CSIDL_DRIVES = $0011;
// Виртуальный каталог, представляющий папку "Мой компьютер"
CSIDL_NETWORK = $0012;
// Виртуальный каталог, представляющий "Сетевое окружение"
CSIDL_NETHOOD = $0013;
// Папка "My Nethood Places" (обычно C:\Documents and Settings\username\NetHood)
// В неё ссылки на избранные расшаренные ресурсы
CSIDL_FONTS = $0014;
// Папка, содержащая установленные шрифты. (обычно C:\Windows\Fonts)
CSIDL_TEMPLATES = $0015;
// Шаблоны документов. (Обычно Settings\username\Templates)
CSIDL_COMMON_STARTMENU = $0016;
// Элементы меню Пуск для всех пользователей. (обычно C:\Documents and Settings\All Users\Start Menu)
// Константы, начинающиеся на CSIDL_COMMON_ существуют только в NT версиях
CSIDL_COMMON_PROGRAMS = $0017;
// Меню Пуск -> программы для всех пользователей (обычно C:\Documents and Settings\All Users\Start Menu\Programs)
CSIDL_COMMON_STARTUP = $0018;
// Меню Пуск -> Программы -> Автозагрузка для всех пользователей (обычно C:\Documents and Settings\All Users\Start Menu\Programs\Startup)
CSIDL_COMMON_DESKTOPDIRECTORY = $0019;
// Элементы Рабочего стола для всех пользователей (обычно C:\Documents and Settings\All Users\Desktop)
CSIDL_APPDATA = $001a;
// Папка, в которой рограммы должны хранить свои данные(C:\Documents and Settings\username\Application Data)
CSIDL_PRINTHOOD = $001b;
// Установленные принтеры. (обычно C:\Documents and Settings\username\PrintHood)
CSIDL_ALTSTARTUP = $001d; // DBCS
// user's nonlocalized Startup program group. Устарело.
CSIDL_COMMON_ALTSTARTUP = $001e; // DBCS
// Устарело
CSIDL_COMMON_FAVORITES = $001f;
// Ссылки "Избранное" для всех пользователей
CSIDL_INTERNET_CACHE = $0020;
// Временные Internet файлы (обычно C:\Documents and Settings\username\Local Settings\Temporary Internet Files)
CSIDL_COOKIES = $0021;
// Папка для хранения Cookies (обычно C:\Documents and Settings\username\Cookies)
CSIDL_HISTORY = $0022;
// Хранит ссылки интернет истории IE
}

// Следующих идентификаторов нет в ShlObj:
CSIDL_ADMINTOOLS = $30;
// Административные инструменты текущего пользователя (например консоль MMC). Win2000+

CSIDL_CDBURN_AREA = $3b;
// Папка для файлов, подготовленных к записи на CD/DVD
// (Обычно C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\CD Burning)

CSIDL_COMMON_ADMINTOOLS = $2f;
// Папка, содержащая инструменты администрирования

CSIDL_COMMON_APPDATA = $23;
// Папака AppData для всех пользователей. (обычно C:\Documents and Settings\All Users\Application Data)

CSIDL_COMMON_DOCUMENTS = $2e;
// Папка "Общие документы" (обычно C:\Documents and Settings\All Users\Documents)

CSIDL_COMMON_TEMPLATES = $2d;
// Папка шаблонов документов для всех пользователей (Обычно C:\Documents and Settings\All Users\Templates)

CSIDL_COMMON_MUSIC = $35;
// Папка "Моя музыка" для всех пользователей. (обычно C:\Documents and Settings\All Users\Documents\My Music)

CSIDL_COMMON_PICTURES = $36;
// Папка "Мои рисунки" для всех пользователей. (обычно C:\Documents and Settings\All Users\Documents\My Pictures)

CSIDL_COMMON_VIDEO = $37;
// Папка "Моё видео" для всех пользователей (C:\Documents and Settings\All Users\Documents\My Videos)

CSIDL_COMPUTERSNEARME = $3d;
// Виртуальная папка, представляет список компьютеров в вашей рабочей группе

CSIDL_CONNECTIONS = $31;
// Виртуальная папка, представляет список сетевых подключений

CSIDL_LOCAL_APPDATA = $1c;
// AppData для приложений, которые не переносятся на другой компьютер (обычно C:\Documents and Settings\username\Local Settings\Application Data)

CSIDL_MYDOCUMENTS = $0c;
// Виртуальный каталог, представляющий папку "Мои документы"

CSIDL_MYMUSIC = $0d;
// Папка "Моя музыка"

CSIDL_MYPICTURES = $27;
// Папка "Мои картинки"

CSIDL_MYVIDEO = $0e;
// Папка "Моё видео"

CSIDL_PROFILE = $28;
// Папка пользователя (обычно C:\Documents and Settings\username)

CSIDL_PROGRAM_FILES = $26;
// Папка Program Files (обычно C:\Program Files)

CSIDL_PROGRAM_FILESX86 = $2a;

CSIDL_PROGRAM_FILES_COMMON = $2b;
// Папка Program Files\Common (обычно C:\Program Files\Common)

CSIDL_PROGRAM_FILES_COMMONX86 = $2c;

CSIDL_RESOURCES = $38;
// Папка для ресерсов. Vista и выше (обычно C:\Windows\Resources)

CSIDL_RESOURCES_LOCALIZED = $39;

CSIDL_SYSTEM = $25;
// Папака System (обычно C:\Windows\System32 или C:\Windows\System)

CSIDL_SYSTEMX86 = $29;

CSIDL_WINDOWS = $24;
// Папка Windows. Она же %windir% или %SYSTEMROOT% (обычно C:\Windows)

function GetSpecialPath(CSIDL: word): string;
var s: string;
begin
SetLength(s, MAX_PATH);
if not SHGetSpecialFolderPath(0, PChar(s), CSIDL, true)
then s := GetSpecialPath(CSIDL_APPDATA);
result := PChar(s);
end;

Удаление файла без возможности восстановления

Код писался не для практических целей, а как демонстрация работы теории.
Поэтому в нём много места для оптимизации, т.к. код работает довольно медленно.
Но свою задачу он выполняет. А задача простая – удалить файл с дистка так, чтобы его невозможно было восстановить.
procedure ZeroFillDelete(FileName: string);  
var
fs: TFileStream;
i: integer;
procedure RandomWrite;
var b: byte;
begin
repeat
b := Random(256); fs.Write(b, 1);
until fs.Position + 1 >= fs.Size;
end;
procedure WritePattern(pattern: byte);
const patt: array[5..31] of dword = ($555555, $AAAAAA, $924924, $492492,
$249249, 0, $111111, $222222, $333333, $444444, $555555, $666666,
$777777, $888888, $999999, $AAAAAA, $BBBBBB, $CCCCCC, $DDDDDD,
$EEEEEE, $FFFFFF, $924924, $492492, $249249, $6DB6DB, $B6DB6D, $DB6DB6);
var d: dword;
begin
d := patt[pattern] shl 8;
repeat fs.Write(d, 3); until fs.Position + 3 >= fs.Size;
end;
begin
if not FileExists(FileName) then Exit;
for i := 1 to 35 do
try
fs := TFileStream.Create(FileName, fmOpenWrite);
try
if (i < 5) or (i > 31) then RandomWrite
else WritePattern(i);
finally
fs.Free;
end;
except Exit; end;
DeleteFile(FileName);
end;

Шифрование с закрытым ключём

Рассмотрим пример классического шифрования с закрытым ключём.
Данное шифрование считается ненадёжным, если пароль заложен в программу. Если пароль вводится пользователем, то стойкость зависит от сложности пароля.
Данный пример создан для удобства хранения шифрованных данных в реестре или текстовых и ini файлах. То есть, шифрованные бинарные данные возвращаются в текстовом HEX виде.
В представленом ниже коде всего две функции:

function EncString(s: string; pass: string = def; alg: Cardinal = CALG_RC4): string;
function DecString(s: string; pass: string = def; alg: Cardinal = CALG_RC4): string;
Первая шифрует, вторая, соответственно, дешифрует.
Первый параметр обязательный - это сами данные.
Второй параметр необязательный - это пароль. Если не указан, используется внутренний фиксированный пароль (константа def).
Третий параметр совсем необязательный - алгоритм шифрования. Всего два варианта - RC2 и RC4. Для шифрования паролей лучше использовать RC2, т.к. в RC4 видно, сколько байт зашифровано. Для всего остального можно использовать RC4 (по умолчанию), чтоб не добавлять лишнего мусора.
Пример использования:
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2.Text := EncString(Edit1.Text);
Edit1.Text := '';
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Edit1.Text := DecString(Edit2.Text);
end;
Далее сам код модуля.
Код не использует других модулей (даже Windows). Построен на CryptoAPI функциях системы, поэтому практически не добавляет веса программе и может использоваться, как в VCL проектах, так и в проектах на чистом API.
Шифрованные данные "подсаливаются" так, что одни и те же данные, зашифрованные дважды, дают разный результат, что практически исключает возможность подобрать ключ анализом, а не тупым брутфорсом.
unit MiniCry;

interface

const
CALG_RC4 = ((3 shl 13) or (4 shl 9) or 1);
CALG_RC2 = ((3 shl 13) or (3 shl 9) or 2);
def = 'WrSxnCNBpJ7Ko4[e",7Ty)a0ykP)62Ce[.bAA;SuOf4*{nagx4s,;5!eHU!v=p3z';

function EncString(s: string; pass: string = def; alg: Cardinal = CALG_RC4): string;
{* зашифровать строку }
function DecString(s: string; pass: string = def; alg: Cardinal = CALG_RC4): string;
{* расшифровать строку }

implementation

const
ADVAPI32 = 'advapi32.dll';
PROV_RSA_FULL = 1;
CRYPT_VERIFYCONTEXT = $F0000000;
CALG_SHA = ((4 shl 13) or 0 or 4);

type
HCRYPTPROV = Cardinal;
HCRYPTKEY = Cardinal;
ALG_ID = Cardinal;
PHCRYPTPROV = ^HCRYPTPROV;
PHCRYPTKEY = ^HCRYPTKEY;
LPAWSTR = PWideChar;
HCRYPTHASH = Cardinal;
PHCRYPTHASH = ^HCRYPTHASH;

function CryptReleaseContext(hProv:HCRYPTPROV;dwFlags:LongWord):LongBool;stdcall;external ADVAPI32 name 'CryptReleaseContext';
function CryptAcquireContext(Prov:PHCRYPTPROV;Container:LPAWSTR;Provider:LPAWSTR;ProvType:LongWord;Flags:LongWord):LongBool;stdcall;external ADVAPI32 name 'CryptAcquireContextW';
function CryptEncrypt(Key:HCRYPTKEY;Hash:HCRYPTHASH;Final:LongBool;Flags:LongWord;Data:PBYTE;Len:PLongWord;BufLen:LongWord):LongBool;stdcall;external ADVAPI32 name 'CryptEncrypt';
function CryptDecrypt(Key:HCRYPTKEY;Hash:HCRYPTHASH;Final:LongBool;Flags:LongWord;Data:PBYTE;Len:PLongWord):LongBool;stdcall;external ADVAPI32 name 'CryptDecrypt';
function CryptCreateHash(Prov:HCRYPTPROV;Algid:ALG_ID;Key:HCRYPTKEY;Flags:LongInt;Hash:PHCRYPTHASH):LongBool;stdcall;external ADVAPI32 name 'CryptCreateHash';
function CryptHashData(Hash:HCRYPTHASH;Data:PBYTE;DataLen :LongInt;Flags:LongInt):LongBool;stdcall;external ADVAPI32 name 'CryptHashData';
function CryptDeriveKey(Prov:HCRYPTPROV;Algid:ALG_ID;BaseData:HCRYPTHASH;Flags:LongInt;Key:PHCRYPTKEY) :LongBool;stdcall;external ADVAPI32 name 'CryptDeriveKey';
function CryptDestroyHash(hHash :HCRYPTHASH) :LongBool;stdcall;external ADVAPI32 name 'CryptDestroyHash';

function ByteToHex(b: byte): string;
function GetChar(b: byte): char;
begin
if b < 10 then Result := chr(Ord('0') + b)
else Result := chr(Ord('A') - 10 + b);
end;
begin
Result := GetChar(b div 16) + GetChar(b mod 16);
end;

function StringToHex(const s: string): string;
var
i: integer;
begin
result := '';
for i := 1 to Length(s) do
result := result + ByteToHex(ord(s[i]));
end;

function StrToIntDef(s: string; def: integer): integer;
var
i, c: integer;
begin
Val(s, i, c);
if c = 0 then Result := i else Result := def;
end;

function HexToString(const s: string): string;
var
i: integer;
begin
result := '';
for i := 1 to Length(s) div 2 do
try result := result + chr(StrToIntDef('$' + copy(s, i*2-1, 2), 32));
except result := result + '?'; end;
end;

procedure InitPass(pass: string; alg: LongWord; var hProv: HCRYPTPROV; var hSKey: HCRYPTKEY);
var
hash: HCRYPTHASH;
begin
CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptCreateHash(hProv, CALG_SHA, 0, 0, @hash);
CryptHashData(hash, @pass[1], length(pass), 0);
CryptDeriveKey(hProv, alg, hash, 0, @hSKey);
CryptDestroyHash(hash);
end;

function EncString(s: string; pass: string = def; alg: Cardinal = CALG_RC4): string;
var
p: PByte;
sz: LongWord;
hProv: HCRYPTPROV;
hSKey: HCRYPTKEY;
begin
InitPass(pass, alg, hProv, hSKey);
Insert(chr(Random(256)), s, 1);
sz := Length(s);
GetMem(p, sz + 8); move(s[1], p^, sz);
if CryptEncrypt(hSKey, 0, true, 0, p, @sz, sz + 8) then
begin
SetLength(result, sz);
move(p^, result[1], sz);
result := StringToHex(result);
end else result := s;
FreeMem(p);
CryptReleaseContext(hProv, 0);
end;

function DecString(s: string; pass: string = def; alg: Cardinal = CALG_RC4): string;
var
p: PByte;
sz: LongWord;
hProv: HCRYPTPROV;
hSKey: HCRYPTKEY;
begin
InitPass(pass, alg, hProv, hSKey);
s := HexToString(s);
sz := Length(s);
GetMem(p, sz); move(s[1], p^, sz);
if CryptDecrypt(hSKey, 0, true, 0, p, @sz) then
begin
SetLength(result, sz);
move(p^, result[1], sz);
delete(result, 1, 1);
end else result := s;
FreeMem(p);
CryptReleaseContext(hProv, 0);
end;

initialization
Randomize;

end.

Наложение изображений с прозрачностью

Данный код накладывает одно изображение на другое с указанной степенью прозрачности.
Степень прозрачности задаётся от 0 до 255.
var   
bmp1, bmp2: TBitMap;
Blend: TBlendFunction;
begin
bmp1 := TBitMap.Create;
bmp2 := TBitMap.Create;
bmp1.LoadFromFile('C:\1.bmp'); // загружаем 1 битмап
bmp2.LoadFromFile('C:\2.bmp'); // и второй битмап
bmp1.PixelFormat := pf32bit; // переводим оба в 32 бит
bmp2.PixelFormat := pf32bit;
Blend.BlendOp := AC_SRC_OVER;
Blend.BlendFlags := 0;
Blend.SourceConstantAlpha := 128; // прозрачность 50% (0 - 255)
Blend.AlphaFormat := AC_SRC_ALPHA; // либо = 0 (другой алгоритм)
// накладываем битмап 2 на битмап 1. Результат в bmp1
if Windows.AlphaBlend(bmp1.Canvas.Handle, 0, 0, bmp1.Width, bmp1.Height,
bmp2.Canvas.Handle, 0, 0, bmp2.Width, bmp2.Height, Blend) then
Canvas.Draw(0, 0, bmp1) // рисуем результат на форме
else ShowMessage(IntToStr(GetLastError)); // или код ошибки, если наложить не удалось
bmp1.Free; bmp2.Free; // уничтожаем битмапы
end;

Уменьшаем Exe, удаляя релоки без сторонних утилит

Многие знают, что можно уменьшить размер exe файла, не используя упаковщики и не изменяя функциональность, путём удаления из exe таблицы релокаций.
Обычно для этого используют сторонние утилиты. Например StripReloc Джордона Рассела.
А теперь я расскажу страшную тайну. В Delphi 2006 и выше, релоки можно не удалять, а просто не создавать!

В Delphi 2006 появилась недокументированная директива компилятора {$SETPEFLAGS}. Она позволяет настроить несколько тонких моментов создания нашего бинарника.
В первую очередь она интересна тем, что позволяет отключить создание таблицы релокаций.
Внимание! Не отключайте таблицы релокаций в dll, bpl и др. файлах.
Таблица релокации не нужна exe файлу, т.к. он всегда грузится по одному и тому же адресу.
Использование директивы {$SETPEFLAGS} очень простое:
  • Откройте файл проекта (dpr)
  • В uses добавьте Windows
  • Ниже пропишите {$SETPEFLAGS IMAGE_FILE_RELOCS_STRIPPED}
Попробуйте скомпилировать файл до добавления этой директивы и после.
Вы сами сможете убедиться, что размер exe уменьшился.

В дополнение хочу сказать, что использование SETPEFLAGS этим не ограничивается.
У неё есть ещё масса интересных возможностей. Получить их полный список очень просто:
  • Откройте модуль Windows
  • Найдите в нём поиском IMAGE_FILE_RELOCS_STRIPPED
Нашли? Ниже идёт целый список констант, начинающихся с IMAGE_FILE_
Справа идёт комментарий. Для включения нескольких инструкций, используйте or. Пример:
{$SETPEFlAGS IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_DEBUG_STRIPPED or
IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED or
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}
Что я здесь сделал?
  • IMAGE_FILE_RELOCS_STRIPPED - отрезал релоки
  • IMAGE_FILE_DEBUG_STRIPPED - Выбросил из ехе Debug информацию
  • IMAGE_FILE_LINE_NUMS_STRIPPED - Выбросил из exe информацию о номерах строк
  • IMAGE_FILE_LOCAL_SYMS_STRIPPED - Выбросил local symbols
  • IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP - При запуске exe с компакта, флэшки, других извлекаемых устройств, считать exe в свап и запустить оттуда. Полезно, если нужно запустить программу с компакта, а потом попросить вставить другой...
  • IMAGE_FILE_NET_RUN_FROM_SWAP - аналогично предыдущей, только для сетевых дисков

Delphi (язык программирования)

Delphi (Де́льфи, произносится /ˈdɛlˌfi/[1]) — язык программирования, который используется в одноимённой среде разработки. Название используется начиная с 7 версии среды разработки[2], ранее это был Object Pascal, разработанный фирмой Borland и изначально реализованный в её пакете Borland Delphi, от которого и получил в 2003 году своё нынешнее название. Object Pascal по сути является наследником языка Pascal с объектно-ориентированными расширениями.
По поводу «правильного» произношения названия языка было сломано немало копий не только в России [3]. Интересно, что нет единства даже среди англоязычных стран. В частности, согласно данному источнику, в Великобритании доминирует произношение «дел-фи́»[4], а в США — «де́л-фай»[5].

Целевая платформа
Изначально среда разработки была предназначена исключительно для разработки приложений Microsoft Windows, затем был реализован также для платформ GNU/Linux (как Kylix), однако после выпуска в 2002 году Kylix 3 его разработка была прекращена, и, вскоре после этого, было объявлено о поддержке Microsoft .NET. При этом высказывались предположения, что эти два факта взаимосвязаны.
Реализация среды разработки проектом Lazarus (Free Pascal) позволяет использовать его для создания приложений на Delphi для таких платформ, как GNU/Linux, Mac OS X и Windows CE.

История языка
Delphi — результат развития языка Турбо Паскаль, который, в свою очередь, развился из языка Паскаль. Паскаль был полностью процедурным языком, Турбо Паскаль начиная с версии 5.5 добавил в Паскаль объектно-ориентированные свойства, а Delphi — объектно-ориентированный язык программирования с возможностью доступа к метаданным классов (то есть к описанию классов и их членов) в компилируемом коде, также называемом интроспекцией. Так как все классы наследуют функции базового класса TObject, то любой указатель на объект можно преобразовать к нему, после чего воспользоваться методом ClassType и функцией TypeInfo, которые и обеспечат интроспекцию. Также отличительным свойством Дельфи от С++ является то, что объекты по-умолчанию располагаются в динамической памяти. Однако можно переопределить виртуальные методы NewInstance и FreeInstance класса TObject. Таким образом, абсолютно любой класс может осуществить «желание» «где хочу — там и буду лежать». Соответственно организуется и «многокучность».
Де-факто Object Pascal, а затем и язык Delphi являются функциональными наращиваниями Turbo Pascal. Об этом говорят обозначения версий компилятора. Так, в Delphi 7 компилятор имеет номер версии 15.0 (Последняя версия Borland Pascal / Turbo Pascal обозначалась 7.0, в Delphi 1 компилятор имеет версию 8.0, в Delphi 2 — 9.0, и т. д. Номер версии 11.0 носит компилятор Pascal, входивший в состав среды C++ Builder).
Delphi оказал огромное влияние на создание концепции языка C# для платформы .NET. Многие его элементы и концептуальные решения вошли в состав С#. Одной из причин называют переход Андерса Хейлсберга, одного из ведущих разработчиков Дельфи, из компании Borland Ltd. в Microsoft Corp.

* Версия 1 была предназначена для разработки под 16-ти разрядную платформу Win16;
* Версии со второй компилируют программы под 32-х разрядную платформу Win32;
* Вместе с 6-й версией Delphi вышла совместимая с ним по языку и библиотекам среда Kylix, предназначенная для компиляции программ под операционную систему GNU/Linux;
* Версия 8 способна генерировать байт-код исключительно для платформы .NET. Это первая среда, ориентированная на разработку мультиязычных приложений (лишь для платформы .NET);
* Последующие версии (обозначаемые годами выхода, а не порядковыми номерами, как это было ранее) могут создавать как приложения Win32, так и байт-код для платформы .NET;

Delphi for .NET — среда разработки Delphi, а также язык Delphi (Object Pascal), ориентированные на разработку приложений для .NET.
Первая версия полноценной среды разработки Delphi для .NET — Delphi 8. Она позволяла писать приложения только для .NET. В настоящее время, в Delphi 2006, можно писать приложения для .NET, используя стандартную библиотеку классов .NET, VCL для .NET. Среда также позволяет создавать .NET-приложения на C# и Win32-приложения на C++. Delphi 2006 содержит функции для написания обычных приложений с использованием библиотек VCL и CLX. Delphi 2006 поддерживает технологию MDA с помощью ECO (Enterprise Core Objects) версии 3.0.
В марте 2006 года компания Borland приняла решение о прекращении дальнейшего совершенствования интегрированных сред разработки JBuilder, Delphi и C++ Builder по причине убыточности этого направления. Планировалась продажа IDE-сектора компании. Группа сторонников свободного программного обеспечения организовала сбор средств для покупки у Borland прав на среду разработки и компилятор (см. openDelphi.org).
Однако в ноябре того же года было принято решение отказаться от продажи IDE бизнеса. Тем не менее, разработкой IDE продуктов теперь будет заниматься новая компания — CodeGear, которая будет финансово полностью подконтрольна Borland.
В августе 2006 года Borland выпустил облегченные версию RAD Studio под именем Turbo: Turbo Delphi, Turbo Delphi for .NET, Turbo C#, Turbo C++. В марте 2008 года было объявлено о прекращении развития этой линейки продуктов.
В марте 2007 года CodeGear порадовала пользователей обновленной линейкой продуктов Delphi 2007 for Win32 и выходом совершенно нового продукта Delphi 2007 for PHP.
В июне 2007 года CodeGear представила свои планы на будущее, то есть опубликовала так называемый roadmap, с которым можно ознакомиться здесь
25 августа 2008 года компания Embarcadero, новый хозяин CodeGear, опубликовала пресс-релиз на Delphi for Win32 2009. Версия принесла[6] множество нововведений в язык, как-то:

* Полная поддержка Юникода по умолчанию во всех частях языка, VCL и RTL.
* Полная замена всех строковых и символьных типов на их юникодные аналоги (String = UnicodeString, Char = WideChar)
* Полная замена всех Windows API фунций на юникодные аналоги (MessageBox = MessageBoxW)
* Обобщённые типы, они же generics.
* Анонимные методы.

Пример

 {Событие, происходящее при создании формы MainForm}
procedure TMainForm.FormCreate(Sender: TObject);
var
{Объявление переменной типа TStrings(список строк).}
Strings: TStrings;
begin
{Создание(выделение памяти и т. д.) объекта типа TStringList.
TStringList - это потомок TStrings, реализующий абстрактные методы.}

Strings := TStringList.Create;
try
{Добавление строки.}
Strings.Add('Добавляемая строка.');
{Сохранение строк в файл.}
Strings.SaveToFile('C:\Strings.txt');
finally
{Удаление объекта.}
Strings.Free;
end;
end;


Ваша собственная Интернет-радиостанция


Вы, возможно, не знали о том, что компоненты, которые устанавливаются вместе с Windows Media Player 9 (и более поздними версиями) содержат встроенные средства широковещательной передачи аудио-данных. Фактически каждый подключенный к сети компьютер, на котором установлен Windows Media Player, может быть превращен в сетевую радиостанцию. Для этого можно воспользоваться готовыми программами. Можно написать собственную программу, используя напрямую интерфейсы, предоставляемые Windows Media System (такие как IWMWriterNetworkSink, IWMProfile, IWMCodecInfo) и еще десяток функций и интерфейсов (их описание содержится в Windows Media SDK).
Мы рассмотрим другое решение - создание собственной Интернет-радиостанции с помощью Delphi и компонентов New Audio Components (NewAC). Написать такую программу очень просто. Мы увидим, что в простейшем примере нам будет достаточно соединить два компонента и настроить их свойства.
Что дает нам написание собственной программы передачи аудио-данных? Прежде всего - свободу. Можно организовать передачу аудио с помощью микрофона, подключенного к вашему компьютеру. Можно передавать содержимое аудио-записей с вашего компьютера (для этого надо будет задействовать компоненты чтения аудио-данных из различных форматов, входящие в состав NewAC). Можно просто транслировать все, что звучит в вашей системе.
Поскольку передача данных выполняется в формате Windows Media Audio, ее можно будет прослушивать с любого компьютера, на котором установлен Windows Media Player, или совместимый проигрыватель. Стоит отметить, что за последние годы качество потокового аудио-формата Windows Media Audio заметно улучшилось, так что даже при скорости передачи данных 16 кбит/сек мы можем получить звук вполне приемлемого радио-качества. При этом передача данных создаст незначительную нагрузку на локальную сеть. Разумеется, ничто не мешает нам организовать передачу данных с более высоким битрейтом, (а, следовательно, - качеством), но нагрузка на сеть в этом случае, естественно, возрастет. При наличии DSL-модема и видимого из внешней сети IP-адреса вы даже можете организовать трансляцию в глобальную сеть, хотя число клиентов, способных принимать вашу радиопередачу будет не очень велико.

Пишем программу
Передача данных осуществляется компонентом TWMStreamedOut. Разместим этот компонент в форме приложения.стим этот компонент в форме приложения.


В Инспекторе объектов следует настроить важнейшие свойства объекта WMStreamedOut1
.

Свойство DesiredBitrate позволяет установить скорость и качество передачи данных. Скажем сразу, что фактическая скорость передачи данных может быть ниже, чем та, которую мы выбрали. Дело в том, что система Windows Media предоставляет нам несколько кодеков, каждый из которых работает с фиксированным набором входных форматов аудио-данных. Результирующий формат данных, созданных кодеком, зависит от типа кодека и входного формата данных, в большей степени, чем от заданного нами битрейта. Компонент TWMStreamedOut сам подбирает оптимальный кодек (можно пойти и по более сложному пути - выбрать нужный коде и формат вручную, но сейчас мы рассматриваем самое простое решение). Поскольку все кодеки являются частью формата Windows Media Audio, принимающая программа (Windows Media Player) справится с любым сочетанием. Свойство Id3V2Tags позволяет нам добавить текстовую информацию к передаваемой записи (эта информация будет отображаться в принимающей программе). Свойство MaxClients позволяет указать максимальное число одновременных подключений к нашей радиостанции (если присвоить этому свойству значение 0, максимально допустимое число клиентов будет неограниченным). В свойстве Port мы указываем номер порта, по которому наша программа будет ожидать запросы на подключение. С помощью свойства Input мы указываем объекту WMStreamedOut1 объект-источник данных. Обзор компонентов-источников аудиоданных NewAC выходит за рамки этой статьи. В нашем примере мы используем компонент DXAudioIn, который позволяет передавать звук, поступающий на различные входы ваших звуковых карт или просто работать в режиме "What U hear" - "все, что вы слышите", если ваше оборудование поддерживает такой режим. В обработчике события OnClick кнопки StartButton, запускающей передачу, достаточно написать:
procedure TForm1.StartButtonClick(Sender: TObject);
begin
StartButton.Enabled := False;
WMStreamedOut1.Run;
end;

Начинаем радиовещание

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

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

Прослушивание

Для того чтобы "настроиться" на нашу радиостанцию, нужно запустить проигрыватель Windows Media, выбрать команду "Файл >> Открыть URL-адрес…" и в открывшемся окне ввести адрес вида:

mms://<имя_узла>:<порт>


На всякий случай поясню, что "порт" должен соответствовать тому значению, которое мы указали в свойстве Port объекта WMStreamedOut1.

После этого вы можете насладиться прослушиванием.



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

Открытие блога!

Здраствуйте!
Вот я и создал свой первый блог посвещенный языку программирования Delphi
В даном блоге я буду описывать самые насушенные вопросы по этому языку программирования!
Также вы можете задавать свои вопросы я с радостью на них отвечу!