Delphi - база знаний

         

Blitting, Спрайты и Анимация


Blitting, Спрайты и Анимация





Для тех, кто интересуется, что это за слово такое "JEDI"? выберите в Delphi 5 пункт меню Help->About и наберите слово JEDI, удерживая нажатой клавишу Alt. Вы узнаете, что JEDI ? это аббревиатура, расшифровывающаяся как Join Endeavor of Delphi Innovators. (на русский это можно перевести приблизительно ? Совместные Усилия Дельфийских Новаторов или еще лучше - все для Delphi, все для победы) :-).

Звучит красиво, но нам-то что до этого? На самом деле нам до этого есть дело ? в рамках проекта JEDI (кстати, некоммерческого и держащегося на энтузиазме, пусть и с официальным одобрением Borland), в рамках именно этого проекта были созданы заголовочные файлы DirectX для Delphi. Так скачаем же их! (http://www.delphi-jedi.org/DelphiGraphics/)

Итак, заголовочные фалы у нас есть. Более того ? мы умеем инициализировать Direct Draw, создавать Surface'ы и загружать на них картинки. (Если Вы забыли как это делается ? перечитайте первые две главы).

Наконец то мы приблизились к самому интересному. Спрайты. Анимация. Blitting.

Blitting -непереводимое на русский язык слово. Тоже кстати аббревиатура - bit block transfer ? пересылка блоков бит. Благодаря этой пересылке, мы можем скопировать прямоугольную область из одной части Surface'а в другую или из одного Surface'а в другой. Такое копирование происходит пересылкой байт в видеопамяти, отсюда и название - bit block transfer. Да конечно, ничего удивительного в копировании прямоугольных участков Вы не видите ? это можно и без DirectDraw сделать кучей способов… Стоп! Прежде чем Вы начнете перечислять эти способы ? Blitting с использованием DirectDraw самый быстрый. Тем паче, что большинство современных видеоадаптеров поддерживают его на аппаратном уровне. Чувствуете, к чему я клоню? Стоит разобраться с Blitting'ом внимательнее.

Итак, для копирования прямоугольных участков интерфейс IDirectDrawSurface имеет два метода: IDirectDrawSurface4::Blt и IDirectDrawSurface4::BltFast. Как видно из названия второй быстрее ? с него и начнем.





functionBltFast(dwX: DWORD;
  dwY: DWORD;
  lpDDSrcSurface: IDirectDrawSurface4;
  lpSrcRect: PRect;
  dwTrans: DWORD): HResult;




Копирует прямоугольный участок из Surface'а-источника, задаваемого параметром lpDDSrcSurface. Первые два параметра метода ? dwX и dwY ? координаты верхнего левого угла прямоугольника на принимающем Surface'е - в эту точку будет скопирован прямоугольный участок, размеры которого задаются структурой типа TRect (параметр lpSrcRect типа PRect ? указатель на TRect). (для тех, кто не знаком с типом TRect ? познакомьтесь с ним в справке Delphi) Параметр dwTrans ? набор флагов, о них чуть позже. Использовать BltFast можно, например, так:



// копируем прямоугольник, размер которого задается переменной
// Kvadratik из Surface'а AnotherSurface в PrimarySurface.
PrimarySurface.BltFast(10, 10, AnotherSurface, Kvadratik,
  DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT);




Если вызвать этот метод, передав в качестве параметров dwX и dwY нулевые значения, а вместо указателя на ограничивающий прямоугольник lpSrcRect ? nil, то будет скопирован весь Surface-источник.

Вторая функция



function Blt(lpDestRect: PRect;
  lpDDSrcSurface: IDirectDrawSurface4;
  lpSrcRect: PRect;
  dwFlags: DWORD;
  lpDDBltFx: PDDBltFX): HResult;




Здесь координаты принимающего (lpDestRect) и передающего (lpSrcRect) Surface'ов задаются с помощью структур TRect. Размеры передающего и принимающего прямоугольников могут быть не равны! Функция Blt выполнит масштабирование автоматически. Но возможности Blt этим не ограничиваются: можно использовать его для закрашивания областей экрана определенным цветом (dwFlags:=DDBLT_COLORFILL, lpDDBltFx.dwFillColor:= цвет), можно зеркально переворачивать копируемый прямоугольник по горизонтали или по вертикали (dwFlags:=DDBLT_DDFX, lpDDBltFx.dwDDFX:=DDBLTFX_MIRRORUPDOWN или DDBLTFX_MIRRORLEFTRIGHT), поворачивать его на 90, 180, 270 градусов (dwFlags:=DDBLT_DDFX, lpDDBltFx.dwDDFX:= DDBLTFX_ROTATE90 или DDBLTFX_ROTATE180 или DDBLTFX_ROTATE270), поворачивать на любой заданный угол (угол задается в 1/100-х градуса) (dwFlags:= DDBLT_ROTATIONANGLE, lpDDBltFx.dwRotationAngle:=угол поворота)…. и делать еще многое другое. За все эти удовольствия приходится расплачиваться быстродействием ? Blt обладает многими возможностями, которых нет в BltFast, но работает чуть медленнее.

Кстати о скорости. Несмотря на потрясающую скорость Blitting-операций, использующих всю мощь аппаратного ускорения, может возникнуть ситуация, когда видеоадаптер еще не успел закончить пересылку одного блока байт, а наша программа уже просит его сделать другую. Что будет в таком случае? Катастрофа? Нет. Просто функция Blt или BltFast вернет код ошибки DDERR_WASSTILLDRAWING. Чтобы такого не происходило, можно указать Blitting-функциям, что им следует ждать, не возвращая управления до тех пор, пока видеоадаптер не выполнит операцию. Для этого при вызове функции Blt параметру dwFlags нужно присвоить значение DDBLT_WAIT, а при вызове BltFast - значение DDBLTFAST_WAIT параметру dwTrans.

Самое время рассказать, наконец, поподробнее о параметре dwTrans функции BltFast. Кроме флага, используемого для приостановки программы на время неготовности видеоадаптера, этот параметр используется для указания цветового ключа (Color Key).

Цветовой ключ ? очень полезная штука, из разряда тех, которые следовало бы изобрести, если бы их не было. Цветовой ключ ? это один или, несколько цветов, предназначенных для изображения "прозрачного" цвета. Пикселы окрашенные этим цветом не копируются при Blitting'е. Это позволяет создавать иллюзию непрямоугольного изображения, хотя при Blitting'е копируются только прямоугольные области. Делается это вот как: рисуем (или просим нарисовать кого-нибудь у кого это хорошо получается) какую-нибудь картинку, ограниченную прямоугольной областью. Все пикселы этой прямоугольной области, которые не относятся к картинке, закрашиваем каким-то особым цветом, который не использовался в самой картинке. Этот особый цвет назначаем в качестве цветового ключа ? при Blitting'е он не будет копироваться, и вместо пикселов, окрашенных этим цветом, останутся пикселы фона ? возникнет иллюзия прозрачности. Такая картинка, в прямоугольной области, заполненной цветовым ключом называется "спрайт".

Итак, параметр dwTrans функции BltFast может принимать следующие, кроме уже знакомого нам DDBLTFAST_WAIT, значения:

DDBLTFAST_NOCOLORKEY ? цветовой ключ не используется;
DDBLTFAST_SRCCOLORKEY - используется цветовой ключ Surface'а ?источника;
DDBLTFAST_DESTCOLORKEY - используется цветовой ключ Surface'а ?приемника;
Аналогично, при использовании цвтового ключа с функцией Blt, ее параметру dwFlags присваивают значение DDBLT_KEYSRC (цветовой ключ источника) или DDBLT_KEYDEST (цветовой ключ приемника).
Для задания цветового ключа предназначена специальная структура TDDColorKey. Вот ее описание



TDDColorKey = packed record
  dwColorSpaceLowValue: DWORD;
  dwColorSpaceHighValue: DWORD;
end;




Как видите это запись, состоящая из двух полей типа DWORD, поле dwColorSpaceLowValue ? означает нижнюю границу диапазона цветов, который используется в качестве цветового ключа, dwColorSpaceHighValue - верхнюю границу диапазона цветов.

Пример задания цветового ключа:



{для 8 - битового палитрового режима}
dwColorSpaceLowValue := 26;
dwColorSpaceHighValue := 26;
// 26 - ой элемент палитры будет использоваться как цветовой ключ.

{для 24 - битового безпалитрового режима}
dwColorSpaceLowValue = RGB(255, 128, 128);
dwColorSpaceHighValue = RGB(255, 128, 128);
// Цвет RGB(255, 128, 128) ? будет считаться прозрачным.

 


Естественно, для Blitting'а спрайт должен находится на каком-то Surface. А у Surface'а для указания цветового ключа есть специальный метод: IDirectDrawSurface4.SetColorKey, который принимает в качестве параметра указатель на структуру типа TDDColorKey, описывающую цветовой ключ.

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

Алгоритм 1.

Подготовить два Surface'а ? Primary (видимый на экране) и BackBuffer ? они будут учавствовать во flip-цепочке (см. первую главу). Кроме того, понадобятся Surface'ы для хранения фонового изображения и для хранения всех изображений всех спрайтов. Загрузить на Surface'ы соответствующие изображения (см. вторую главу).
Занести в BackBuffer-Surface изображение фоновой картинки, выполнив BltFast с соответствующего Surface'а (тем самым удалив на нем спрайты если они там были).
Занести в BackBuffer-Surface изображения всех спрайтов, поверх картинки фона, используя цветовые ключи, каждый в соответствующие координаты, и каждый в соответствующей фазе движения. Это можно сделать либо функцией BltFast либо функцией Blt.
Выполнить Flip. Очередной кадр анимации появится на экране. Подождать некоторое время (если необходимо) и повторить с шага 2.
Этот примерный алгоритм можно усовершенствовать, ведь на шаге 2 перерисовывается вся картинка фона, можно, зная координаты всех спрайтов, перерисовывать только ту часть фоновой картинки, на которой находятся спрайты, требующие перемещения.

Пожалуй, пришло время попробовать все это на практике. Посмотрите на мой пример (DDrawPrimer3.zip 80K ). Программа-пример инициализирует DirectDraw, создает три Surface'а, два размером 640Х480 (т.е. на весь экран) (FPrimarySurface и FPictureSurface), и один маленький (FSpriteSurface), для хранения изображения спрайта, и загружает на них соответствующие картинки, на FPrimarySurface и FPictureSurface ? изображение фона, а на FSpriteSurface ? изображения спрайта. В этом нет ничего нового, с этим Вы уже познакомились в первых двух главах. Вы можете открыть изображение из файла Sprite.bmp, которое загружается на FSpriteSurface и убедится, что там находятся изображения для всех фаз анимации спрайта (я пытался нарисовать что-то вроде жучка, перебирающего ногами, но похоже получилось нечто, больше смахивающее на муравья). В моем примере для простоты, я несколько отошел от Алгоритма 1 ? вместо рисования на BackBuffer'e c последующим вызовом функции Flip я рисую непосредственно на главном, видимом Surface. Это может привести к небольшому миганию спрайта при перерисовке, но я думаю, в нашем примере это не так уж и существенно ? мне не хотелось его слишком усложнять.

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

Если Вы хорошо знакомы с объектно-ориентированным подходом в программировании, Вы, безусловно, подвергнете Алгоритм 1 беспощадной (и справедливой) критике. В самом деле, почему бы не создать специальный класс спрайта, который сам бы перерисовывал себя при каждой итерации, зная свои старые и новые координаты. Можно было бы снабдить этот класс методами, автоматически меняющими картинку спрайта при анимации, регулирующими скорость анимации и т.п. Что ж, это очень неплохая идея. Я надеюсь рассказанная мной информация послужит Вам подспорьем для создания чего-то подобного. Впрочем можно воспользоваться и каким-либо готовым спрайтовым "движком", например тем, что входит в состав набора компонент DelphiX. Спрайтовый Engine от Hiroyuki Hori очень неплох. Примеры его использования входят в поставку DelphiX ? они находятся в каталогах \Samples\Sprite\Basic и \Samples\Sprite\Shoot.

На этом я пока заканчиваю рассказ о DirectDraw ? присылайте свои предложения и замечания: aziz@telebot.com или error@softhome.net.

Автор: Азиз (JINX)

Взято из





BLOB has been modified., Index is out of date


BLOB has been modified., Index is out of date




Объяснение от Борланд:
Index out Date ($2F02) is an error that occurs while using Paradox tables when the data in a table and a corresponding index is not consistent. In most cases (see below for the one exception), short of malicious behavior such as renaming an index, adding some data to the table, then renaming the index back, there is no programmatic way to cause this error to occur. There is no way to determine which index is out of date. All indexes must be recreated.

Blob has been modified ($3302) is an error that occurs when the Blob portion of the record contained in the .DB file has become inconsistent with the Blob portion in the .MB file. This could occur when the write to the .DB file was successful but the .MB file did not get updated, or visa-versa.

There are a few mechanisms to fix a table where these errors have occurred.
1. First try re-starting the application. It is possible that the BDE has become unstable and is reporting incorrect errors. Also try opening the table with a different application.
2. Use Paradox 7 or 8 to run the Table Repair utility. Please see original documentation for more information.
3. Run TUtility and rebuild the table. TUtility is an unsupported utility available for download from the Borland web site in the {Utilities, programs and updates section}.
4. Delete all indexes and recreate them (Index out Date ($2F02) error only). To do this you'll need to know the structure of all your indexes (including primary) before recreating them, which means you need to know the structure of all indexes before the error occurs.
There are 8 known possible causes for this error.
1. Incorrectly setting the LOCAL SHARE property.

Most commonly this occurs via Peer-to-Peer networking. In this case the two different database engines are on two CPUs, even though they may be the same version. See { BDE setup for Peer-To-Peer(Non-Dedicated) Networks} for additional information on Peer-to-Peer setup.

Another condition is when two different database engines execute on the same CPU concurrently and access data locally. This would be true when any combination of following are used concurrently: The Paradox Engine, BDE 16 bit, BDE 32 bit, Paradox for DOS. In this case each engine must set LOCAL SHARE to TRUE. Note that if use two applications which both use the same database engine (for example: Delphi 3 and C++ Builder 3) concurrently are run LOCAL SHARE does not need to be set to TRUE. In this case, all locking and cached data is in a central memory pool which all BDE applications have access to. Also, if two different database engines use data remotely, LOCAL SHARE must be set to TRUE.

Code should be used at startup to check the setting of local share. Look at the {DbiOpenCfgInfoList } BDE API function call for more information.

2. Error transmitting data from the workstation to the server.

Most commonly, this occurs with bad network hardware (cable, card, hub, etc.). This has been determined to be a problem even though there were no other errors are detected in data transmission. To determine if this is the cause for your error, try eliminating one CPU at a time from using the data and see if the problem continues.

3. Bad VREDIR.VXD on any client accessing tables Windows 95 ONLY:

Several versions (notably 4.00.1113 and 4.00.1114) of the file VREDIR.VXD may need to be updated.

Reports have shown that using the original release of VREDIR.VXD (4.00.950) and a new release (4.00.1116) do not result in the errors "Blob has been modified" and/or "Index is out of date." If any one of the clients has a "bad" version of this device driver, the error can occur on any machine, not just the machine with the bad driver.

This error most likely occurs in 16Bit versions of the Borland Database Engine, although it still can occur in 32Bit versions.

For further information on the update of VREDIR.VXD, Please check the following Microsoft Articles: {Q174371} and {Q165403}

4. For Windows 95 clients only, when using data on Windows NT: Add the following key in your registry: HKEY_LOCAL_MACHINESystemCurrentControlSetServicesVxDVredir

Then create the string or Binary Value (either one works) with a name of DiscardCacheonOpen and make it equal to 1.

Note that this an undocumented registry entry obtained from Microsoft. Questions on its functionality should be directed to Microsoft.

5. Problem with opportunistic locking Windows NT ONLY: Try turning off opportunistic locking in the Windows NT registry: See Microsoft Article {Q129202}

Note: Borland internal testing has not indicated this setting to be significant. However, some Borland customers have indicated this to solve the problem.

6. Improperly closing files such as due to loss of power or restarting a workstation or the server without closing files first may cause this problem. Paradox tables are not designed to withstand such behavior. If this is a possibility in your environment, we recommend you use a Client Server database that can recover from such conditions.

7. Extremely large numbers of indexes, especially involving Referential Integrity can cause this problem and especially when using Windows NT as the server. Borland recommends using a Client Server database under this condition. However, if you are using Windows NT as your server, switching to Novell Netware or Windows 95 as the server may resolve the problem as well.

8. The one programmatic way you can make this error occur is if you attempt to post a duplicate value to a unique, non-primary index at the same time you attempt to open the same table. This problem only occurs if local share is set to False and only occurs on local drives.
Unverified solutions
1. Windows 95 Only: Bring up the network properties screen on all Workstations and enter the netBEUI properties screen. On the advanced tab, make sure that "Set this protocol to be the default protocol" is checked.

2. Windows 95 Only: If the previous suggestion did not work, try removing the following protocols in order. Remove one at a time and then re-test your problem:
1. NETBIOS support for IPX/SPX-compatible Protocol
2. TCP/IP
3. IPX/SPX-compatible Protocol If the problem disappears, attempt to add back in all protocols except for the last one that was taken out. Again, make sure netBEUI's default protocol check box is checked.

3. Windows NT Only used as a Workstation: On the Network Bindings page of the Network Properties, set the NetBEUI Protocol to be at the top of all services. The TCP/IP stack is known for having a lot of overhead that might cause timing problems. Since NT will send requests back in the same protocol as it is sent, changing the bindings on a NT machine used as a server will have no effect.
Other resources
1. {The Delphi Magazine} has a number of interesting articles on this subject as well. See { www.itecuk.com/Delmag/Paradox.htm} for details.

Примечание от Vit:
Обычно такие ошибки возникают из-за проблем с кэшированием измений в базе данных, особенно при использовании BLOB/Memo полей и особенно при многопользовательском доступе. В простейшем случае снизить частоту возникновения этой ошибки на несколько порядков помогает вызов метода FlushBuffers после каждого изменения таблицы:

Table1.post;
Table1.FlushBuffers;



BLOBFIELD как BITMAP


BLOBFIELD как BITMAP





Сохраняем Bitmap в поле dbase с именем Icon. Icon представляет собой двоичное Blob-поле.

procedure....
var IconStream : TMemoryStream;
..
..
begin

.
.
IconStream := TMemoryStream.Create;
Image1.picture.icon.savetostream(IconStream);
(Table1.fieldbyname('Icon') as TBlobField).LoadFromStream(IconStream);
Table1.post;
IconStream.Free;
.
.
end;


** Читаем Bitmap в Timage из поля dbase с именем Icon.

procedure .....
var IconStream : TMemoryStream;
..
..
begin
.  
.  
IconStream := TMemoryStream.Create;  
(Table1.fieldbyname('Icon') as TBlobField).SaveToStream(IconStream);  
{что бы что-нибудь записать, необходимо установить позицию потока в ноль!}  
IconStream.Position := 0;  
appointment.iconimage.picture.icon.loadfromstream(iconstream);  
IconStream.Free;  
end;

Надеюсь это поможет, поскольку найти информацию в справочной системе по этой теме практически невозможно. Чтобы сделать это, я перепробовал множество способов. Я пробовал использовать TBlobField и TBlobStream, но они не смогли мне помочь (может быть из-за убогой документации borland?).

Взято из







Блокировка/Разблокировка CD-ROM


Блокировка/Разблокировка CD-ROM



Вы уж простите, что на сях... сподручней было :\
Исходный код

//заблокировать
void CMFcDlg::OnBnClickedButton1()
{
HANDLE hDevice = CreateFile ("\\\\.\\E:", 
 GENERIC_READ,
 FILE_SHARE_READ | FILE_SHARE_WRITE,
 NULL,
 OPEN_EXISTING,
 NULL,
 NULL);
DWORD dwBytesReturned = 0;
PREVENT_MEDIA_REMOVAL pmr = {TRUE};
if(!DeviceIoControl (hDevice, IOCTL_STORAGE_MEDIA_REMOVAL, &pmr, sizeof(pmr), NULL, 0, &dwBytesReturned, NULL)) AfxMessageBox ("Door can\'t be locked");
CloseHandle (hDevice);
}

//разблокировать
void CMFcDlg::OnBnClickedButton2()
{
HANDLE hDevice = CreateFile ("\\\\.\\E:", 
 GENERIC_READ,
 FILE_SHARE_READ | FILE_SHARE_WRITE,
 NULL,
 OPEN_EXISTING,
 NULL,
 NULL);
DWORD dwBytesReturned = 0;
PREVENT_MEDIA_REMOVAL pmr = {FALSE};
if(!DeviceIoControl (hDevice, IOCTL_STORAGE_MEDIA_REMOVAL, &pmr, sizeof(pmr), NULL, 0, &dwBytesReturned, NULL)) AfxMessageBox ("Door can\'t be unlocked");
CloseHandle (hDevice);

}

Автор ответа: Baa
Взято с Vingrad.ru




Блокируется таблица в MS SQL Server


Блокируется таблица в MS SQL Server




По умолчанию, оператор UPDATE в MS SQL Server пытается поставить эксклюзивную табличную блокировку. Вы можете обойти это, используя ключевое слово FROM в сочетании с опцией PAGLOCK для использования MS SQL Server страничных блокировок вместо эксклюзивной табличной блокировки:

UPDATEorders SET customer_id=NULL FROM orders(PAGLOCK) WHERE customer_id=32;

Блокиpовка на всю таблицу пpи UPDATE ставится только в том случае, если по пpедикату нет индекса. Так, можно пpосто пpоиндексиpовать таблицу orders по полю customer_id, и не забывать делать UPDATE STATISTIC, хотя будет работать и с PAGLOCK. Просто не факт, что UPDATE всегда делает табличную блокировку.

Взято из





BMP ---> AVI (для TAnimate)


BMP ---> AVI (для TAnimate)





TAnimate is a rather nice component. However if you don't want to use the built in AVI files and want to create your own AVI files from BMP files, then you may have a problem as there is no tool in Delphi to do this.

While browsing the web for information on AVI file formats I came upon a site www.shrinkwrapvb.com/avihelp/avihelp.htm that is maintained by Ray Mercer. In this tutorial he explains how to manipulate,read and write AVI files. I was particularly interested in "Step 5" in which he shows a utility that takes a list of BMP files that creates an AVI file which can be used by the TAnimate component. The only problem was that the examples are in Visual Basic, thus a conversion to Delphi was required.

I have posted this procedure
CreateAVI(const FileName : string; BMPFileList : TStrings; FramesPerSec : integer = 10);

To keep the text of the example simple and readable I have left out most to the error checking (try except etc.). You can also play with the AVISaveOptions dialog box, but I can only seem to get it to work with "Full Frames Uncompressed" with BMP files. Can anyone shed some light on this ?

Errors you should check for are ..
All files are valid BMP files and are of the same size.
All Blockreads are valid with no read errors.

Ray has a downloadable EXE that works quite nicely, however I am about to write my own utility that incorporates the following ...

Multiline file selection.
Listbox line reordering (drag/drop).
Sort File list
Layout Save and Load .
AVI Preview.

(I have beta version 1.0.0.0 ready, if anyone wants a copy of exe or source code, drop me a mail at mheydon@pgbison.co.za)

For further info on AVI files I recommend you vist Ray's site at http://www.shrinkwrapvb.com/avihelp/avihelp.htm it really is a well written tutorial (even if it is in Visual Basic)

const
// AVISaveOptions Dialog box flags

  ICMF_CHOOSE_KEYFRAME = 1; // show KeyFrame Every box
  ICMF_CHOOSE_DATARATE = 2; // show DataRate box
  ICMF_CHOOSE_PREVIEW = 4; // allow expanded preview dialog
  ICMF_CHOOSE_ALLCOMPRESSORS = 8; // don't only show those that
  // can handle the input format
  // or input data
  AVIIF_KEYFRAME = 10;

type

  AVI_COMPRESS_OPTIONS = packed record
    fccType: DWORD; // stream type, for consistency
    fccHandler: DWORD; // compressor
    dwKeyFrameEvery: DWORD; // keyframe rate
    dwQuality: DWORD; // compress quality 0-10,000
    dwBytesPerSecond: DWORD; // bytes per second
    dwFlags: DWORD; // flags... see below
    lpFormat: DWORD; // save format
    cbFormat: DWORD;
    lpParms: DWORD; // compressor options
    cbParms: DWORD;
    dwInterleaveEvery: DWORD; // for non-video streams only
  end;

  AVI_STREAM_INFO = packed record
    fccType: DWORD;
    fccHandler: DWORD;
    dwFlags: DWORD;
    dwCaps: DWORD;
    wPriority: word;
    wLanguage: word;
    dwScale: DWORD;
    dwRate: DWORD;
    dwStart: DWORD;
    dwLength: DWORD;
    dwInitialFrames: DWORD;
    dwSuggestedBufferSize: DWORD;
    dwQuality: DWORD;
    dwSampleSize: DWORD;
    rcFrame: TRect;
    dwEditCount: DWORD;
    dwFormatChangeCount: DWORD;
    szName: array[0..63] of char;
  end;

  BITMAPINFOHEADER = packed record
    biSize: DWORD;
    biWidth: DWORD;
    biHeight: DWORD;
    biPlanes: word;
    biBitCount: word;
    biCompression: DWORD;
    biSizeImage: DWORD;
    biXPelsPerMeter: DWORD;
    biYPelsPerMeter: DWORD;
    biClrUsed: DWORD;
    biClrImportant: DWORD;
  end;

  BITMAPFILEHEADER = packed record
    bfType: word; //"magic cookie" - must be "BM"
    bfSize: integer;
    bfReserved1: word;
    bfReserved2: word;
    bfOffBits: integer;
  end;

  // DLL External declarations

function AVISaveOptions(Hwnd: DWORD; uiFlags: DWORD; nStreams: DWORD;
  pPavi: Pointer; plpOptions: Pointer): boolean;
  stdcall; external 'avifil32.dll';

function AVIFileCreateStream(pFile: DWORD; pPavi: Pointer; pSi: Pointer): integer;
  stdcall; external 'avifil32.dll';

function AVIFileOpen(pPfile: Pointer; szFile: PChar; uMode: DWORD;
  clSid: DWORD): integer;
  stdcall; external 'avifil32.dll';

function AVIMakeCompressedStream(psCompressed: Pointer; psSource: DWORD;
  lpOptions: Pointer; pclsidHandler: DWORD): integer;
  stdcall; external 'avifil32.dll';

function AVIStreamSetFormat(pAvi: DWORD; lPos: DWORD; lpGormat: Pointer;
  cbFormat: DWORD): integer;
  stdcall; external 'avifil32.dll';

function AVIStreamWrite(pAvi: DWORD; lStart: DWORD; lSamples: DWORD;
  lBuffer: Pointer; cBuffer: DWORD; dwFlags: DWORD;
  plSampWritten: DWORD; plBytesWritten: DWORD): integer;
  stdcall; external 'avifil32.dll';

function AVISaveOptionsFree(nStreams: DWORD; ppOptions: Pointer): integer;
  stdcall; external 'avifil32.dll';

function AVIFileRelease(pFile: DWORD): integer; stdcall; external 'avifil32.dll';

procedure AVIFileInit; stdcall; external 'avifil32.dll';

procedure AVIFileExit; stdcall; external 'avifil32.dll';

function AVIStreamRelease(pAvi: DWORD): integer; stdcall; external 'avifil32.dll';

function mmioStringToFOURCCA(sz: PChar; uFlags: DWORD): integer;
  stdcall; external 'winmm.dll';

// ============================================================================
// Main Function to Create AVI file from BMP file listing
// ============================================================================

procedure CreateAVI(const FileName: string; IList: TStrings;
  FramesPerSec: integer = 10);
var
  Opts: AVI_COMPRESS_OPTIONS;
  pOpts: Pointer;
  pFile, ps, psCompressed: DWORD;
  strhdr: AVI_STREAM_INFO;
  i: integer;
  BFile: file;
  m_Bih: BITMAPINFOHEADER;
  m_Bfh: BITMAPFILEHEADER;
  m_MemBits: packed array of byte;
  m_MemBitMapInfo: packed array of byte;
begin
  DeleteFile(FileName);
  Fillchar(Opts, SizeOf(Opts), 0);
  FillChar(strhdr, SizeOf(strhdr), 0);
  Opts.fccHandler := 541215044; // Full frames Uncompressed
  AVIFileInit;
  pfile := 0;
  pOpts := @Opts;

  if AVIFileOpen(@pFile, PChar(FileName), OF_WRITE or OF_CREATE, 0) = 0 then
  begin
    // Determine Bitmap Properties from file item[0] in list
    AssignFile(BFile, IList[0]);
    Reset(BFile, 1);
    BlockRead(BFile, m_Bfh, SizeOf(m_Bfh));
    BlockRead(BFile, m_Bih, SizeOf(m_Bih));
    SetLength(m_MemBitMapInfo, m_bfh.bfOffBits - 14);
    SetLength(m_MemBits, m_Bih.biSizeImage);
    Seek(BFile, SizeOf(m_Bfh));
    BlockRead(BFile, m_MemBitMapInfo[0], length(m_MemBitMapInfo));
    CloseFile(BFile);

    strhdr.fccType := mmioStringToFOURCCA('vids', 0); // stream type video
    strhdr.fccHandler := 0; // def AVI handler
    strhdr.dwScale := 1;
    strhdr.dwRate := FramesPerSec; // fps 1 to 30
    strhdr.dwSuggestedBufferSize := m_Bih.biSizeImage; // size of 1 frame
    SetRect(strhdr.rcFrame, 0, 0, m_Bih.biWidth, m_Bih.biHeight);

    if AVIFileCreateStream(pFile, @ps, @strhdr) = 0 then
    begin
      // if you want user selection options then call following line
      // (but seems to only like "Full frames Uncompressed option)

      // AVISaveOptions(Application.Handle,
      //                ICMF_CHOOSE_KEYFRAME or ICMF_CHOOSE_DATARATE,
      //                1,@ps,@pOpts);
      // AVISaveOptionsFree(1,@pOpts);

      if AVIMakeCompressedStream(@psCompressed, ps, @opts, 0) = 0 then
      begin
        if AVIStreamSetFormat(psCompressed, 0, @m_memBitmapInfo[0],
          length(m_MemBitMapInfo)) = 0 then
        begin

          for i := 0 to IList.Count - 1 do
          begin
            AssignFile(BFile, IList[i]);
            Reset(BFile, 1);
            Seek(BFile, m_bfh.bfOffBits);
            BlockRead(BFile, m_MemBits[0], m_Bih.biSizeImage);
            Seek(BFile, SizeOf(m_Bfh));
            BlockRead(BFile, m_MemBitMapInfo[0], length(m_MemBitMapInfo));
            CloseFile(BFile);
            if AVIStreamWrite(psCompressed, i, 1, @m_MemBits[0],
              m_Bih.biSizeImage, AVIIF_KEYFRAME, 0, 0) <> 0 then
            begin
              ShowMessage('Error during Write AVI File');
              break;
            end;
          end;
        end;
      end;
    end;

    AVIStreamRelease(ps);
    AVIStreamRelease(psCompressed);
    AVIFileRelease(pFile);
  end;

  AVIFileExit;
  m_MemBitMapInfo := nil;
  m_memBits := nil;
end;

Взято с

Delphi Knowledge Base






BMP ---> DIB


BMP ---> DIB




Если файл хранится в формате BMP, как мне преобразовать его в DIB и как затем отобразить?

Это не тривиально, но помочь нам смогут функции GetDIBSizes и GetDIB из модуля GRAPHICS.PAS. Приведу две процедуры: одну для создания DIB из TBitmap и вторую для его освобождения:



{Преобразование TBitmap в DIB }

procedure BitmapToDIB(Bitmap: TBitmap;
  var BitmapInfo: PBitmapInfo;
  var InfoSize: integer;
  var Bits: pointer;
  var BitsSize: longint);
begin
  BitmapInfo := nil;
  InfoSize := 0;
  Bits := nil;
  BitsSize := 0;
  if not Bitmap.Empty then
  try
    GetDIBSizes(Bitmap.Handle, InfoSize, BitsSize);
    GetMem(BitmapInfo, InfoSize);
    Bits := GlobalAllocPtr(GMEM_MOVEABLE, BitsSize);
    if Bits = nil then
      raise
        EOutOfMemory.Create('Не хватает памяти для пикселей изображения');
    if not GetDIB(Bitmap.Handle, Bitmap.Palette, BitmapInfo^, Bits^) then
      raise Exception.Create('Не могу создать DIB');
  except
    if BitmapInfo <> nil then
      FreeMem(BitmapInfo, InfoSize);
    if Bits <> nil then
      GlobalFreePtr(Bits);
    BitmapInfo := nil;
    Bits := nil;
    raise;
  end;
end;

{ используйте FreeDIB для освобождения информации об изображении и битовых указателей }

procedure FreeDIB(BitmapInfo: PBitmapInfo;
  InfoSize: integer;
  Bits: pointer;
  BitsSize: longint);
begin
  if BitmapInfo <> nil then
    FreeMem(BitmapInfo, InfoSize);
  if Bits <> nil then
    GlobalFreePtr(Bits);
end;




Создаем форму с TImage Image1 и загружаем в него 256-цветное изображение, затем рядом размещаем TPaintBox. Добавляем следующие строчки к private-объявлениям вашей формы:



{ Private declarations }
BitmapInfo : PBitmapInfo ;
InfoSize   : integer ;
Bits       : pointer ;
BitsSize   : longint ;




Создаем нижеприведенные обработчики событий, которые демонстрируют процесс отрисовки DIB:



procedure TForm1.FormCreate(Sender: TObject);
begin
  BitmapToDIB(Image1.Picture.Bitmap, BitmapInfo, InfoSize,
    Bits, BitsSize);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeDIB(BitmapInfo, InfoSize, Bits, BitsSize);
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  OldPalette: HPalette;
begin
  if Assigned(BitmapInfo) and Assigned(Bits) then
    with BitmapInfo^.bmiHeader, PaintBox1.Canvas do
    begin
      OldPalette := SelectPalette(Handle,
        Image1.Picture.Bitmap.Palette,
        false);
      try
        RealizePalette(Handle);
        StretchDIBits(Handle, 0, 0, PaintBox1.Width, PaintBox1.Height,
          0, 0, biWidth, biHeight, Bits,
          BitmapInfo^, DIB_RGB_COLORS,
          SRCCOPY);
      finally
        SelectPalette(Handle, OldPalette, true);
      end;
    end;
end;




Это поможет вам сделать первый шаг. Единственное, что вы можете захотеть, это создание собственного HPalette на основе DIB, вместо использования TBitmap и своей палитры. Функция с именем PaletteFromW3DIB из GRAPHICS.PAS как раз этим и занимается, но она не объявлена в качестве экспортируемой, поэтому для ее использования необходимо скопировать ее исходный код и вставить его в ваш модуль.

Взято с






BMP ---> EMF


BMP ---> EMF





function bmp2emf(const SourceFileName: TFileName): Boolean; 
// Converts a Bitmap to a Enhanced Metafile (*.emf) 
var 
  Metafile: TMetafile; 
  MetaCanvas: TMetafileCanvas; 
  Bitmap: TBitmap; 
begin 
  Metafile := TMetaFile.Create; 
  try 
    Bitmap := TBitmap.Create; 
    try 
      Bitmap.LoadFromFile(SourceFileName); 
      Metafile.Height := Bitmap.Height; 
      Metafile.Width  := Bitmap.Width; 
      MetaCanvas := TMetafileCanvas.Create(Metafile, 0); 
      try 
        MetaCanvas.Draw(0, 0, Bitmap); 
      finally 
        MetaCanvas.Free; 
      end; 
    finally 
      Bitmap.Free; 
    end; 
    Metafile.SaveToFile(ChangeFileExt(SourceFileName, '.emf')); 
  finally 
    Metafile.Free; 
  end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  bmp2emf('C:\TestBitmap.bmp'); 
end; 

Взято с сайта



BMP ---> ICO


BMP ---> ICO



Автор: Bernhard Angerer

Вам необходимо создать два битмапа, битмап маски (назовём его "AND" bitmap) и битмап изображения (назовём его XOR bitmap). Вы можете пропустить обработчики для "AND" и "XOR" битмапов в Windows API функции CreateIconIndirect() и использовать обработчик возвращённой иконки в Вашем приложении.

procedureTForm1.Button1Click(Sender: TObject); 
var 
  IconSizeX : integer; 
  IconSizeY : integer; 
  AndMask : TBitmap; 
  XOrMask : TBitmap; 
  IconInfo : TIconInfo; 
  Icon : TIcon; 
begin 
{Получаем размер иконки} 
  IconSizeX := GetSystemMetrics(SM_CXICON); 
  IconSizeY := GetSystemMetrics(SM_CYICON); 

{Создаём маску "And"} 
  AndMask := TBitmap.Create; 
  AndMask.Monochrome := true; 
  AndMask.Width := IconSizeX; 
  AndMask.Height := IconSizeY; 

{Рисуем на маске "And"} 
  AndMask.Canvas.Brush.Color := clWhite; 
  AndMask.Canvas.FillRect(Rect(0, 0, IconSizeX, IconSizeY)); 
  AndMask.Canvas.Brush.Color := clBlack; 
  AndMask.Canvas.Ellipse(4, 4, IconSizeX - 4, IconSizeY - 4); 

{Рисуем для теста} 
  Form1.Canvas.Draw(IconSizeX * 2, IconSizeY, AndMask); 

{Создаём маску "XOr"} 
  XOrMask := TBitmap.Create; 
  XOrMask.Width := IconSizeX; 
  XOrMask.Height := IconSizeY; 

{Рисуем на маске "XOr"} 
  XOrMask.Canvas.Brush.Color := ClBlack; 
  XOrMask.Canvas.FillRect(Rect(0, 0, IconSizeX, IconSizeY)); 
  XOrMask.Canvas.Pen.Color := clRed; 
  XOrMask.Canvas.Brush.Color := clRed; 
  XOrMask.Canvas.Ellipse(4, 4, IconSizeX - 4, IconSizeY - 4); 

{Рисуем в качестве теста} 
  Form1.Canvas.Draw(IconSizeX * 4, IconSizeY, XOrMask); 

{Создаём иконку} 
  Icon := TIcon.Create; 
  IconInfo.fIcon := true; 
  IconInfo.xHotspot := 0; 
  IconInfo.yHotspot := 0; 
  IconInfo.hbmMask := AndMask.Handle; 
  IconInfo.hbmColor := XOrMask.Handle; 
  Icon.Handle := CreateIconIndirect(IconInfo); 

{Уничтожаем временные битмапы} 
  AndMask.Free; 
  XOrMask.Free; 

{Рисуем в качестве теста} 
  Form1.Canvas.Draw(IconSizeX * 6, IconSizeY, Icon); 

{Объявляем иконку в качестве иконки приложения} 
  Application.Icon := Icon; 

{генерируем перерисовку} 
  InvalidateRect(Application.Handle, nil, true); 

{Освобождаем иконку} 
  Icon.Free; 
end; 

Взято с Исходников.ru


Способ преобразования изображения размером 32x32 в иконку.



unit main;

interface

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs, ExtCtrls, StdCtrls;

type

  TForm1 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    Image2: TImage;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var

  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  winDC, srcdc, destdc: HDC;

  oldBitmap: HBitmap;
  iinfo: TICONINFO;
begin

  GetIconInfo(Image1.Picture.Icon.Handle, iinfo);

  WinDC := getDC(handle);
  srcDC := CreateCompatibleDC(WinDC);
  destDC := CreateCompatibleDC(WinDC);
  oldBitmap := SelectObject(destDC, iinfo.hbmColor);
  oldBitmap := SelectObject(srcDC, iinfo.hbmMask);

  BitBlt(destdc, 0, 0, Image1.picture.icon.width,
    Image1.picture.icon.height,
    srcdc, 0, 0, SRCPAINT);
  Image2.picture.bitmap.handle := SelectObject(destDC, oldBitmap);
  DeleteDC(destDC);
  DeleteDC(srcDC);
  DeleteDC(WinDC);

  image2.Picture.Bitmap.savetofile(ExtractFilePath(Application.ExeName)
    + 'myfile.bmp');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin

  image1.picture.icon.loadfromfile('c:\myicon.ico');
end;

end.

Взято из






BMP ---> JPG


BMP ---> JPG





uses 
  Jpeg, ClipBrd; 

procedure TfrmMain.ConvertBMP2JPEG; 
  // converts a bitmap, the graphic of a TChart for example, to a jpeg 
var  
  jpgImg: TJPEGImage; 
begin 
  // copy bitmap to clipboard 
  chrtOutputSingle.CopyToClipboardBitmap; 
  // get clipboard and load it to Image1 
  Image1.Picture.Bitmap.LoadFromClipboardFormat(cf_BitMap, 
    ClipBoard.GetAsHandle(cf_Bitmap), 0); 
  // create the jpeg-graphic 
  jpgImg := TJPEGImage.Create; 
  // assign the bitmap to the jpeg, this converts the bitmap 
  jpgImg.Assign(Image1.Picture.Bitmap); 
  // and save it to file 
  jpgImg.SaveToFile('TChartExample.jpg'); 
end; 

Взято с сайта



BMP ---> RTF


BMP ---> RTF





function BitmapToRTF(pict: TBitmap): string; 
var 
  bi, bb, rtf: string; 
  bis, bbs: Cardinal; 
  achar: ShortString; 
  hexpict: string; 
  I: Integer; 
begin 
  GetDIBSizes(pict.Handle, bis, bbs); 
  SetLength(bi, bis); 
  SetLength(bb, bbs); 
  GetDIB(pict.Handle, pict.Palette, PChar(bi)^, PChar(bb)^); 
  rtf := '{\rtf1 {\pict\dibitmap0 '; 
  SetLength(hexpict, (Length(bb) + Length(bi)) * 2); 
  I := 2; 
  for bis := 1 to Length(bi) do 
  begin 
    achar := IntToHex(Integer(bi[bis]), 2); 
    hexpict[I - 1] := achar[1]; 
    hexpict[I] := achar[2]; 
    Inc(I, 2); 
  end; 
  for bbs := 1 to Length(bb) do 
  begin 
    achar := IntToHex(Integer(bb[bbs]), 2); 
    hexpict[I - 1] := achar[1]; 
    hexpict[I] := achar[2]; 
    Inc(I, 2); 
  end; 
  rtf := rtf + hexpict + ' }}'; 
  Result := rtf; 
end; 

Взято с сайта



BMP ---> WMF


BMP ---> WMF



procedure ConvertBMP2WMF
(const BMPFileName, WMFFileName: TFileName); 
var 
  MetaFile : TMetafile; 
  Bitmap : TBitmap; 
begin 
  Metafile := TMetaFile.Create; 
  Bitmap := TBitmap.Create; 
  try 
    Bitmap.LoadFromFile(BMPFileName); 
    with MetaFile do 
    begin 
      Height := Bitmap.Height; 
      Width  := Bitmap.Width; 
      Canvas.Draw(0, 0, Bitmap); 
      SaveToFile(WMFFileName); 
    end; 
  finally
      Bitmap.Free; 
    MetaFile.Free; 
  end; 
end;

Использование:

ConvertBMP2WMF('c:\mypic.bmp','c:\mypic.wmf')

Взято с Исходников.ru




Более быстрый способ добавлять пункты меню


Более быстрый способ добавлять пункты меню



Обычно, когда Вы создаёте меню в приложении, то код выглядит примерно так:

    PopupMenu1 := TPopupMenu.Create(Self); 
    Item := TMenuItem.Create(PopupMenu1); 
    Item.Caption := 'First Menu'; 
    Item.OnClick := MenuItem1Click; 
    PopupMenu1.Items.Add(Item); 
    Item := TMenuItem.Create(PopupMenu1); 
    Item.Caption := 'Second Menu'; 
    Item.OnClick := MenuItem2Click; 
    PopupMenu1.Items.Add(Item); 
    Item := TMenuItem.Create(PopupMenu1); 
    Item.Caption := 'Third Menu'; 
    Item.OnClick := MenuItem3Click; 
    PopupMenu1.Items.Add(Item); 

    Item := TMenuItem.Create(PopupMenu1); 
    Item.Caption := '-'; 
    PopupMenu1.Items.Add(Item); 
    Item := TMenuItem.Create(PopupMenu1); 
    Item.Caption := 'Fourth Menu'; 
    Item.OnClick := MenuItem4Click; 
    PopupMenu1.Items.Add(Item); 


Однако есть более быстрый способ! Воспользуйтесь функциями NewItem и NewLine:

    PopupMenu1 := TPopupMenu.Create(Self); 
    with PopUpMenu1.Items do 
      begin 
        Add(NewItem('First Menu',0,False,True,MenuItem1Click,0,'MenuItem1')); 
        Add(NewItem('Second Menu',0,False,True,MenuItem2Click,0,'MenuItem2')); 
        Add(NewItem('Third Menu',0,False,True,MenuItem3Click,0,'MenuItem3')); 
        Add(NewLine);                        // Добавляем разделитель
        Add(NewItem('Fourth Menu',0,False,True,MenuItem4Click,0,'MenuItem4')); 

      end;

Взято с Исходников.ru




Borland Delphi 7 - миграция в сторону .Net


Borland Delphi 7 - миграция в сторону .Net




Borland Delphi 7 - миграция в сторону .Net

Автор: Виталий Чужа
Qui non proficit, deficit. Теряет тот, кто не идет вперед

Delphi 7 Studio позиционируется как первый независимый инструмент для облегчения миграции к платформе .Net
Итак, перед нами очередная версия знаменитого продукта фирмы Borland - Delphi 7 Studio, о выходе которого было сообщено в пресс-релизе компании от 6 августа 2002 года. Новая версия Delphi позиционируется как первый независимый инструмент для облегчения миграции к платформе .Net и, будучи доступна с лета 2002 года, поставляется в четырех редакциях: Architect, Enterprise, Professional и Personal. В шестой версии, как вы помните, отсутствовала редакция Architect, да и само понятие (студии). Также нужно заметить, что, хотя Delphi несколько <потяжелела> и изменился перечень поддерживаемых операционных систем, системные требования Delphi 6 и Delphi 7 версий Enterprise, в основном, остались прежними.
Для версии Architect, которая является самой полной и дорогой (99) редакцией, требования к ПК выше - для полной установки ей требуется 540 Мб пространства на жестком диске. Цены на <стандартные> версии, по сравнению с Delphi 6, не изменились: Enterprise стоит 99, Professional - 9 .
Какие же новые возможности были включены в Delphi 7 Studio? Рассмотрим их по порядку.
Среда разработки
Изменения, затронувшие IDE, коснулись палитры компонент, достройщика кода, отладчика и настроек редактора кода. В палитре компонент появились следующие закладки: новая версия закладки System только для CLX-приложений, закладки Indy Intercepts и Indy I/O Handlers, содержащие компоненты с поддержкой протоколов интернет с открытым исходным кодом (редакции Professional и Enterprise). Для разработки веб-приложений - новые закладки IW Standard, IW Data, IW Client Side, и IW Control с компонентами IntraWeb, а также новая закладка Rave с компонентами генерации отчетов. Кроме того, если закладка содержит компоненты, для доступа к которым необходима горизонтальная прокрутка, то теперь добраться до них можно и с помощью ниспадающего меню.
Достройщик кода (code completion) теперь работает быстрее и позволяет перейти к объявлениям элементов через их список путем нажатия клавиши <Ctrl> и клика мышью на любом идентификаторе в списке. Появился новый достройщик HTML-кода, который автоматически отображает нужные HTML-элементы и атрибуты в редакторе кода (для редакций Professional и Enterprise). Для удобства работы через меню Tools р Editor Options р Code Insight можно настроить цвета, используемые достройщиком кода. Также необходимо отметить возможность написания собственных менеджеров завершения кода.
Окно просмотра сообщений отладчика (Watch List) обзавелось множеством закладок для облегчения процесса отлова ошибок. Каждую закладку можно настроить - отображать ее или спрятать. Диалоговое окно Run Parameters теперь имеет новую настройку: рабочий каталог (Working Directory), указав который, можно настроить каталог, используемый для отладки.
Из Project Manager можно компилировать лишь часть проектов в группе, щелкнув правой кнопкой по проекту и выбрав пункты меню Make All from Here или Build All from Here, а в окне просмотра сообщений (Message view) появилось множество закладок для отображения разных типов сообщений (Build, Search, и т. д.) В окне, доступном через меню View р Component List, можно выбирать несколько компонент с помощью клавиши <Ctrl>. Окно настроек редактора кода, доступное через меню Tools р Editor Options р Source Options, позволяет устанавливать различные настройки для языков Pascal, C++, C#, HTML, XML, контролировать отображение знаков пробела и табуляции, редактировать шаблоны кода. Окно, доступное через меню Tools р Editor Options р Color, имеет две новые настройки: цвет символа (Foreground Color) и цвет фона (Background Color) - вместо цветовой сетки для настройки цвета в редакторе кода.
Веб-технологии
В седьмую версию Delphi вошел набор компонент IntraWeb от AtoZed Software, который может быть использован для написания приложений веб-сервера с использованием стандартного инструментария разработки форм. IntraWeb также годится для разработки страниц Web Broker и WebSnap приложений. Полная версия IntraWeb входит в состав редакции Delphi Enterprise. Delphi также поддерживает Apache 2 - как целевой тип для Web Broker, WebSnap и SOAP. В то же время Borland не рекомендует использовать Win-CGI для приложений веб-сервера или веб-сервисов. Вместо этого рекомендуется использовать CGI, ISAPI/NSAPI, или Apache.
Веб-сервисы
Появился новый UDDI (Universal Description, Discovery, and Integration) браузер у волшебника импорта WSDL, который позволяет сканировать реестр UDDI для поиска веб-сервиса и импорта адреса WSDL документа. Сам реестр UDDI является базой данных, в которой регистрируются компании, поставляющие веб-сервисы. Новые классы и интерфейсы позволяют читать или вставлять заголовки в SOAP-конверты, пересылающие сообщения между клиентом и сервером. Приложения веб-сервисов (как клиентов, так и серверов) теперь в состоянии обрабатывать вложения. Вложения (наследники класса TSOAPAttachment) отсылаются вместе с закодированными сообщениями SOAP как часть составной формы. Когда приложение получает сообщение с вложением, оно сохраняет вложение во временном файле, доступном вашей программе.
Новые события, обрабатываемые компонентом THTTPReqResp, позволят вам перехватывать сообщения HTTP до их отсылки и отслеживать ход получения или отсылки длинных сообщений. В классе THTTPSoapPascalInvoker доступны сообщения, которые позволят написать код, исполняемый до или после того, как объект класса осуществит вызов запрашиваемого метода. Интерфейс IOPConvert получил новое свойство Encoding, что позволяет указать набор символов для использования в сообщениях, передаваемых между клиентом поставщиком веб-сервиса.
Базы данных
Обновлены драйвера dbExpress для Informix SE, Oracle 9i, DB2 7.2, InterBase 6.5 и MySQL 3.23.49. Новый драйвер поставляется и для MS SQL Server 2000. А вот SQL Links Borland не рекомендует использовать, более того - работа над усовершенствованием SQL Links прекращается. Сообщается также, что эта технология не будет поставляться вместе с Delphi после 2002 года. В виде замены рекомендовано использовать dbExpress для доступа к базам данных SQL серверов.
Прекращена также поддержка CORBA-соединений компонентами DataSnap.
Библиотека компонент
Приложения, написанные с использованием VCL, теперь включают компоненты, поддерживающие библиотеку элементов управления Windows шестой версии. Поэтому приложение будет автоматически использовать новые элементы управления Windows в ОС Windows XP, если найдет подходящий файл-манифест.
Новый модуль DBClientActns включает три новых компонента для работы с клиентскими наборами данных: TClientDataSetApply, TclientDataSetUndo и TClientDataSetRevert.
Закладка dbExpress включает новый компонент TSimpleDataSet для использования с простыми, двухуровневыми приложениями баз данных (TSimpleDataSet заменил собой TSQLClientDataSet). Обновлена закладка Dialogs на палитре компонент - добавлен TPageSetupDialog для представления стандартного диалогового окна Windows настройки параметров страницы. На закладку Additional добавлены компоненты TXPColorMap, TstandardColorMap и TtwilightColorMap для окраски меню и панелей инструментов.
У VCL-версии компонента TCustomForm добавились два новых свойства: ScreenSnap и SnapBuffer, контролирующие <прилипание> окна к краям экрана. Компонент TCustomComboBoxEx получил новое свойство AutoCompleteOptions, которое позволяет откликаться на ввод пользователя.
Библиотека времени выполнения
Модуль Classes содержит новый класс-исключение EFileStreamError. Классы EFCreateError и EFOpenError являются наследниками этого класса. Поскольку конструктор этого класса принимает имя файла как параметр, то в сообщении об исключительной ситуации можно видеть имя файла, в котором она произошла.
Класс TStrings также обладет теперь двумя новыми свойствами: ValueFromIndex и NameValueSeparator.
В модуле StrUtils также произошли определенные изменения, касающиеся работы с многобайтными наборами символов. Ранее функции LeftStr, RightStr и MidStr принимали параметр типа AnsiString и возвращали значение того же типа, не поддерживая многобайтные наборы символов. Теперь каждая из этих функций заменена парой перегруженных функций, одна из которых работает с типом AnsiString, а другая - с типом WideString. Также в модуль добавлена новая функция для поиска в строке, именуемая PosEx.
В модуле SysUtils функции, работающие над форматированием и разбором чисел, валют и значений типа дата и время, заменены на безопасные при работе с нитями.
Модуль VarCmplx содержит новые функции VarComplexLog2, VarComplexLog10, VarComplexLogN, VarComplexTimesImaginary и VarComplexTimesReal.
В модуль Variants добавлены функции VarIsError и VarAsError. Исключение EVariantError теперь является родительским классом для более тщательно разработанных классов-исключений, которые используются в коде с использованием переменных типа variant.
Компилятор
Компилятор Delphi поддерживает три дополнительных предупреждения: Unsafe_Type, Unsafe_Code и Unsafe_Cast. Эти предупреждения по умолчанию отключены, однако их можно задействовать с помощью директив компилятора {$WARN UNSAFE_CODE ON}, команды компилятора командной строки (dcc32 -W+UNSAFE_CODE), или посредством среды разработки, воспользовавшись меню Project р Options р Compiler Messages. Эта особенность должна помочь вам портировать код в окружение управляемого выполнения платформы Microsoft .NET. В этом окружении значит, что действия, выполняемые программой, не могут быть проверены во время анализа, осуществляемого Just In Time (JIT) компилятором. Такой код представляется небезопасным. Примером такого кода могут послужить операции с указателями.
Поддержка Rave Reports (для редакции Professional и Enterprise)
Вместе с Delphi теперь поставляется набор компонент для генерации отчетов Rave Reports фирмы Nevrona. Полное его название - Rave 4.0 Borland Edition (BE). Включает 19 компонентов, содержащих более 500 методов, свойств и событий. Компоненты компилируются в ехе-файл приложения и не требуют для работы никаких дополнительных файлов. В генератор отчетов включена поддержка графики, выравнивания и переноса текста, точное позиционирование страницы, конфигурирование принтера, управление шрифтами, полнофункциональный предпросмотр. Rave 4.0 BE справляется и с отчетами вида master-detail, письмами, счетами и т. д. (рис. 1)
Поддержка ModelMaker (для редакции Professional и Enterprise)
ModelMaker призван помочь упростить дизайн, разработку и поддержку классов и интерфейсов. ModelMaker также включает инструменты для создания диаграмм в стиле UML (Unified Modeling Language), которые могут быть использованы для создания и модификации исходного кода проекта.
Отмечу, что версия Delphi Enterprise включает полноценную версию ModelMaker, а Delphi Professional - лишь 30-дневную пробную версию, хотя функциональность обоих версий одинакова.
Заключение
Несмотря на множество нововведений в этой версии Borland Delphi, можно отметить, как минимум, три важные тенденции.
Первая - сворачивание собственных технологий, таких как Borland Database Engine (BDE) и SQL Links. Кажется вероятным отказ от набора компонент Quick Reports, успешно поставлявшихся с несколькими последними версиями Delphi.
Вторая - ставшая уже традиционной поддержка написания приложений для Linux.
Третья - на мой взгляд, более важная - постепенный отход ведущих средств разработки от платформы Win32 и их миграция в сторону платформы .Net. И хотя, как сказано в пресс-релизе Borland, за одну ночь новая платформа не изменит технологию разработки и распространения приложений, однако платформа .Net - следующая, эволюционная ступень Windows, приход которой неизбежен. Принимая во внимание тот факт, что разработчики в основной своей массе люди инертные, а также то, что на изучение новых технологий необходимо довольно много времени и средств, Borland сделала ставку на необходимость эволюционного развития Delphi и, на мой взгляд, не ошиблась. Включение в эту версию подсказок и предупреждений компилятора, касающихся совместимости с Microsoft .Net, возможности импорта узлов (assembly) .Net в Delphi и экспорта COM объектов в приложения .Net, подтверждает сказанное выше. Полноценная же поддержка этой многообещающей платформы наверняка будет реализована в следующей версии Delphi - Delphi .Net, которую и будем с нетерпением ждать.

Взято с сайта

Буфер обмена (Clipboard) и TMemoryStream


Буфер обмена (Clipboard) и TMemoryStream



Обычно, это нужно для того, чтобы запихнуть в буфер обмена данные собственного формата. Сначала необходимо зарегистрировать этот формат при помощи функции RegisterClipboardFormat():

CF_MYFORMAT := RegisterClipboardFormat('My Format Description'); 

Затем необходимо проделать следующие шаги:
1. Создать поток (stream) и записать в него данные.
2. Создать в памяти глобальный буфер и скопировать в него поток (stream).
3. При помощи Clipboard.SetAsHandle() поместить глобальный буфер в буфер обмена.

Пример:

var
  hbuf    : THandle;
  bufptr  : Pointer;
  mstream : TMemoryStream;
begin
  mstream := TMemoryStream.Create;
  try
    {-- Записываем данные в mstream. --}
    hbuf := GlobalAlloc(GMEM_MOVEABLE, mstream.size);
    try
      bufptr := GlobalLock(hbuf);
      try
        Move(mstream.Memory^, bufptr^, mstream.size);
        Clipboard.SetAsHandle(CF_MYFORMAT, hbuf);
      finally
        GlobalUnlock(hbuf);
      end;
    except
      GlobalFree(hbuf);
      raise;
    end;
  finally
    mstream.Free;
  end;
end;

ВАЖНО: Не удаляйте буфер после GlobalAlloc(). Как только Вы поместите его в буфер обмена, то буфер обмена будет пользоваться им.

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

var
  hbuf    : THandle;
  bufptr  : Pointer;
  mstream : TMemoryStream;
begin
  hbuf := Clipboard.GetAsHandle(CF_MYFORMAT);
  if hbuf <> 0 then begin
    bufptr := GlobalLock(hbuf);
    if bufptr <> nil then begin
      try
        mstream := TMemoryStream.Create;
        try
          mstream.WriteBuffer(bufptr^, GlobalSize(hbuf));
          mstream.Position := 0;
          {-- Читаем данные из mstream. --}
        finally
          mstream.Free;
        end;
      finally
        GlobalUnlock(hbuf);
      end;
    end;
  end;
end;

Взято с Исходников.ru



Буффер обмена


Буффер обмена



Cодержание раздела:

















См. также статьи в других разделах:






Button, SpeedButton, BitBtn


Button, SpeedButton, BitBtn



Cодержание раздела:
















Быстрая обработка CSV файла


Быстрая обработка CSV файла





Классы Tstrings/TStringlist имеют свойство commatext, которое автоматически разделяет строки, содержащие разделители, на отдельные части. Пример показывает как считать CSV файл. В Конечном итоге, автоматически разделённые строки содержатся в TStringlist.

var
ts: tstringlist;
  S: string;
  Tf: Textfile;
begin
  Ts := Tstringlist.create;
  Assignfile(tf, 'filename');
  Reset(tf);
  while not eof(tf) do
  begin
    Readln(tf,S);
    Ts.CommaText := S;
    //ProcessLine;
  end;
  closefile(tf);
  ts.free;
end;

Так же операцию можно производить в обратном порядке.

Свойство Commatext поддерживает разделители как в виде запятых, так и двойных кавычек: 1,2,3,4 и "1","2","3","4"

Например, строка вида "1","2,3","4" будет разделена на три элемента, которые заключены в кавычки (средняя запятая будет проигнорирована). Чтобы включить кавычку в конечный результ, нужно поставить две кавычки подряд: "1",""2" (результат будет 1 и "2 ).

Взято из







Быстрое копирование таблиц


Быстрое копирование таблиц



Из книги Стива Тейксейра и Пачеко 'Delphi 4. Руководство разработчика'
я взял функцию для быстрого копирования
таблиц вместе со всеми дополнительными файлами:
Вот она:

procedure QuickCopyTable(T: TTable;DestTblName:string;Overwrite: boolean);
// только для не SQL-ых, т.е не промышленных  БД (dBase, Paradox ..)
var DBType: DBIName;
   WasOpen:boolean;
   NumCopied:word;
begin
 WasOpen:=T.Active;
 if not WasOpen then T.Open;
 Check(DbiGetProp(hDBIObj(T.Handle),drvDRIVERTYPE,@DBType,SizeOf(DBINAME),
    NumCopied));
 Check(DbiCopyTable(T.DBHandle, Overwrite, PChar(T.TableName),DBType, PChar(DestTblName)));
 T.Active:=WasOpen;
end;

Взято с сайта



Быстрое сравнение памяти


Быстрое сравнение памяти




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

functionKeys_are_Equal(var OldRec, NewRec; KeyLn: word): boolean; assembler;
asm
PUSH    DS  
MOV     AL,01  
CLD  
LES     DI,NewRec  
LDS     SI,OldRec  
MOV     CX,KeyLn  
CLI  
REPE    CMPSB  
STI  
JZ      @1  
XOR     AL,AL  
@1:  
POP     DS  
end;

function First_Key_is_Less(var NewRec, OldRec; Keyln : word): boolean; assembler;
asm
PUSH    DS  
MOV     AL,01  
CLD  
LES     DI,NewRec  
LDS     SI,OldRec  
MOV     CX,KeyLn  
CLI  
REPE    CMPSB  
STI  
JZ      @5  
JGE     @6  
@5: XOR     AL,AL  
@6: POP     DS  
end; 

- Dennis Passmore

Взято из

Советов по Delphi от


Сборник Kuliba






Быстрый доступ к ADO


Быстрый доступ к ADO




unitADO;
{This unit provides a quick access into ADO
      It handles all it's own exceptions
      It assumes it is working with SQL Server, on a PLC Database
         If an exception is thrown with a [PLCErr] suffix:
               the suffix is removed, and ErrMsg is set to the remaining string
             otherwise
               the whole exception is reported in ErrMsg
             Either way, the function call fails.

      Globals: adocn     - connection which all other ADO objects use
               adors     - Recordset
               adocmd    - Command Object
               adocmdprm - Command Object set aside for Parametric querying
               ConnectionString
                         - Connection String used for connecting

               ErrMsg    - Last Error Message
               ADOActive - Indicator as to whether ADO has been started yet

Functions:
General ADO
           ADOStart:Boolean;
           ADOReset:Boolean;
           ADOStop:Boolean;

Recordsets
           RSOpen(SQL:string;adRSType,adLockType,adCmdType:integer;UseServer:Boolean):Boolean;
           RSClose:Boolean;

Normal Command Procedures
           CMDExec(SQL:string;adCmdType:integer):Boolean;

Parametric Procedures
           PRMClear:Boolean;
           PRMSetSP(StoredProcedure:string;WithClear:Boolean):Boolean;
           PRMAdd(ParamName:string;ParamType,ParamIO,ParamSize:integer;Val:variant):Boolean;
           PRMSetParamVal(ParamName:string;val:variant):Boolean;
           PRMGetParamVal(ParamName:string;var val:variant):Boolean;

Field Operations
           function SQLStr(str:string;SQLStrType:TSQLStrType);
           function SentenceCase(str:string):string;

           --to convert from 'FIELD_NAME' -> 'Field Name' call
           SQLStr(SentenceCase(txt),ssFromSQL);
}

interface

uses OLEAuto, sysutils;

const
  {Param Data Types}
  adInteger = 3;
  adSingle = 4;
  adDate = 7;
  adBoolean = 11;
  adTinyInt = 16;
  adUnsignedTinyInt = 17;
  adDateTime = 135;
  advarChar = 200;

  {Param Directions}
  adParamInput = 1;
  adParamOutput = 2;
  adParamReturnValue = 4;

  {Command Types}
  adCmdText = 1;
  adCmdTable = 2;
  adCmdStoredProc = 4;
  adCmdTableDirect = 512;
  adCmdFile = 256;

  {Cursor/RS Types}
  adOpenForwardOnly = 0;
  adOpenKeyset = 1;
  adOpenDynamic = 2;
  adOpenStatic = 3;

  {Lock Types}
  adLockReadOnly = 1;
  adLockOptimistic = 3;

  {Cursor Locations}
  adUseServer = 2;
  adUseClient = 3;

function ADOReset: Boolean;
function ADOStop: Boolean;

function RSOpen(SQL: string; adRSType, adLockType, adCmdType: integer;
  UseServer: Boolean): Boolean;
function RSClose: Boolean;

function CMDExec(SQL: string; adCmdType: integer): Boolean;

function PRMClear: Boolean;
function PRMSetSP(StoredProcedure: string; WithClear: Boolean): Boolean;
function PRMAdd(ParamName: string; ParamType, ParamIO, ParamSize: integer; Val:
  variant): Boolean;
function PRMSetParamVal(ParamName: string; val: variant): Boolean;
function PRMGetParamVal(ParamName: string; var val: variant): Boolean;

type
  TSQLStrType = (ssToSQL, ssFromSQL);
function SQLStr(str: string; SQLStrType: TSQLStrType): string;
function SentenceCase(str: string): string;

var
  adocn, adors, adocmd, adocmdPrm: variant;
  ConnectionString, ErrMsg: string;
  ADOActive: boolean = false;

implementation

var
  UsingConnection: Boolean;

function ADOStart: Boolean;
begin
  //Get the Object References
  try
    adocn := CreateOLEObject('ADODB.Connection');
    adors := CreateOLEObject('ADODB.Recordset');
    adocmd := CreateOLEObject('ADODB.Command');
    adocmdprm := CreateOLEObject('ADODB.Command');
    result := true;
  except
    on E: Exception do
    begin
      ErrMsg := e.message;
      Result := false;
    end;
  end;
  ADOActive := result;
end;

function ADOReset: Boolean;
begin
  Result := false;
  //Ensure a clean slate...
  if not (ADOStop) then
    exit;

  //Restart all the ADO References
  if not (ADOStart) then
    exit;

  //Wire up the Connections
  //If the ADOconnetion fails, all objects will use the connection string
  //                               directly - poorer performance, but it works!!
  try
    adocn.ConnectionString := ConnectionString;
    adocn.open;
    adors.activeconnection := adocn;
    adocmd.activeconnection := adocn;
    adocmdprm.activeconnection := adocn;
    UsingConnection := true;
  except
    try
      adocn := unassigned;
      UsingConnection := false;
      adocmd.activeconnection := ConnectionString;
      adocmdprm.activeconnection := ConnectionString;
    except
      on e: exception do
      begin
        ErrMsg := e.message;
        exit;
      end;
    end;
  end;
  Result := true;
end;

function ADOStop: Boolean;
begin
  try
    if not (varisempty(adocn)) then
    begin
      adocn.close;
      adocn := unassigned;
    end;
    adors := unassigned;
    adocmd := unassigned;
    adocmdprm := unassigned;
    result := true;
  except
    on E: Exception do
    begin
      ErrMsg := e.message;
      Result := false;
    end;
  end;
  ADOActive := false;
end;

function RSOpen(SQL: string; adRSType, adLockType, adCmdType: integer;
  UseServer: Boolean): Boolean;
begin
  result := false;
  //Have two attempts at getting the required Recordset
  if UsingConnection then
  begin
    try
      if UseServer then
        adors.CursorLocation := adUseServer
      else
        adors.CursorLocation := adUseClient;
      adors.open(SQL, , adRSType, adLockType, adCmdType);
    except
      if not (ADOReset) then
        exit;
      try
        if UseServer then
          adors.CursorLocation := adUseServer
        else
          adors.CursorLocation := adUseClient;
        adors.open(SQL, , adRSType, adLockType, adCmdType);
      except
        on E: Exception do
        begin
          ErrMsg := e.message;
          exit;
        end;
      end;
    end;
  end
  else
  begin
    //Use the Connetcion String to establish a link
    try
      adors.open(SQL, ConnectionString, adRSType, adLockType, adCmdType);
    except
      if not (ADOReset) then
        exit;
      try
        adors.open(SQL, ConnectionString, adRSType, adLockType, adCmdType);
      except
        on E: Exception do
        begin
          ErrMsg := e.message;
          exit;
        end;
      end;
    end;
  end;
  Result := true;
end;

function RSClose: Boolean;
begin
  try
    adors.Close;
    result := true;
  except
    on E: Exception do
    begin
      ErrMsg := e.message;
      result := false;
    end;
  end;
end;

function CMDExec(SQL: string; adCmdType: integer): Boolean;
begin
  result := false;
  //Have two attempts at the execution..
  try
    adocmd.commandtext := SQL;
    adocmd.commandtype := adCmdType;
    adocmd.execute;
  except
    try
      if not (ADOReset) then
        exit;
      adocmd.commandtext := SQL;
      adocmd.commandtype := adCmdType;
      adocmd.execute;
    except
      on e: exception do
      begin
        ErrMsg := e.message;
        exit;
      end;
    end;
  end;
  result := true;
end;

function PRMClear: Boolean;
var
  i: integer;
begin
  try
    for i := 0 to (adocmdprm.parameters.count) - 1 do
    begin
      adocmdprm.parameters.delete(0);
    end;
    result := true;
  except
    on e: exception do
    begin
      ErrMsg := e.message;
      result := false;
    end;
  end;
end;

function PRMSetSP(StoredProcedure: string; WithClear: Boolean): Boolean;
begin
  result := false;
  //Have two attempts at setting the Stored Procedure...
  try
    adocmdprm.commandtype := adcmdStoredProc;
    adocmdprm.commandtext := StoredProcedure;
    if WithClear then
      if not (PRMClear) then
        exit;
    result := true;
  except
    try
      if not (ADOReset) then
        exit;
      adocmdprm.commandtype := adcmdStoredProc;
      adocmdprm.commandtext := StoredProcedure;
      //NB: No need to clear the parameters, as an ADOReset will have done this..
      result := true;
    except
      on e: exception do
      begin
        ErrMsg := e.message;
      end;
    end;
  end;
end;

function PRMAdd(ParamName: string; ParamType, ParamIO, ParamSize: integer; Val:
  variant): Boolean;
var
  DerivedParamSize: integer;
begin
  //Only try once to add the parameter (a call to ADOReset would reset EVERYTHING!!)
  try
    case ParamType of
      adInteger: DerivedParamSize := 4;
      adSingle: DerivedParamSize := 4;
      adDate: DerivedParamSize := 8;
      adBoolean: DerivedParamSize := 1;
      adTinyInt: DerivedParamSize := 1;
      adUnsignedTinyInt: DerivedParamSize := 1;
      adDateTime: DerivedParamSize := 8;
      advarChar: DerivedParamSize := ParamSize;
    end;
    adocmdprm.parameters.append(adoCmdPrm.createparameter(ParamName, ParamType,
      ParamIO, DerivedParamSize, Val));
  except
    on e: exception do
    begin
      ErrMsg := e.message;
    end;
  end;
end;

function PRMSetParamVal(ParamName: string; val: variant): Boolean;
begin
  //Only try once to set the parameter (a call to ADOReset would reset EVERYTHING!!)
  try
    adocmdprm.Parameters[ParamName].Value := val;
    result := true;
  except
    on e: exception do
    begin
      ErrMsg := e.message;
      result := false;
    end;
  end;
end;

function PRMGetParamVal(ParamName: string; var val: variant): Boolean;
begin
  //Only try once to read the parameter (a call to ADOReset would reset EVERYTHING!!)
  try
    val := adocmdprm.Parameters[ParamName].Value;
    result := true;
  except
    on e: exception do
    begin
      ErrMsg := e.message;
      result := false;
    end;
  end;
end;

function SQLStr(str: string; SQLStrType: TSQLStrType): string;
var
  FindChar, ReplaceChar: char;
begin
  {Convert ' '->'_' for ssToSQL (remove spaces)
  Convert '_'->' ' for ssFromSQL (remove underscores)}
  case SQLStrType of
    ssToSQL:
      begin
        FindChar := ' ';
        ReplaceChar := '_';
      end;
    ssFromSQL:
      begin
        FindChar := '_';
        ReplaceChar := ' ';
      end;
  end;

  result := str;
  while Pos(FindChar, result) > 0 do
    Result[Pos(FindChar, result)] := ReplaceChar;
end;

function SentenceCase(str: string): string;
var
  tmp: char;
  i {,len}: integer;
  NewWord: boolean;
begin
  NewWord := true;
  result := str;
  for i := 1 to Length(str) do
  begin
    if (result[i] = ' ') or (result[i] = '_') then
      NewWord := true
    else
    begin
      tmp := result[i];
      if NewWord then
      begin
        NewWord := false;
        result[i] := chr(ord(result[i]) or 64); //Set bit 6 - makes uppercase
      end
      else
        result[i] := chr(ord(result[i]) and 191); //reset bit 6 - makes lowercase
    end;
  end;
  {This was the original way of doing it, but I wanted to look for spaces or '_'s,
        and it all seemed problematic - if I find a better way another day, I'll alter the above...
       if str<>'' then
          begin
               tmp:=LowerCase(str);
               len:=length(tmp);
               tmp:=Uppercase(copy(tmp,1,1))+copy(tmp,2,len);
               i:=pos('_',tmp);
               while i<>0 do
                     begin
                          tmp:=copy(tmp,1,i-1)+' '+Uppercase(copy(tmp,i+1,1))+copy(tmp,i+2,len-i);
                          i:=pos('_',tmp);
                     end;
          end;
       result:=tmp;}
end;

end.


Взято из





Быстрый доступ к нужной записи в таблице Paradox


Быстрый доступ к нужной записи в таблице Paradox



Автор: Valler ( http://www.valler.narod.ru )

var NeedNumber: Integer;

...
NeedNumber := Table.RecNo;
{сохранение номера нужной записи}
...
{код меняющий номе записи}
...
Table.RecNo := NeedNumber;
{востановление номера нужной записи}


Взято с Исходников.ru

Примечания Vit:
1) Следует категорически избегать подобных решений в приложениях "Клиент-Сервер"
2) Если есть многопользовательский доступ, то эта конструкция может работать неправильно




Быстрый способ обмена значений в 2х переменных.


Быстрый способ обмена значений в 2х переменных.





procedure SwapVars1(var u, v; Size: Integer); 
var 
  x: Pointer; 
begin 
  GetMem(x, Size); 
  try 
    System.move(u, x^, Size); 
    System.move(v, u, Size); 
    System.move(x^, v, Size); 
  finally 
    FreeMem(x); 
  end; 
end; 


procedure SwapVars2(var Source, Dest; Size: Integer); 
  // By Mike Heydon, mheydon@eoh.co.za 
begin 
  asm 
     push edi 
     push esi 
     mov esi,Source 
     mov edi,Dest 
     mov ecx,Size 
     cld 
 @1: 
     mov al,[edi] 
     xchg [esi],al 
     inc si 
     stosb 
     loop @1 
     pop esi 
     pop edi 
  end; 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
begin 
  SwapVars1(X1, X2, SizeOf(Integer)); 
end; 

Взято с сайта


var 
 X1, X2: Byte; 
begin 
 X1 := X2 xor X2;  
 X2 := X1 xor X2; // X2 = X1 
 X1 := X1 xor X2; // X1 = X2 

Автор ___ALex___





Byte-поля Paradox


Byte-поля Paradox




Что за магия при записи в поле Paradox Byte? По этому поводу в документации ничего не сказано.

Есть 2 пути получить доступ к данным в TBytesField.

Просто вызовите метод GetData, передавая ему указатель на буфер, где сам буфер должен иметь размер, достаточный для хранения данных:

procedure SetCheckBoxStates;
var
CBStates: array[1..13] of Byte;
begin
  CBStateField.GetData(CBStates);
  { Здесь обрабатываем данные... }
end;

Для записи значений вы должны использовать SetData.

Используйте свойство Value, возвращающее вариантный массив байт (variant array of bytes):

procedure SetCheckBoxStates;
var
  CBStates: Variant;
begin
  CBStates := CBStateField.Value;
  { Здесь обрабатываем данные... }
end;

Первый метод, вероятно, для вас будет легче, поскольку вы сразу докапываетесь до уровня байт. Запись данных также получится сложнее, поскольку вам нужно будет работать с variant-методами типа VarArrayCreate и др.

Взято из





CD Remember


CD Remember




Как-то раз в один прекрасный день решил я у друга взять на денек очередной диск поиграть - и в итоге забыл его в дисководе у другого друга Вот и решил я написать программу-напоминалку: при завершении работы она выскакивает и спрашивает юзера, а не хотел бы он вынуть диск (если диска нет - она даже не пикнет )?

Исходный код модуля:

unit cd;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Buttons, StdCtrls, MMSystem;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Label2: TLabel;
    Label3: TLabel;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    Edit1: TEdit;
    GroupBox1: TGroupBox;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure BitBtn2Click(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function FindCD:Integer;
var
  i, DType:integer;
  str:string;
  drive:integer;

begin
  Result:=0;
  for i:=65 to 90 do
  begin
  str:=chr(i)+':\';
  DType:=GetDrivetype(PChar(str));
  case DType of

      0: drive:=0;
      1: drive:=1;
      DRIVE_CDROM : drive:=i;
  end;
if not ((DType=0) or (Dtype=1)) then
Result:=drive;
end;
end;

function DiskInDrive(Drive: Char): Boolean;
var 
  ErrorMode: word; 
begin 
  { переводим в верхний регистр } 
  if Drive in ['a'..'z'] then Dec(Drive, $20); 
  { убеждаемся, что это буква } 
  if not (Drive in ['A'..'Z']) then 
      raise EConvertError.Create('Not a valid drive ID');
  
  //отключаем критические ошибки// 
  
  ErrorMode := SetErrorMode(SEM_FailCriticalErrors); 
  try 
      if DiskSize (Ord(Drive) - $40) = -1 then 
        Result := False 
      else 
        Result := True; 
  finally 
      { восстанавливаем старый режим ошибок } 
      SetErrorMode(ErrorMode); 
  end; 
end;

procedure ChooseCloseMode;
begin
Form1.Height:=290;
Form1.Repaint;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.text:=(chr(Findcd)+':\');
Button1.Enabled:=false;
Label1.Enabled:=false;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if DiskInDrive(chr(findcd))=true then
begin
Canclose:=false;
Form1.Show;
end
else // если нет
CanClose:=true;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
ChooseCloseMode;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
mciSendString('Set cdaudio door open wait', nil, 0, handle);
Button1.Enabled:=true;
Label1.Enabled:=true;
BitBtn1.Enabled:=false;
Bitbtn2.Enabled:=false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
mciSendString('Set cdaudio door closed wait', nil, 0, handle);
ChooseCloseMode;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
if Radiobutton1.Checked=true then
        ExitWindowsEx(EWX_POWEROFF or EWX_SHUTDOWN,0)
else
if Radiobutton2.Checked=true then
        ExitWindowsEx(EWX_REBOOT,0);

end;

end.

Немного кривоваты комментарии, но кому нужно - разберется.
Код .DPR файла:

program cdrem;

uses
  Forms,
  cd in 'cd.pas' {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.ShowMainForm:=false;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Автор: Blabsadm

Компилятор: Delphi 5




CD-ROM/CD-R/CD-RW


CD-ROM/CD-R/CD-RW


Cодержание раздела:














Частные вопросы по конкретным базам данных


Частные вопросы по конкретным базам данных



Cодержание раздела:


·
·  
·  
·  
·  
·  
·  
·  
·  



·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  



·
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  



·  
·  
·  
·  
·  
·  
·  
·  



·
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  



·  
·  



·




·
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  
·  



·  
·  
·  
·  
·  
·  
·  
·  
·  
·  



·




·
·  
·  



·  


·  
·  
·  





Частые Вопросы и Ответы


Частые Вопросы и Ответы



Частые Вопросы и Ответы

1) Настройка CGI для IIS

Запустите программу
Пуск/Программы/Microsoft Internet Server/Служба Управления  
Кликните два раза на службе WWW, и выберите закладку "Каталоги":  
 

Каталог   Алиас   Адрес    Ошибка   

C:\InetPub\wwwroot   <базовый каталог>         
C:\InetPub\scripts   /Scripts         
C:\WINNT\System32\inetsrv\iisadmin    /iisadmin         
 
Кликните на Добавить, укажите каталог, в котором будут содержаться CGI-программы (например C:\DELPHI).  
Алиас виртуального каталога, обычно называемый "/cgi bin", заменяет права доступа для чтения на права доступа для "Выполнения".  
 

КаталогАлиас   Адрес    Ошибка   

C:\InetPub\wwwroot   <базовый каталог>         
c:\delphi   /cgi-bin         
C:\InetPub\scripts   /Scripts         
C:\WINNT\System32\inetsrv\iisadmin    /iisadmin         
 
Теперь нам достаточно поместить наши CGI-программы в каталог C:\DELPHI и обращаться к ним примерно так: http://ваш_сервер/cgi-bin/program.exe  
 
Если ваша NT выдает ошибку прав доступа на конкретном документе, кликните на этом документе, и проверьте, разрешен ли доступ...  
 

2) Как избавиться от запроса СОХРАНИТЬ/ВЫПОЛНИТЬ при клике на ссылку вида <a href="/cgi-bin/programm.exe"> ?

Для того, чтобы браузер не спрашивал у вас, надо ли сохранить или выполнить вашу CGI-программу, необходимо обязательно размещать выполняемые программы не где попало, а именно в том каталоге, который вы указали серверу в качестве каталога CGI...  
 
Если вы установили web-сервер на локальный компьютер (localhost), то обращаться к нему нужно следующим образом:  
http://127.0.0.1/cgi-bin/programm.exe  




Checkbox


Checkbox



Cодержание раздела:




См. также статьи в других разделах:





Черчение


Черчение



Cодержание раздела:









См. также статьи в других разделах:





Через DAO/ODBC/ADO


Через DAO/ODBC/ADO



Чтобы использовать только стандартные компоненты давайте попробуем работать с Excel через ADO. Это не самый быстрый и далеко не первый по возможностям метод (DAO работает на порядок быстрее и предоставляет куда больше возможностей), но ADO компоненты входят в стандартную поставку 5 и 6 Дельфи. Итак заходим в Панель управления Windows, идем в свойства ODBC, делаем DSN используя Excel драйвер, не забываем указать в свойствах на файл Excel. Закрываем ODBC, открываем Дельфи. Ставим на форму ADOConnection. Идем в ConnectionString - строим строку подключения - надо выбрать только ODBC провайдер и на следующей вкладке указать сделанный DSN, остальные опции в большинстве случаев можно оставить как есть. Строка получена. Кстати ее можно вообще упростить до вида: "DSN=MyDsn". Теперь вам доступны листы файла как таблицы а весь файл как база данных. Подключаем ADOQuery к ADOConnection. Cоздаем таблицу, т.е. новый лист - путем запуска следующей квери:

Create Table MyTable1 (
Field1 varchar(20),
Field2 varchar(10) )

Снова переходим в дизайн - ставим на форму ADOTable, указываем как Connection наш компонент с ADOConnection, теперь если кликнуть на свойстве TableName - вы сможете увидеть в списке сделанную нами таблицу "MyTable1". Соедините таблицу с DBGrid - убедитесь что работа с таблицей в Excel мало отличается от работы с другими базами данных.

Автор ответа Vit
Взято с Vingrad.ru








Через СОМ интерфейс


Через СОМ интерфейс



var Excel, WorkBook, Sheet: Variant;
begin
Excel := CreateOleObject('Excel.Application');  
Excel.WorkBooks.Open(FileName,False);  
WorkBook := Excel.WorkBooks.Item[1];  
Sheet := Workbook.Sheets.Item[3];  
Sheet.Cells[1,2]:='ASDFG';  
Sheet.Cells[2,2]:=230;  


Все объекты и методы Офиса можно посмотреть в help'е Офиса.

Автор ответа: Fantasist
Взято с Vingrad.ru



Ниже представлен пример создания новой таблице в Excel 2000:

uses
  ComObj, ActiveX;

var
  Row, Col: integer;
  DestRange: OleVariant;
  Excel: Variant;

begin
  Excel := CreateOleObject('Excel.Application.9');
  Excel.Visible := True;
  Excel.WorkBooks.Add; //Создать новую таблицу

  //Можно помещать текст и значения в диапазон ячеек
  //Поместить     слово тест в диапазон ячеек
  Excel.ActiveSheet.Range['A2', 'B3'].Value := 'Тест';
  //Или число
  Excel.ActiveSheet.Range['A4', 'B5'].Value := 42;

  //А вот так задаётся формула
  Excel.ActiveSheet.Range['A10', 'A11'].Formula := '=RAND()';

  //Можно задавать номера ячеек и столбцов
  Excel.ActiveSheet.Cells.Item[1, 1].Value := 'Первая ячейка';

  Row:=1;
  Col:=3;
  Excel.ActiveSheet.Cells.Item[Row, Col].Value := 'Другая ячейка';

  //Можно скопировать данный из одного диапазона ячеек в другой
  DestRange := Excel.Range['D6', 'F10'];
  Excel.Range['A1', 'C5'].Copy(DestRange);

  //Можно задавать параметры шрифта в определённой ячейке
  Excel.Range['A2', 'A2'].Font.Size := 20;
  Excel.Range['A2', 'A2'].Font.FontStyle := 'Bold';
  Excel.Range['A2', 'A2'].Font.Color := clFuchsia;
  Excel.Range['A2', 'A2'].Font.Name := 'Arial';

  //Можно ещё и так изменить цвет диапазона ячеек
  Excel.Range['B2', 'C6'].Interior.Color := RGB(223, 123, 123);

end;



Далее представлен пример открытия и закрытия таблицы:

uses
  ComObj, ActiveX;

var
  Excel: Variant;
  WBk : OleVariant;
  SaveChanges: OleVariant;

begin
  Excel := CreateOleObject('Excel.Application.9');
  Excel.Visible := True;

  //Открыть существующую таблицу
  WBk := Excel.WorkBooks.Open('C:\Test.xls');

  ...

  WBk.Close(SaveChanges := True);
  Excel.Quit;

end;

Взято с Исходников.ru




Число английской строкой


Число английской строкой




unituNum2Str;

// Possible enhancements
// Move strings out to resource files
// Put in a general num2str utility

interface

function Num2Dollars(dNum: double): string;

implementation

uses SysUtils;

function LessThan99(dNum: double): string; forward;

// floating point modulus
function FloatMod(i, j: double): double;
begin

  result := i - (Int(i / j) * j);
end;

function Hundreds(dNum: double): string;
var

  workVar: double;
begin

  if (dNum < 100) or (dNum > 999) then
    raise Exception.Create('hundreds range exceeded');

  result := '';

  workVar := Int(dNum / 100);
  if workVar > 0 then
    result := LessThan99(workVar) + ' Hundred';
end; function OneToNine(dNum: Double): string;
begin

  if (dNum < 1) or (dNum > 9) then
    raise exception.create('onetonine: value out of range');

  result := 'woops';

  if dNum = 1 then
    result := 'One'
  else if dNum = 2 then
    result := 'Two'
  else if dNum = 3 then
    result := 'Three'
  else if dNum = 4 then
    result := 'Four'
  else if dNum = 5.0 then
    result := 'Five'
  else if dNum = 6 then
    result := 'Six'
  else if dNum = 7 then
    result := 'Seven'
  else if dNum = 8 then
    result := 'Eight'
  else if dNum = 9 then
    result := 'Nine';

end;

function ZeroTo19(dNum: double): string;
begin

  if (dNum < 0) or (dNum > 19) then
    raise Exception.Create('Bad value in dNum');

  result := '';

  if dNum = 0 then
    result := 'Zero'
  else if (dNum <= 1) and (dNum >= 9) then
    result := OneToNine(dNum)
  else if dNum = 10 then
    result := 'Ten'
  else if dNum = 11 then
    result := 'Eleven'
  else if dNum = 12 then
    result := 'Twelve'
  else if dNum = 13 then
    result := 'Thirteen'
  else if dNum = 14 then
    result := 'Fourteen'
  else if dNum = 15 then
    result := 'Fifteen'
  else if dNum = 16 then
    result := 'Sixteen'
  else if dNum = 17 then
    result := 'Seventeen'
  else if dNum = 18 then
    result := 'Eighteen'
  else if dNum = 19 then
    result := 'Nineteen'
  else
    result := 'woops!';
end;

function TwentyTo99(dNum: double): string;
var

  BigNum: string;
begin

  if (dNum < 20) or (dNum > 99) then
    raise exception.Create('TwentyTo99: dNum out of range!');

  BigNum := 'woops';

  if dNum >= 90 then
    BigNum := 'Ninety'
  else if dNum >= 80 then
    BigNum := 'Eighty'
  else if dNum >= 70 then
    BigNum := 'Seventy'
  else if dNum >= 60 then
    BigNum := 'Sixty'
  else if dNum >= 50 then
    BigNum := 'Fifty'
  else if dNum >= 40 then
    BigNum := 'Forty'
  else if dNum >= 30 then
    BigNum := 'Thirty'
  else if dNum >= 20 then
    BigNum := 'Twenty';

// lose the big num
  dNum := FloatMod(dNum, 10);

  if dNum > 0.00 then
    result := BigNum + ' ' + OneToNine(dNum)
  else
    result := BigNum;
end;

function LessThan99(dNum: double): string;
begin

  if dNum <= 19 then
    result := ZeroTo19(dNum)
  else
    result := TwentyTo99(dNum);
end;

function Num2Dollars(dNum: double): string;
var

  centsString: string;
  cents: double;
  workVar: double;
begin

  result := '';

  if dNum < 0 then
    raise Exception.Create('Negative numbers not supported');

  if dNum > 999999999.99 then
    raise Exception.Create('Num2Dollars only supports up to the millions at this point!');

  cents := (dNum - Int(dNum)) * 100.0;
  if cents = 0.0 then
    centsString := 'and 00/100 Dollars'
  else if cents < 10 then
    centsString := Format('and 0%1.0f/100 Dollars', [cents])
  else
    centsString := Format('and %2.0f/100 Dollars', [cents]);

  dNum := Int(dNum - (cents / 100.0)); // lose the cents

// deal with million's
  if (dNum >= 1000000) and (dNum <= 999999999) then
    begin
      workVar := dNum / 1000000;
      workVar := Int(workVar);
      if (workVar <= 9) then
        result := ZeroTo19(workVar)
      else if (workVar <= 99) then
        result := LessThan99(workVar)
      else if (workVar <= 999) then
        result := Hundreds(workVar)
      else
        result := 'mill fubar';

      result := result + ' Million';

      dNum := dNum - (workVar * 1000000);
    end;

// deal with 1000's
  if (dNum >= 1000) and (dNum <= 999999.99) then
    begin
// doing the two below statements in one line of code yields some really
// freaky floating point errors
      workVar := dNum / 1000;
      workVar := Int(workVar);
      if (workVar <= 9) then
        result := ZeroTo19(workVar)
      else if (workVar <= 99) then
        result := LessThan99(workVar)
      else if (workVar <= 999) then
        result := Hundreds(workVar)
      else
        result := 'thou fubar';

      result := result + ' Thousand';

      dNum := dNum - (workVar * 1000);
    end;

// deal with 100's
  if (dNum >= 100.00) and (dNum <= 999.99) then
    begin
      result := result + ' ' + Hundreds(dNum);
      dNum := FloatMod(dNum, 100);
    end;

// format in anything less than 100
  if (dNum > 0) or ((dNum = 0) and (Length(result) = 0)) then
    begin
      result := result + ' ' + LessThan99(dNum);
    end;
  result := result + ' ' + centsString;
end;

end.


function HundredAtATime(TheAmount: Integer): string;
var

  TheResult: string;
begin

  TheResult := '';
  TheAmount := Abs(TheAmount);
  while TheAmount > 0 do
    begin
      if TheAmount >= 900 then
        begin
          TheResult := TheResult + 'Nine hundred ';
          TheAmount := TheAmount - 900;
        end;
      if TheAmount >= 800 then
        begin
          TheResult := TheResult + 'Eight hundred ';
          TheAmount := TheAmount - 800;
        end;
      if TheAmount >= 700 then
        begin
          TheResult := TheResult + 'Seven hundred ';
          TheAmount := TheAmount - 700;
        end;
      if TheAmount >= 600 then
        begin
          TheResult := TheResult + 'Six hundred ';
          TheAmount := TheAmount - 600;
        end;
      if TheAmount >= 500 then
        begin
          TheResult := TheResult + 'Five hundred ';
          TheAmount := TheAmount - 500;
        end;
      if TheAmount >= 400 then
        begin
          TheResult := TheResult + 'Four hundred ';
          TheAmount := TheAmount - 400;
        end;
      if TheAmount >= 300 then
        begin
          TheResult := TheResult + 'Three hundred ';
          TheAmount := TheAmount - 300;
        end;
      if TheAmount >= 200 then
        begin
          TheResult := TheResult + 'Two hundred ';
          TheAmount := TheAmount - 200;
        end;
      if TheAmount >= 100 then
        begin
          TheResult := TheResult + 'One hundred ';
          TheAmount := TheAmount - 100;
        end;
      if TheAmount >= 90 then
        begin
          TheResult := TheResult + 'Ninety ';
          TheAmount := TheAmount - 90;
        end;
      if TheAmount >= 80 then
        begin
          TheResult := TheResult + 'Eighty ';
          TheAmount := TheAmount - 80;
        end;
      if TheAmount >= 70 then
        begin
          TheResult := TheResult + 'Seventy ';
          TheAmount := TheAmount - 70;
        end;
      if TheAmount >= 60 then
        begin
          TheResult := TheResult + 'Sixty ';
          TheAmount := TheAmount - 60;
        end;
      if TheAmount >= 50 then
        begin
          TheResult := TheResult + 'Fifty ';
          TheAmount := TheAmount - 50;
        end;
      if TheAmount >= 40 then
        begin
          TheResult := TheResult + 'Fourty ';
          TheAmount := TheAmount - 40;
        end;
      if TheAmount >= 30 then
        begin
          TheResult := TheResult + 'Thirty ';
          TheAmount := TheAmount - 30;
        end;
      if TheAmount >= 20 then
        begin
          TheResult := TheResult + 'Twenty ';
          TheAmount := TheAmount - 20;
        end;
      if TheAmount >= 19 then
        begin
          TheResult := TheResult + 'Nineteen ';
          TheAmount := TheAmount - 19;
        end;
      if TheAmount >= 18 then
        begin
          TheResult := TheResult + 'Eighteen ';
          TheAmount := TheAmount - 18;
        end;
      if TheAmount >= 17 then
        begin
          TheResult := TheResult + 'Seventeen ';
          TheAmount := TheAmount - 17;
        end;
      if TheAmount >= 16 then
        begin
          TheResult := TheResult + 'Sixteen ';
          TheAmount := TheAmount - 16;
        end;
      if TheAmount >= 15 then
        begin
          TheResult := TheResult + 'Fifteen ';
          TheAmount := TheAmount - 15;
        end;
      if TheAmount >= 14 then
        begin
          TheResult := TheResult + 'Fourteen ';
          TheAmount := TheAmount - 14;
        end;
      if TheAmount >= 13 then
        begin
          TheResult := TheResult + 'Thirteen ';
          TheAmount := TheAmount - 13;
        end;
      if TheAmount >= 12 then
        begin
          TheResult := TheResult + 'Twelve ';
          TheAmount := TheAmount - 12;
        end;
      if TheAmount >= 11 then
        begin
          TheResult := TheResult + 'Eleven ';
          TheAmount := TheAmount - 11;
        end;
      if TheAmount >= 10 then
        begin
          TheResult := TheResult + 'Ten ';
          TheAmount := TheAmount - 10;
        end;
      if TheAmount >= 9 then
        begin
          TheResult := TheResult + 'Nine ';
          TheAmount := TheAmount - 9;
        end;
      if TheAmount >= 8 then
        begin
          TheResult := TheResult + 'Eight ';
          TheAmount := TheAmount - 8;
        end;
      if TheAmount >= 7 then
        begin
          TheResult := TheResult + 'Seven ';
          TheAmount := TheAmount - 7;
        end;
      if TheAmount >= 6 then
        begin
          TheResult := TheResult + 'Six ';
          TheAmount := TheAmount - 6;
        end;
      if TheAmount >= 5 then
        begin
          TheResult := TheResult + 'Five ';
          TheAmount := TheAmount - 5;
        end;
      if TheAmount >= 4 then
        begin
          TheResult := TheResult + 'Four ';
          TheAmount := TheAmount - 4;
        end;
      if TheAmount >= 3 then
        begin
          TheResult := TheResult + 'Three ';
          TheAmount := TheAmount - 3;
        end;
      if TheAmount >= 2 then
        begin
          TheResult := TheResult + 'Two ';
          TheAmount := TheAmount - 2;
        end;
      if TheAmount >= 1 then
        begin
          TheResult := TheResult + 'One ';
          TheAmount := TheAmount - 1;
        end;
    end;
  HundredAtATime := TheResult;
end;

function Real2CheckAmount(TheAmount: Real): string;
var

  IntVal: LongInt;
  TmpVal: Integer;
  TmpStr,
    RetVal: string;
begin

  TheAmount := Abs(TheAmount);

{ центы }
  TmpVal := Round(Frac(TheAmount) * 100);
  IntVal := Trunc(TheAmount);
  TmpStr := HundredAtATime(TmpVal);
  if TmpStr = '' then TmpStr := 'Zero ';
  RetVal := TmpStr + 'cents';
  if IntVal > 0 then RetVal := 'dollars and ' + RetVal;

{ сотни }
  TmpVal := Round(Frac((IntVal * 1.0) / 1000.0) * 1000);
  IntVal := Trunc((IntVal * 1.0) / 1000.0);
  TmpStr := HundredAtATime(TmpVal);
  RetVal := TmpStr + RetVal;

{ тысячи }
  TmpVal := Round(Frac((IntVal * 1.0) / 1000.0) * 1000);
  IntVal := Trunc((IntVal * 1.0) / 1000.0);
  TmpStr := HundredAtATime(TmpVal);
  if TmpStr <> '' then
    RetVal := TmpStr + 'Thousand ' + RetVal;

{ миллионы }
  TmpVal := Round(Frac((IntVal * 1.0) / 1000.0) * 1000);
  IntVal := Trunc((IntVal * 1.0) / 1000.0);
  TmpStr := HundredAtATime(TmpVal);
  if TmpStr <> '' then
    RetVal := TmpStr + 'Million ' + RetVal;

{ миллиарды }
  TmpVal := Round(Frac((IntVal * 1.0) / 1000.0) * 1000);
  IntVal := Trunc((IntVal * 1.0) / 1000.0);
  TmpStr := HundredAtATime(TmpVal);
  if TmpStr <> '' then
    RetVal := TmpStr + 'Billion ' + RetVal;

  Real2CheckAmount := RetVal;
end;

Хммммм...вроде бы работает, но как все громоздко и неуклюже....добавьте в код немного рекурсии и вы получите более элегантную программу..: )))

unit Unit1;

interface

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type

  TForm1 = class(TForm)
    num: TEdit;
    spell: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
{ Private declarations }
    function trans9(num: integer): string;
    function trans19(num: integer): string;
    function trans99(num: integer): string;
    function IntToSpell(num: integer): string;
  public
{ Public declarations }
  end;

var

  Form1: TForm1;

implementation

{$R *.DFM}
function TForm1.IntToSpell(num: integer): string;
var

  spell: string;
  hspell: string;
  hundred: string;
  thousand: string;
  tthousand: string;
  hthousand: string;
  million: string;
begin

  if num &lg; 10 then
    spell := trans9(num);
{endif}
  if (num < 20) and (num > 10) then
    spell := trans19(num);
{endif}
  if (((num < 100) and (num > 19)) or (num = 10)) then
    begin
      hspell := copy(IntToStr(num), 1, 1) + '0';
      spell := trans99(StrToInt(hspell));
      hspell := copy(IntToStr(num), 2, 1);
      spell := spell + ' ' + IntToSpell(StrToInt(hspell));
    end;

  if (num < 1000) and (num > 100) then
    begin
      hspell := copy(IntToStr(num), 1, 1);
      hundred := IntToSpell(StrToInt(hspell));
      hspell := copy(IntToStr(num), 2, 2);
      hundred := hundred + ' hundred and ' + IntToSpell(StrToInt(hspell));
      spell := hundred;
    end;

  if (num < 10000) and (num > 1000) then
    begin
      hspell := copy(IntToStr(num), 1, 1);
      thousand := IntToSpell(StrToInt(hspell));
      hspell := copy(IntToStr(num), 2, 3);
      thousand := thousand + ' thousand ' + IntToSpell(StrToInt(hspell));
      spell := thousand;
    end;

  if (num < 100000) and (num > 10000) then
    begin
      hspell := copy(IntToStr(num), 1, 2);
      tthousand := IntToSpell(StrToInt(hspell));
      hspell := copy(IntToStr(num), 3, 3);
      tthousand := tthousand + ' thousand ' + IntToSpell(StrToInt(hspell));
      spell := tthousand;
    end;

  if (num < 1000000) and (num > 100000) then
    begin
      hspell := copy(IntToStr(num), 1, 3);
      hthousand := IntToSpell(StrToInt(hspell));
      hspell := copy(IntToStr(num), 4, 3);
      hthousand := hthousand + ' thousand and ' +
        IntToSpell(StrToInt(hspell));

      spell := hthousand;
    end;

  if (num < 10000000) and (num > 1000000) then
    begin
      hspell := copy(IntToStr(num), 1, 1);
      million := IntToSpell(StrToInt(hspell));
      hspell := copy(IntToStr(num), 2, 6);
      million := million + ' million and ' + IntToSpell(StrToInt(hspell));
      spell := million;
    end;

  IntToSpell := spell;

end;

function TForm1.trans99(num: integer): string;
var

  spell: string;
begin

  case num of
    10: spell := 'ten';
    20: spell := 'twenty';
    30: spell := 'thirty';
    40: spell := 'fourty';
    50: spell := 'fifty';
    60: spell := 'sixty';
    70: spell := 'seventy';
    80: spell := 'eighty';
    90: spell := 'ninty';
  end;
  trans99 := spell;
end;
function TForm1.trans19(num: integer): string;
var

  spell: string;
begin

  case num of
    11: spell := 'eleven';
    12: spell := 'twelve';
    13: spell := 'thirteen';
    14: spell := 'fourteen';
    15: spell := 'fifteen';
    16: spell := 'sixteen';
    17: spell := 'seventeen';
    18: spell := 'eighteen';
    19: spell := 'nineteen';
  end;
  trans19 := spell;
end;
function TForm1.trans9(num: integer): string;
var

  spell: string;
begin

  case num of
    1: spell := 'one';
    2: spell := 'two';
    3: spell := 'three';
    4: spell := 'four';
    5: spell := 'five';
    6: spell := 'six';
    7: spell := 'seven';
    8: spell := 'eight';
    9: spell := 'nine';
  end;
  trans9 := spell;
end;
procedure TForm1.Button1Click(Sender: TObject);
var

  numb: integer;
begin

  spell.text := IntToSpell(StrToInt(num.text));
end;


Взято из

Советов по Delphi от


Сборник Kuliba





Число цветов (цветовая палитра) у данного компьютера


Число цветов (цветовая палитра) у данного компьютера



Эта функция возвращает число бит на точку у данного компьютера. Так, например, 8 - 256 цветов, 4 - 16 цветов ...


function GetDisplayColors : integer;
var tHDC  : hdc;
begin
 tHDC:=GetDC(0);
 result:=GetDeviceCaps(tHDC, 12)* GetDeviceCaps(tHDC, 14);
 ReleaseDC(0, tHDC);
end;

Зайцев О.В.
Владимиров А.М.
Взято с Исходников.ru





Число русской строкой


Число русской строкой




Автор Александр

{------------------------Деньги прописью ---------------------}
function TextSum(S: double): string;

  function Conv999(M: longint; fm: integer): string;
  const

    c1to9m: array[1..9] of string[6] =
    ('один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять');
    c1to9f: array[1..9] of string[6] =
    ('одна', 'две', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять');
    c11to19: array[1..9] of string[12] =
    ('одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать',
      'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать');
    c10to90: array[1..9] of string[11] =
    ('десять', 'двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят',
      'семьдесят', 'восемьдесят', 'девяносто');
    c100to900: array[1..9] of string[9] =
    ('сто', 'двести', 'триста', 'четыреста', 'пятьсот', 'шестьсот', 'семьсот',
      'восемьсот', 'девятьсот');
  var

    s: string;
    i: longint;
  begin

    s := '';
    i := M div 100;
    if i <> 0 then s := c100to900[i] + ' ';
    M := M mod 100;
    i := M div 10;
    if (M > 10) and (M < 20) then
      s := s + c11to19[M - 10] + ' '
    else
      begin
        if i <> 0 then s := s + c10to90[i] + ' ';
        M := M mod 10;
        if M <> 0 then
          if fm = 0 then
            s := s + c1to9f[M] + ' '
          else
            s := s + c1to9m[M] + ' ';
      end;
    Conv999 := s;
  end;

{--------------------------------------------------------------}
var

  i: longint;
  j: longint;
  r: real;
  t: string;

begin

  t := '';

  j := Trunc(S / 1000000000.0);
  r := j;
  r := S - r * 1000000000.0;
  i := Trunc(r);
  if j <> 0 then
    begin
      t := t + Conv999(j, 1) + 'миллиард';
      j := j mod 100;
      if (j > 10) and (j < 20) then
        t := t + 'ов '
      else
        case j mod 10 of
          0: t := t + 'ов ';
          1: t := t + ' ';
          2..4: t := t + 'а ';
          5..9: t := t + 'ов ';
        end;
    end;

  j := i div 1000000;
  if j <> 0 then
    begin
      t := t + Conv999(j, 1) + 'миллион';
      j := j mod 100;
      if (j > 10) and (j < 20) then
        t := t + 'ов '
      else
        case j mod 10 of
          0: t := t + 'ов ';
          1: t := t + ' ';
          2..4: t := t + 'а ';
          5..9: t := t + 'ов ';
        end;
    end;

  i := i mod 1000000;
  j := i div 1000;
  if j <> 0 then
    begin
      t := t + Conv999(j, 0) + 'тысяч';
      j := j mod 100;
      if (j > 10) and (j < 20) then
        t := t + ' '
      else
        case j mod 10 of
          0: t := t + ' ';
          1: t := t + 'а ';
          2..4: t := t + 'и ';
          5..9: t := t + ' ';
        end;
    end;

  i := i mod 1000;
  j := i;
  if j <> 0 then t := t + Conv999(j, 1);
  t := t + 'руб. ';

  i := Round(Frac(S) * 100.0);
  t := t + Long2Str(i) + ' коп.';
  TextSum := t;
end;

unit RoubleUnit;
{$D Пропись © Близнец Антон '99 http:\\anton-bl.chat.ru\delphi\1001.htm }
{ 1000011.01->'Один миллион одинадцать рублей 01 копейка'               }
interface
function RealToRouble(c: Extended): string;
implementation
uses SysUtils, math;
const Max000 = 6; {Кол-во триплетов - 000}
  MaxPosition = Max000 * 3; {Кол-во знаков в числе }
//Аналог IIF в Dbase есть в proc.pas для основных типов, частично объявлена тут для независимости
function IIF(i: Boolean; s1, s2: Char): Char; overload; begin if i then
    result := s1
  else
    result := s2 end;
function IIF(i: Boolean; s1, s2: string): string; overload; begin if i then
    result := s1
  else
    result := s2 end;

function NumToStr(s: string): string; {Возвращает число прописью}
const c1000: array[0..Max000] of string = ('', 'тысяч', 'миллион', 'миллиард', 'триллион', 'квадраллион', 'квинтиллион');

  c1000w: array[0..Max000] of Boolean = (False, True, False, False, False, False, False);
  w: array[False..True, '0'..'9'] of string[3] = (('ов ', ' ', 'а ', 'а ', 'а ', 'ов ', 'ов ', 'ов ', 'ов ', 'ов '),
    (' ', 'а ', 'и ', 'и ', 'и ', ' ', ' ', ' ', ' ', ' '));
  function Num000toStr(S: string; woman: Boolean): string; {Num000toStr возвращает число для триплета}
  const c100: array['0'..'9'] of string = ('', 'сто ', 'двести ', 'триста ', 'четыреста ', 'пятьсот ', 'шестьсот ', 'семьсот ', 'восемьсот ', 'девятьсот ');
    c10: array['0'..'9'] of string = ('', 'десять ', 'двадцать ', 'тридцать ', 'сорок ', 'пятьдесят ', 'шестьдесят ', 'семьдесят ', 'восемьдесят ', 'девяносто ');
    c11: array['0'..'9'] of string = ('', 'один', 'две', 'три', 'четыр', 'пят', 'шест', 'сем', 'восем', 'девят');
    c1: array[False..True, '0'..'9'] of string = (('', 'один ', 'два ', 'три ', 'четыре ', 'пять ', 'шесть ', 'семь ', 'восемь ', 'девять '),
      ('', 'одна ', 'две ', 'три ', 'четыре ', 'пять ', 'шесть ', 'семь ', 'восемь ', 'девять '));
  begin {Num000toStr}
    Result := c100[s[1]] + iif((s[2] = '1') and (s[3] > '0'), c11[s[3]] + 'надцать ', c10[s[2]] + c1[woman, s[3]]);
  end; {Num000toStr}

var s000: string[3];

  isw, isMinus: Boolean;
  i: integer; //Счётчик триплетов
begin

  Result := ''; i := 0;
  isMinus := (s <> '') and (s[1] = '-');
  if isMinus then s := Copy(s, 2, Length(s) - 1);
  while not ((i >= Ceil(Length(s) / 3)) or (i >= Max000)) do
    begin
      s000 := Copy('00' + s, Length(s) - i * 3, 3);
      isw := c1000w[i];
      if (i > 0) and (s000 <> '000') then //тысячи и т.д.
        Result := c1000[i] + w[Isw, iif(s000[2] = '1', '0', s000[3])] + Result;
      Result := Num000toStr(s000, isw) + Result;
      Inc(i)
    end;
  if Result = '' then Result := 'ноль';
  if isMinus then Result := 'минус ' + Result;
end; {NumToStr}

function RealToRouble(c: Extended): string;

const ruble: array['0'..'9'] of string[2] = ('ей', 'ь', 'я', 'я', 'я', 'ей', 'ей', 'ей', 'ей', 'ей');
  Kopeek: array['0'..'9'] of string[3] = ('ек', 'йка', 'йки', 'йки', 'йки', 'ек', 'ек', 'ек', 'ек', 'ек');

  function ending(const s: string): Char;
  var l: Integer; //С l на 8 байт коротче $50->$48->$3F
  begin //Возвращает индекс окончания
    l := Length(s);
    Result := iif((l > 1) and (s[l - 1] = '1'), '0', s[l]);
  end;

var rub: string[MaxPosition + 3]; kop: string[2];
begin {Возвращает число прописью с рублями и копейками}

  Str(c: MaxPosition + 3: 2, Result);
  if Pos('E', Result) = 0 then //Если число можно представить в строке <>1E+99
    begin
      rub := TrimLeft(Copy(Result, 1, Length(Result) - 3));
      kop := Copy(Result, Length(Result) - 1, 2);
      Result := NumToStr(rub) + ' рубл' + ruble[ending(rub)]
        + ' ' + kop + ' копе' + Kopeek[ending(kop)];
      Result := AnsiUpperCase(Result[1]) + Copy(Result, 2, Length(Result) - 1);
    end;
end;
end.


Редянов Денис


function CifrToStr(Cifr: string; Pr: Integer; Padeg: Integer): string;
{Функция возвращает прописью 1 цифры признак 3-единицы 2-десятки 1-сотни 4-11-19

Padeg - 1-нормально 2- одна, две }
var i: Integer;
begin

  i := StrToInt(Cifr);
  if Pr = 1 then
    case i of
      1: CifrToStr := 'сто';
      2: CifrToStr := 'двести';
      3: CifrToStr := 'триста';
      4: CifrToStr := 'четыреста';
      5: CifrToStr := 'пятьсот';
      6: CifrToStr := 'шестьсот';
      7: CifrToStr := 'семьсот';
      8: CifrToStr := 'восемьсот';
      9: CifrToStr := 'девятьсот';
      0: CifrToStr := '';
    end
  else if Pr = 2 then
    case i of
      1: CifrToStr := '';
      2: CifrToStr := 'двадцать';
      3: CifrToStr := 'тридцать';
      4: CifrToStr := 'сорок';
      5: CifrToStr := 'пятьдесят';
      6: CifrToStr := 'шестьдесят';
      7: CifrToStr := 'семьдесят';
      8: CifrToStr := 'восемьдесят';
      9: CifrToStr := 'девяносто';
      0: CifrToStr := '';
    end
  else if Pr = 3 then
    case i of
      1: if Padeg = 1 then
          CifrToStr := 'один'
        else
          CifrToStr := 'одна';
      2: if Padeg = 1 then
          CifrToStr := 'два'
        else
          CifrToStr := 'две';
      3: CifrToStr := 'три';
      4: CifrToStr := 'четыре';
      5: CifrToStr := 'пять';
      6: CifrToStr := 'шесть';
      7: CifrToStr := 'семь';
      8: CifrToStr := 'восемь';
      9: CifrToStr := 'девять';
      0: CifrToStr := '';
    end
  else if Pr = 4 then
    case i of
      1: CifrToStr := 'одиннадцать';
      2: CifrToStr := 'двенадцать';
      3: CifrToStr := 'тринадцать';
      4: CifrToStr := 'четырнадцать';
      5: CifrToStr := 'пятнадцать';
      6: CifrToStr := 'шестнадцать';
      7: CifrToStr := 'семнадцать';
      8: CifrToStr := 'восемнадцать';
      9: CifrToStr := 'девятнадцать';
      0: CifrToStr := 'десять';

    end;
end;

function Rasryad(K: Integer; V: string): string;
{Функция возвращает наименование разряда в зависимости от последних 2 цифр его}
var j: Integer;
begin

  j := StrToInt(Copy(v, Length(v), 1));
  if (StrToInt(Copy(v, Length(v) - 1, 2)) > 9) and (StrToInt(Copy(v, Length(v) - 1, 2)) < 20) then
    case K of
      0: Rasryad := '';
      1: Rasryad := 'тысяч';
      2: Rasryad := 'миллионов';
      3: Rasryad := 'миллиардов';
      4: Rasryad := 'триллионов';
    end
  else
    case K of
      0: Rasryad := '';
      1: case j of
          1: Rasryad := 'тысяча';
          2..4: Rasryad := 'тысячи';
        else
          Rasryad := 'тысяч';
        end;
      2: case j of
          1: Rasryad := 'миллион';
          2..4: Rasryad := 'миллионa';
        else
          Rasryad := 'миллионов';
        end;
      3: case j of
          1: Rasryad := 'миллиард';
          2..4: Rasryad := 'миллиарда';
        else
          Rasryad := 'миллиардов';
        end;
      4: case j of
          1: Rasryad := 'триллион';
          2..4: Rasryad := 'триллиона';
        else
          Rasryad := 'триллионов';
        end;
    end;
end;

function GroupToStr(Group: string; Padeg: Integer): string;
{Функция возвращает прописью 3 цифры}
var i: Integer;

  S: string;
begin

  S := '';
  if (StrToInt(Copy(Group, Length(Group) - 1, 2)) > 9) and (StrToInt(Copy(Group, Length(Group) - 1, 2)) < 20) then
    begin
      if Length(Group) = 3 then
        S := S + ' ' + CifrToStr(Copy(Group, 1, 1), 1, Padeg);
      S := S + ' ' + CifrToStr(Copy(Group, Length(Group), 1), 4, Padeg);
    end
  else
    for i := 1 to Length(Group) do
      S := S + ' ' + CifrToStr(Copy(Group, i, 1), i - Length(Group) + 3, Padeg);
  GroupToStr := S;
end;

{Функция возвращает сумму прописью}
function RubToStr(Rubs: Currency; Rub, Kop: string): string;
var i, j: Integer;

  R, K, S: string;
begin

  S := CurrToStr(Rubs);
  S := Trim(S);
  if Pos(',', S) = 0 then
    begin
      R := S;
      K := '00';
    end
  else
    begin
      R := Copy(S, 0, (Pos(',', S) - 1));
      K := Copy(S, (Pos(',', S) + 1), Length(S));
    end;

  S := '';
  i := 0;
  j := 1;
  while Length(R) > 3 do
    begin
      if i = 1 then
        j := 2
      else
        j := 1;
      S := GroupToStr(Copy(R, Length(R) - 2, 3), j) + ' ' + Rasryad(i, Copy(R, Length(R) - 2, 3)) + ' ' + S;
      R := Copy(R, 1, Length(R) - 3);
      i := i + 1;
    end;
  if i = 1 then
    j := 2
  else
    j := 1;
  S := Trim(GroupToStr(R, j) + ' ' + Rasryad(i, R) + ' ' + S + ' ' + Rub + ' ' + K + ' ' + Kop);
  S := ANSIUpperCase(Copy(S, 1, 1)) + Copy(S, 2, Length(S) - 1);
  RubToStr := S;
end;


Вот еще одно решение, присланное Олегом Клюкач.


unit Numinwrd;

interface
function sMoneyInWords(Nin: currency): string; export;
function szMoneyInWords(Nin: currency): PChar; export;
{ Денежная сумма Nin в рублях и копейках прописью

1997, в.2.1, by О.В.Болдырев}

implementation
uses SysUtils, Dialogs, Math;

type

  tri = string[4];
  mood = 1..2;
  gender = (m, f);
  uns = array[0..9] of string[7];
  tns = array[0..9] of string[13];
  decs = array[0..9] of string[12];
  huns = array[0..9] of string[10];
  nums = array[0..4] of string[8];
  money = array[1..2] of string[5];
  endings = array[gender, mood, 1..3] of tri; {окончания числительных и денег}

const

  units: uns = ('', 'один ', 'два ', 'три ', 'четыре ', 'пять ',
    'шесть ', 'семь ', 'восемь ', 'девять ');
  unitsf: uns = ('', 'одна ', 'две ', 'три ', 'четыре ', 'пять ',
    'шесть ', 'семь ', 'восемь ', 'девять ');
  teens: tns = ('десять ', 'одиннадцать ', 'двенадцать ', 'тринадцать ',
    'четырнадцать ', 'пятнадцать ', 'шестнадцать ',
    'семнадцать ', 'восемнадцать ', 'девятнадцать ');
  decades: decs = ('', 'десять ', 'двадцать ', 'тридцать ', 'сорок ',
    'пятьдесят ', 'шестьдесят ', 'семьдесят ', 'восемьдесят ',
    'девяносто ');
  hundreds: huns = ('', 'сто ', 'двести ', 'триста ', 'четыреста ',
    'пятьсот ', 'шестьсот ', 'семьсот ', 'восемьсот ',
    'девятьсот ');
  numericals: nums = ('', 'тысяч', 'миллион', 'миллиард', 'триллион');
  RusMon: money = ('рубл', 'копе');
  ends: endings = ((('', 'а', 'ов'), ('ь', 'я', 'ей')),
    (('а', 'и', ''), ('йка', 'йки', 'ек')));
threadvar

  str: string;

function EndingIndex(Arg: integer): integer;
begin

  if ((Arg div 10) mod 10) <> 1 then
    case (Arg mod 10) of
      1: Result := 1;
      2..4: Result := 2;
    else
      Result := 3;
    end
  else
    Result := 3;
end;

function sMoneyInWords(Nin: currency): string; { Число Nin прописью, как функция }
var
//  str: string;

  g: gender; //род
  Nr: comp; {целая часть числа}
  Fr: integer; {дробная часть числа}
  i, iTri, Order: longint; {триада}

  procedure Triad;
  var
    iTri2: integer;
    un, de, ce: byte; //единицы, десятки, сотни

    function GetDigit: byte;
    begin
      Result := iTri2 mod 10;
      iTri2 := iTri2 div 10;
    end;

  begin
    iTri := trunc(Nr / IntPower(1000, i));
    Nr := Nr - int(iTri * IntPower(1000, i));
    iTri2 := iTri;
    if iTri > 0 then
      begin
        un := GetDigit;
        de := GetDigit;
        ce := GetDigit;
        if i = 1 then
          g := f
        else
          g := m; {женского рода только тысяча}

        str := TrimRight(str) + ' ' + Hundreds[ce];
        if de = 1 then
          str := TrimRight(str) + ' ' + Teens[un]
        else
          begin
            str := TrimRight(str) + ' ' + Decades[de];
            case g of
              m: str := TrimRight(str) + ' ' + Units[un];
              f: str := TrimRight(str) + ' ' + UnitsF[un];
            end;
          end;

        if length(numericals[i]) > 1 then
          begin
            str := TrimRight(str) + ' ' + numericals[i];
            str := TrimRight(str) + ends[g, 1, EndingIndex(iTri)];
          end;
      end; //triad is 0 ?

    if i = 0 then Exit;
    Dec(i);
    Triad;
  end;

begin

  str := '';
  Nr := int(Nin);
  Fr := round(Nin * 100 + 0.00000001) mod 100;
  if Nr > 0 then
    Order := trunc(Log10(Nr) / 3)
  else
    begin
      str := 'ноль';
      Order := 0
    end;
  if Order > High(numericals) then
    raise Exception.Create('Слишком большое число для суммы прописью');
  i := Order;
  Triad;
  str :=
    Format('%s %s%s %.2d %s%s', [Trim(str), RusMon[1], ends[m, 2, EndingIndex(iTri)],
    Fr, RusMon[2], ends[f, 2, EndingIndex(Fr)]]);
  str[1] := (ANSIUpperCase(copy(str, 1, 1)))[1];
  str[Length(str) + 1] := #0;
  Result := str;
end;

function szMoneyInWords(Nin: currency): PChar;
begin

  sMoneyInWords(Nin);
  Result := @(str[1]);
end;

end.


Взято из

Советов по Delphi от


Сборник Kuliba





Число украинской строкой


Число украинской строкой




unitUkrRecog;
{копирайт непомню чей. Был для русских циферок, а я переделал под
украинские}
{если кто что найдет пришлите

}
{by Andrew Tkachenko, proektwo@netcity.ru, Ukraine,

}
interface

const

  UkrMonthString: array[1..12] of string[9] = (
    'січня', 'лютого', 'березня', 'квiтня', 'травня',
    'червня', 'липня', 'серпня', 'вересня', 'жовтня',
    'листопада', 'грудня');

function UkrRecognizeAmount(Amount: real;
  CurrName, CurrSubname: string): string;

implementation
uses Sysutils;

function UkrRecognizeAmount(Amount: real;
  CurrName, CurrSubname: string): string;
{* CurrName in [грн.]

CurrSubName in [коп.]
Распознается число <= 999 999 999 999.99*}
const suffBL: string = ' ';

  suffDCT: string = 'дцять';
  suffNA: string = 'надцять ';
  suffDCM: string = 'десят';
  suffMZ: string = 'ь';
  sot: string = 'сот';
  st: string = 'ст';
  aa: string = 'а';
  ee: string = 'и'; {e}
  ii: string = 'і'; {и}
  oo: string = 'о';
  ov: string = 'ів'; {ов}
  C2: string = 'дв';
  C3: string = 'тpи';
  C4: string = 'чотир';
  C5: string = 'п''ят';
  C6: string = 'шіст';
  C7: string = 'сім';
  C8: string = 'вісім';
  C9: string = 'дев''ят';
var

  i: byte;
  sAmount, sdInt, sdDec: string;
  IsMln, IsTha {,IsDcm}, IsRange1019: boolean;
  currNum, endMlx, sResult: string;
begin

  if (amount <= 0) or (amount > 999999999999.99) then
    begin
      Result := '<<<< Ошибка в диапазоне >>>>';
      Exit;
    end;
  STR(Amount: 16: 2, sAmount);
  sdInt := Copy(sAmount, 1, 13);
  sdDec := Copy(sAmount, 15, 2);
  IsMln := false;
//IsDcm:=false;
  IsTha := false;
  IsRange1019 := false;
  sResult := '';

  for i := 1 to 13 do
    begin
      currNum := Copy(sdInt, i, 1);

      if currNum <> suffBL then
        begin
          case i of
            5, 6, 7: if currNum <> '0' then IsMln := true;
            8, 9, 10: if currNum <> '0' then IsTha := true;
          end;

          if i in [2, 5, 8, 11] then {сотни}
            begin
              if currNum = '1' then sResult := sResult + st + oo + suffBL;
              if currNum = '2' then sResult := sResult + C2 + ii + st + ii + suffBL;
              if currNum = '3' then sResult := sResult + C3 + st + aa + suffBL;
              if currNum = '4' then sResult := sResult + C4 + ee + st + aa + suffBL;
              if currNum = '5' then sResult := sResult + C5 + sot + suffBL;
              if currNum = '6' then sResult := sResult + C6 + sot + suffBL;
              if currNum = '7' then sResult := sResult + C7 + sot + suffBL;
              if currNum = '8' then sResult := sResult + C8 + sot + suffBL;
              if currNum = '9' then sResult := sResult + C9 + sot + suffBL;
            end;
          if i in [3, 6, 9, 12] then {десятки}
            begin
              if currNum = '1' then IsRange1019 := true;
              if currNum = '2' then sResult := sResult + C2 + aa + suffDCT + suffBL;
              if currNum = '3' then sResult := sResult + C3 + suffDCT + suffBL;
              if currNum = '4' then sResult := sResult + 'соpок ';
              if currNum = '5' then
                sResult := sResult + C5 + suffMZ + suffDCM + suffBL;

              if currNum = '6' then
                sResult := sResult + C6 + suffMZ + suffDCM + suffBL;

              if currNum = '7' then
                sResult := sResult + C7 + suffMZ + suffDCM + suffBL;

              if currNum = '8' then
                sResult := sResult + C8 + suffMZ + suffDCM + suffBL;

              if currNum = '9' then
                sResult := sResult + 'дев''ян' + oo + st + oo + suffBL;

            end;
          if i in [4, 7, 10, 13] then {единицы}
            begin
              if (currNum = '0') then
                if IsRange1019 then sResult := sResult + suffDCM + suffMZ + suffBL;
              if (currNum = '1') then
                begin
                  if (i = 13) and (not IsRange1019) then
                    sResult := sResult + 'одна '
                  else
                    begin
                      if (i = 10) and (IsRange1019) then
                        sResult := sResult + 'оди'
                      else if (i = 10) and (not IsRange1019) then
                        sResult := sResult + 'одна '
                      else
                        sResult := sResult + 'один' {ин};

                      if IsRange1019 and (i = 13) then
                        sResult := sResult + 'адцять' + suffBL

                      else if IsRange1019 then
                        sResult := sResult + suffNA
                      else
                        sResult := sResult + suffBL;
                    end;
                end;
              if (currNum = '2') then
                begin
                  sResult := sResult + C2;
                  if (i = 10) and (IsRange1019 = False) then
                    sResult := sResult + ii
                  else if (i = 10) or (IsRange1019) then
                    sResult := sResult + aa
                  else
                    sResult := sResult + {aa} ii;
                  if IsRange1019 then
                    sResult := sResult + suffNA
                  else
                    sResult := sResult + suffBL;
                end;
              if (currNum = '3') then
                begin
                  sResult := sResult + C3;
                  if IsRange1019 then
                    sResult := sResult + suffNA
                  else
                    sResult := sResult + suffBL;
                end;
              if (currNum = '4') then
                begin
                  sResult := sResult + C4;
                  if IsRange1019 then
                    sResult := sResult + suffNA
                  else
                    sResult := sResult + ee + suffBL;
                end;
              if (currNum = '5') then
                begin
                  sResult := sResult + C5;
                  if IsRange1019 then
                    sResult := sResult + suffNA
                  else
                    sResult := sResult + suffMZ + suffBL;
                end;
              if (currNum = '6') then
                begin
                  sResult := sResult + C6;
                  if IsRange1019 then
                    sResult := sResult + suffNA
                  else
                    sResult := sResult + suffMZ + suffBL;
                end;
              if (currNum = '7') then
                begin
                  sResult := sResult + C7;
                  if IsRange1019 then
                    sResult := sResult + suffNA
                  else
                    sResult := sResult + suffBL;
                end;
              if (currNum = '8') then
                begin
                  sResult := sResult + C8;
                  if IsRange1019 then
                    sResult := sResult + suffNA
                  else
                    sResult := sResult + suffBL;
                end;
              if (currNum = '9') then
                begin
                  sResult := sResult + C9;
                  if IsRange1019 then
                    sResult := sResult + suffNA
                  else
                    sResult := sResult + suffMZ + suffBL;
                end;
            end;

          endMlx := '';
          case i of
            4:
              begin
                if IsRange1019 then
                  endMlx := ov + suffBL
                else if currNum = '1' then
                  endMlx := suffBL
                else if (currNum = '2') or (currNum = '3') or (currNum = '4') then
                  endMlx := aa + suffBL
                else
                  endMlx := ov + suffBL;
                sResult := sResult + 'мiльярд' + endMlx;
              end;
            7: if IsMln then
                begin
                  if IsRange1019 then
                    endMlx := ov + suffBL
                  else if currNum = '1' then
                    endMlx := suffBL
                  else if (currNum = '2') or (currNum = '3') or (currNum = '4') then
                    endMlx := aa + suffBL
                  else
                    endMlx := ov + suffBL;
                  sResult := sResult + 'мiльйон' + endMlx;
                end;
            10: if IsTha then
                begin
                  if IsRange1019 then
                    endMlx := suffBL
                  else if currNum = '1' then
                    endMlx := aa + suffBL
                  else if (currNum = '2') or (currNum = '3') or (currNum = '4') then
                    endMlx := ii + suffBL
                  else
                    endMlx := suffBL;
                  sResult := sResult + 'тисяч' + endMlx;
                end;
          end; {case}
          if i in [4, 7, 10, 13] then IsRange1019 := false;
        end; {IF}
    end; {FOR}

  sResult := sResult + CurrName + ',' + suffBL + sdDec + suffBL + CurrSubname;
  sResult := AnsiUpperCase(sResult[1]) + Copy(sResult, 2, length(sResult) - 1);
  Result := sResult;
end;

end.

С уважением,

Andrew Tkachenko

ООО "Проект ВО"
Украина, г.Харьков

Взято из

Советов по Delphi от


Сборник Kuliba





Читаем CSV текстовый файл в StringGrid


Читаем CSV текстовый файл в StringGrid





procedureReadTabFile(FN: TFileName; FieldSeparator:
Char; SG: TStringGrid);
var 
  i: Integer; 
  S: string; 
  T: string; 
  Colonne, ligne: Integer; 
  Les_Strings: TStringList; 
  CountCols: Integer; 
  CountLines: Integer; 
  TabPos: Integer; 
  StartPos: Integer; 
  InitialCol: Integer; 
begin 
  Les_Strings := TStringList.Create; 
  try 
    Les_Strings.LoadFromFile(FN); 
    CountLines := Les_Strings.Count + SG.FixedRows; 
    T := Les_Strings[0]; 
    for i := 0 to Length(T) - 1 do Inc(CountCols,
    Ord(IsDelimiter(FieldSeparator, T, i)));
    Inc(CountCols, 1 + SG.FixedCols); 
    if CountLines > SG.RowCount then SG.RowCount := CountLines; 
    if CountCols > SG.ColCount then SG.ColCount := CountCols; 
    InitialCol := SG.FixedCols - 1;
    Ligne := SG.FixedRows - 1; 
    for i := 0 to Les_Strings.Count - 1 do 
    begin 
      Colonne := InitialCol; 
      Inc(Ligne); 
      StartPos := 1; 
      S := Les_Strings[i]; 
      TabPos := Pos(FieldSeparator, S); 
      repeat 
        Inc(Colonne); 
        SG.Cells[Colonne, Ligne] := Copy(S, StartPos, TabPos - 1); 
        S := Copy(S, TabPos + 1, 999); 
        TabPos := Pos(FieldSeparator, S); 
      until TabPos = 0; 
    end; 
  finally 
    Les_Strings.Free; 
  end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  Screen.Cursor := crHourGlass; 
  ReadTabFile('C:\TEST.TXT', #9, StringGrid1); 
  Screen.Cursor := crDefault; 
end;

Взято из







Читаем заголовок exe файла


Читаем заголовок exe файла





{ You'll need a OpenDialog to open a Exe-File and a Memo to show the file informations } 



procedure DumpDOSHeader(const h: IMAGE_DOS_HEADER; Lines: TStrings); 
begin 
  Lines.Add('Dump of DOS file header'); 
  Lines.Add(Format('Magic number: %d', [h.e_magic])); 
  Lines.Add(Format('Bytes on last page of file: %d', [h.e_cblp])); 
  Lines.Add(Format('Pages in file: %d', [h.e_cp])); 
  Lines.Add(Format('Relocations: %d', [h.e_crlc])); 
  Lines.Add(Format('Size of header in paragraphs: %d', [h.e_cparhdr])); 
  Lines.Add(Format('Minimum extra paragraphs needed: %d', [h.e_minalloc])); 
  Lines.Add(Format('Maximum extra paragraphs needed: %d', [h.e_maxalloc])); 
  Lines.Add(Format('Initial (relative) SS value: %d', [h.e_ss])); 
  Lines.Add(Format('Initial SP value: %d', [h.e_sp])); 
  Lines.Add(Format('Checksum: %d', [h.e_csum])); 
  Lines.Add(Format('Initial IP value: %d', [h.e_ip])); 
  Lines.Add(Format('Initial (relative) CS value: %d', [h.e_cs])); 
  Lines.Add(Format('File address of relocation table: %d', [h.e_lfarlc])); 
  Lines.Add(Format('Overlay number: %d', [h.e_ovno])); 
  Lines.Add(Format('OEM identifier (for e_oeminfo): %d', [h.e_oemid])); 
  Lines.Add(Format('OEM information; e_oemid specific: %d', [h.e_oeminfo])); 
  Lines.Add(Format('File address of new exe header: %d', [h._lfanew])); 
  Lines.Add(''); 
end; 

procedure DumpPEHeader(const h: IMAGE_FILE_HEADER; Lines: TStrings); 
var 
  dt: TDateTime; 
begin 
  Lines.Add('Dump of PE file header'); 
  Lines.Add(Format('Machine: %4x', [h.Machine])); 
  case h.Machine of 
    IMAGE_FILE_MACHINE_UNKNOWN : Lines.Add(' MACHINE_UNKNOWN '); 
    IMAGE_FILE_MACHINE_I386: Lines.Add(' Intel 386. '); 
    IMAGE_FILE_MACHINE_R3000: Lines.Add(' MIPS little-endian, 0x160 big-endian '); 
    IMAGE_FILE_MACHINE_R4000: Lines.Add(' MIPS little-endian '); 
    IMAGE_FILE_MACHINE_R10000: Lines.Add(' MIPS little-endian '); 
    IMAGE_FILE_MACHINE_ALPHA: Lines.Add(' Alpha_AXP '); 
    IMAGE_FILE_MACHINE_POWERPC: Lines.Add(' IBM PowerPC Little-Endian '); 
    // some values no longer defined in winnt.h 
    $14D: Lines.Add(' Intel i860'); 
    $268: Lines.Add(' Motorola 68000'); 
    $290: Lines.Add(' PA RISC'); 
    else 
      Lines.Add(' unknown machine type'); 
  end; { Case } 
  Lines.Add(Format('NumberOfSections: %d', [h.NumberOfSections])); 
  Lines.Add(Format('TimeDateStamp: %d', [h.TimeDateStamp])); 
  dt := EncodeDate(1970, 1, 1) + h.Timedatestamp / SecsPerDay; 
  Lines.Add(FormatDateTime(' c', dt)); 

  Lines.Add(Format('PointerToSymbolTable: %d', [h.PointerToSymbolTable])); 
  Lines.Add(Format('NumberOfSymbols: %d', [h.NumberOfSymbols])); 
  Lines.Add(Format('SizeOfOptionalHeader: %d', [h.SizeOfOptionalHeader])); 
  Lines.Add(Format('Characteristics: %d', [h.Characteristics])); 
  if (IMAGE_FILE_DLL and h.Characteristics) <> 0 then 
    Lines.Add(' file is a DLL') 
  else if (IMAGE_FILE_EXECUTABLE_IMAGE and h.Characteristics) <> 0 then 
    Lines.Add(' file is a program'); 
  Lines.Add(''); 
end; 

procedure DumpOptionalHeader(const h: IMAGE_OPTIONAL_HEADER; Lines: TStrings); 
begin 
  Lines.Add('Dump of PE optional file header'); 
  Lines.Add(Format('Magic: %d', [h.Magic])); 
  case h.Magic of 
    $107: Lines.Add(' ROM image'); 
    $10b: Lines.Add(' executable image'); 
    else 
      Lines.Add(' unknown image type'); 
  end; { If } 
  Lines.Add(Format('MajorLinkerVersion: %d', [h.MajorLinkerVersion])); 
  Lines.Add(Format('MinorLinkerVersion: %d', [h.MinorLinkerVersion])); 
  Lines.Add(Format('SizeOfCode: %d', [h.SizeOfCode])); 
  Lines.Add(Format('SizeOfInitializedData: %d', [h.SizeOfInitializedData])); 
  Lines.Add(Format('SizeOfUninitializedData: %d', [h.SizeOfUninitializedData])); 
  Lines.Add(Format('AddressOfEntryPoint: %d', [h.AddressOfEntryPoint])); 
  Lines.Add(Format('BaseOfCode: %d', [h.BaseOfCode])); 
  Lines.Add(Format('BaseOfData: %d', [h.BaseOfData])); 
  Lines.Add(Format('ImageBase: %d', [h.ImageBase])); 
  Lines.Add(Format('SectionAlignment: %d', [h.SectionAlignment])); 
  Lines.Add(Format('FileAlignment: %d', [h.FileAlignment])); 
  Lines.Add(Format('MajorOperatingSystemVersion: %d', [h.MajorOperatingSystemVersion])); 
  Lines.Add(Format('MinorOperatingSystemVersion: %d', [h.MinorOperatingSystemVersion])); 
  Lines.Add(Format('MajorImageVersion: %d', [h.MajorImageVersion])); 
  Lines.Add(Format('MinorImageVersion: %d', [h.MinorImageVersion])); 
  Lines.Add(Format('MajorSubsystemVersion: %d', [h.MajorSubsystemVersion])); 
  Lines.Add(Format('MinorSubsystemVersion: %d', [h.MinorSubsystemVersion])); 
  Lines.Add(Format('Win32VersionValue: %d', [h.Win32VersionValue])); 
  Lines.Add(Format('SizeOfImage: %d', [h.SizeOfImage])); 
  Lines.Add(Format('SizeOfHeaders: %d', [h.SizeOfHeaders])); 
  Lines.Add(Format('CheckSum: %d', [h.CheckSum])); 
  Lines.Add(Format('Subsystem: %d', [h.Subsystem])); 
  case h.Subsystem of 
    IMAGE_SUBSYSTEM_NATIVE: 
      Lines.Add(' Image doesnot require a subsystem. '); 
    IMAGE_SUBSYSTEM_WINDOWS_GUI: 
      Lines.Add(' Image runs in the Windows GUI subsystem. '); 
    IMAGE_SUBSYSTEM_WINDOWS_CUI: 
      Lines.Add(' Image runs in the Windows character subsystem. '); 
    IMAGE_SUBSYSTEM_OS2_CUI: 
      Lines.Add(' image runs in the OS/2 character subsystem. '); 
    IMAGE_SUBSYSTEM_POSIX_CUI: 
      Lines.Add(' image run in the Posix character subsystem. '); 
    else 
      Lines.Add(' unknown subsystem') 
  end; { Case } 
  Lines.Add(Format('DllCharacteristics: %d', [h.DllCharacteristics])); 
  Lines.Add(Format('SizeOfStackReserve: %d', [h.SizeOfStackReserve])); 
  Lines.Add(Format('SizeOfStackCommit: %d', [h.SizeOfStackCommit])); 
  Lines.Add(Format('SizeOfHeapReserve: %d', [h.SizeOfHeapReserve])); 
  Lines.Add(Format('SizeOfHeapCommit: %d', [h.SizeOfHeapCommit])); 
  Lines.Add(Format('LoaderFlags: %d', [h.LoaderFlags])); 
  Lines.Add(Format('NumberOfRvaAndSizes: %d', [h.NumberOfRvaAndSizes])); 
end; 

// Example Call, Beispielaufruf: 

procedure TForm1.Button1Click(Sender: TObject); 
var 
  fs: TFilestream; 
  signature: DWORD; 
  dos_header: IMAGE_DOS_HEADER; 
  pe_header: IMAGE_FILE_HEADER; 
  opt_header: IMAGE_OPTIONAL_HEADER; 
begin 
  memo1.Clear; 
  with Opendialog1 do 
  begin 
    Filter := 'Executables (*.EXE)|*.EXE'; 
    if Execute then 
    begin 
      fs := TFilestream.Create(FileName, fmOpenread or fmShareDenyNone); 
      try 
        fs.read(dos_header, SizeOf(dos_header)); 
        if dos_header.e_magic <> IMAGE_DOS_SIGNATURE then 
        begin 
          memo1.Lines.Add('Invalid DOS file header'); 
          Exit; 
        end; 
        DumpDOSHeader(dos_header, memo1.Lines); 

        fs.seek(dos_header._lfanew, soFromBeginning); 
        fs.read(signature, SizeOf(signature)); 
        if signature <> IMAGE_NT_SIGNATURE then 
        begin 
          memo1.Lines.Add('Invalid PE header'); 
          Exit; 
        end; 

        fs.read(pe_header, SizeOf(pe_header)); 
        DumpPEHeader(pe_header, memo1.Lines); 

        if pe_header.SizeOfOptionalHeader > 0 then 
        begin 
          fs.read(opt_header, SizeOf(opt_header)); 
          DumpOptionalHeader(opt_header, memo1.Lines); 
        end; 
      finally 
        fs.Free; 
      end; { finally } 
    end; 
  end; 
end; 

Взято с сайта



Чтение из открытого файла


Чтение из открытого файла



Даже если файл открыт с низкими привелегиями (используя ReadOnly, ShareReadWrite) , иногда открытие уже открытого файла может приводить к ошибкам, особенно, если это файл интенсивно используется другим приложением. Самый простой способ решить эту проблемму - это использовать MemoryStream вместо непосредственного доступа к файлу:

var Memory: TMemoryStream;

begin
  Memory := TMemoryStream.Create;
  try
    Memory.LoadFromFile('busyfile.dat'); // это он!!
    ..
      Memory.Read(...); // Вы можете использовать методы чтения как у файлов
      Memory.Seek(...);
      FileSize := Memory.Size;
      ..
  finally
    Memory.Free;
  end;
end;

Данный способ никогда не открывает файл, а заместо этого создаёт копию его в памяти. Конечно Вы можете и записать в поток (Stream) в Памяти(Memory), но изменения не будут записаны на диск до тех пор, пока Вы не запишете их в файл (командой SaveToFile).

Автор ответа: neutrino

Комментарий от Vit

Решение хорошее, но накладно если файл большой...
Взято с Vingrad.ru



var b:string[15];
begin
with TFileStream.create('c:\MyFile.doc', fmShareDenyNone) do
try
read(b,14);
showmessage(b);
finally
Free;
end;

Автор ответа: Vit
Взято с Vingrad.ru


procedure TForm1.Button1Click(Sender: TObject);
type
AnyType = byte; // ??? ???? ?????
var
F: file of AnyType;
const
FName = 'D:/Exp.exe'; //?????????? ????
begin
begin
AssignFile(F, FName); { File selected in dialog }
FileMode:=fmOpenRead;
Reset(F);
// ...
// ...
CloseFile(F);
FileMode:=fmOpenReadWrite;
end;
end;

Автор ответа: PILOTIK
Взято с Vingrad.ru




Чтение OLE из Blob поля Paradox


Чтение OLE из Blob поля Paradox




Автор: Eryk

...после моих дискуссий с людьми из службы технической поддержки Borland вывод один -- это невозможно!

Попробуйте так:

procedureTForm1.SpeedButton1Click(Sender: TObject);
var
  b: TBlobStream;
begin
  try
    b := TBlobStream.Create((Table1.FieldByName('OLE') as TBlobField),bmRead);
    OLEContainer1.LoadFromStream(b);
  finally
    b.free;
  end;
end;

...и:

procedure TForm1.SpeedButton2Click(Sender: TObject);
var
  b: TBlobStream;
begin
  try
    Table1.Insert;
    b := TBlobstream.Create((Table1.FieldByName('OLE') as TBlobField),bmReadWrite);
    OLEContainer1.SaveToStream(b);
    Table1.Post;
  finally
    b.free;
  end;
end;

Я, кажется, припоминаю несколько ошибок GPFs с этим кодом, но это, вероятно, связано с тем, что я использую WinNT с другим распределением памяти... тем не менее, основные функции работали как положено (т.е. данные сохранялись и загружались). Основная специфика проявилась в том, что PdoxWIN не смог прочесть данные TOLEContainer. Но это результаты моих экспериментов и предположений, исходя из которых PdoxWIN ожидает 8-байтовый заголовок BLOB-поля, который ему просто не дает TOLEContainer... если это так, то это легко обойти.

Взято из






Что делает inf-файл?


Что делает inf-файл?




Он позволяет осуществить:

Создание элементов реестра
Определение инициализационных параметров (INI-settings)
Копирование файлов с дистрибутива и размещение их в системе
Инсталляция устройств
Управление другими INF-фаилами
Конфигурирование опций устройств

INF-файлы представляют собой инициализационные файлы, которые конфигурируют
устройство или приложение в вашей системе и задают его элементы в реестре.
INF-файлы обычно поставляются производителем продукта вместе с устройством
или приложением. Кроме того, можно их найти на электронных досках объявле-
ний и других on-line сервисах. INF-файлы понадобятся вам для многих обычных
(не РпР) устройств, которые вам нужно будет конфигурировать для работы с
Windows 95. Как правило, INF-файлы включают список допустимых логических
конфигураций, имена файлов драйверов устройств и г. д. В ряде случаев вам
потребуется самим писать INF-файлы для устройств или программного обеспече-
ния. Формат lNF-файлов аналогичен формату INIфайлов, которые использовались
в Windows З.х, включая квадратные скобки, ключи и разделы, используемые то-
лько Windows 95.

Структура INF-файла
Когда вы инсталлируете новое устройство. Windows ищет INF-фаилы для этого
устройства, используя при этом идентификатор устройства (device ID). Собрав
из INF-фаила всю необходимую информацию, система создает в реестре элемент
для этого устройства под ключом HKEY_LOCAL_MACHINE. Значения из INF-файла
копируются в элемент реестра, соответствующий драйверу устройства. Такие
значения, как DevLoader= и Driverdesc= включаются в элемент аппаратного
драйвера Driver=. Элемент Еnum содержит значения Driver= и ConfigFlags=.
INF-фаилы представляют собой файлы в формате ASCII, состоящие из нескольких
разделов. Каждый раздел предназначен для выполнения определенной задачи.
Имена разделов обычно заключаются в квадратные скобки. Типичные элементы
представляют собой ключ и значение, соединенные знаком равенства. В раздел
можно включить одно или несколько значений. Кроме того, в состав элемента
можно включать комментарии, отделяя их символом точки с запятой, например:

[section] 
keyname=value ;эта часть строки является комментарием 

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

Типы информационных файлов:
Layout (Формат). Определяет информацию о диске и номере версии, а также
содержит список всех файлов с указанием диска, на котором они располагают-
ся.
Selective Install (Избирательная инсталляция). Определяет части инстал-
ляции, являющиеся необязательными компонентами, а также те ее части, кото-
рые зависят от инсталляции других компонентов. Например, Microsoft Fax тре-
бует предварительной загрузки Microsoft Exchange. Вы имеете возможность уп-
равлять инсталляцией компонент этих типов.
Application/Installation, APPS.INF (Приложения/Инсталляция). Обнаружива-
ет используемые вами приложения MS-DOS и устанавливает для них параметры
окружения. Эти lNF-файлы содержат настройки и параметры для многих приложе-
ний DOS. Как правило, это самый большой информационный файл в вашей систе-
ме. В его состав входят многие виды настройки памяти, настройки расширенной
памяти (XMS), а также другие параметры, которые в Windows З.х содержались в
настройках PIF
Device Installation and Configuration (Инсталляция и конфигуриро вание
устройств). Это наиболее общий из всех информационных файлов на котором мы
до сих пор концентрировали все внимание. Эти файлы описывают параметры на-
стройки для конкретных физических устройств. Если вы имеете драйвер устрой-
ства ранних версий, в INF-файле будет содержаться информация об этом уст-
ройстве. Устройства Plug and Play, с другой стороны, помещают информацию о
себе прямо в реестр.

Общая организация lNF-файла
Раздел каждого устройства в INF-файлс состоит из следующих разделов:

Раздел [Version].
Идентифицирует INF и класс поддерживаемого устройства.
Ниже перечислен список некоторых устройств, которые вы можете включить:

adapter                 keyboard        NetService 
 
CDROM                   MCADevices      NetTrans (сетевые транспорты) 
diskdrive               media           nodriver 
dispaly                 modem           PCMCIA 
EISADevices             monitor         ports 
Fdc                     mouse           printer 
Hdc                     MTD             SCSIAdapter 

Раздел [Manufacturer].
Идентифицирует производителя устройства (например, Link, Micro, и т.п.) и
соответствующих продуктов. Каждый INF-файл должен иметь по крайней мере
один раздел [ Manufacturer].

Раздел [Install].
Содержит информацию о физических атрибутах устройства и его драйверах.

Раздел [Classlnstall].
Этот раздел необязателен. Он идентифицирует новый класс для указанного уст-
ройства в INF-фаиле

Раздел [String].
Идентифицирует локализованные строки в INF-фаиле

Раздел [Miscellaneous].
Содержит информацию о том, как устройства управляются пользовательским ин-
терфейсом W95.

Элементы APPS.INF
В разделе [appname] файла APPS.INF вы найдете элементы, перечисленные в
табл. Используя эти элементы вы сможете быстрее перенести в W95 настройки
PIF из ваших старых инсталляций Windows.
Многие из приложений, перечисленных в файле APPS.INF, представляют собой
старые игры для MS-DOS. Если вы сталкиваетесь с тем, что игра не работает в
среде W95, просмотрите этот файл. Возможно, вам удастся модифицировать ка-
кой-либо из его элементов таким образом, чтобы игра запустилась или стала
работать лучше. Если вы вносите изменения в файл APPS.INF, вам потребуется
перезагрузить W95, чтобы внесенные изменения попали в реестр. Помимо редак-
тирования файла APPS.INF, некоторые из параметров вы можете изменить, от-
крыв страницу свойств конкретного приложения.
Ниже приведен пример раздела [аррname]:

[PRODIGY.EXE] 
LowMem=440 
EMSMen=None 
XMSMem=None 
Enable=lml 
Disable=win,hma 

В этой части файла APPS.INF раздел [appname] замещается именем исполняемого
модуля, например, PRODIGY.EXE, PARADOX.EXE и т.п.

Имя элемента реестра           Описание ключа                       Значение 
 
ALLOWSSAVER              Позволяет появляться заставке              sav 
(работает в REALMODE)    при работающих программах DOS. 
                         Настройка по умолчанию 
 
ALTENTER                 Позволяет использовать клавиатурную        аеn 
                         комбинацию + для переклю- 
                         чения между полноэкранным и оконным 
                         режимами. Настройка по умолчанию. 
 
ALTESC                   Позволяет использовать выход с помощью     Aes 
                         клавиатурной комбинации -. 
                         Настройка по умолчанию. 
 
ALTPRTSCRN               Позволяет выполнять моментальный снимок    Psc 
                         экрана с помощью клавиатурной комбинации 
                         +. Настройка по умолчанию. 
 
ALTSPACE                 Позволяет использовать клавиатурную        aps 
                         комбинацию + для отображения 
                         системного меню. Настройка по умолчанию. 
 
ALTTAB                   Позволяет использовать клавиатурную ком-   Ata 
                         бинацию для переключения между приложе- 
                         ниями. Настройка по умолчанию. 
 
BACKGROUND               Дает приложению указание работать в        win 
                         фоновом режиме. Настройка по умолчанию. 
 
CDROM                    Позволяет использовать драйвер MSCDEX.     cdr 
(работает в REALMODE)    Настройка по умолчанию. 
 
CLOSEONEXIT              Закрывает при выходе окно DOS. He явля-    cwe 
                         ется настройкой по умолчанию. 
 
CRTLESC                  Позволяет закрывать приложение нажатием    ces 
                         клавиатурной комбинации +. 
                         Настройка по умолчанию. 
 
DETECTIDLE              Задает чувствительность в неактивном сос-   dit 
                        тоянии. Настройка по умолчанию. 
 
DISKLOCK                Позволяет осуществлять прямой доступ к      dsk 
(работает в REALMODE)   диску. 
 
EMS                     Активизирует EMS386 для программ DOS.       ems 
(работает в REALMODE)   Настройка по умолчанию. 
 
EMSLOCKED               Указывает на блокировку памяти EMS          eml 
 
EMULATEROM              Указывает на необходимость использо-        emt 
                        вания быстрой эмуляции ROM. Настройка 
                        по умолчанию. 
 
EXCLUSIVE               Работает в эксклюзивном режиме. Этот        exc 
                        параметр игнорируется. 
 
FASTPASTE               Активизирует быструю вставку из прило-      aft 
                        жения. Настройка по умолчанию. 
 
GLOBALMEM               Активизирует глобальную защиту памяти       gmp 
 
LOWLOCKED               Указывает на то, что нижняя память          lml 
                        (до 640 Кб) заблокирована. Этот параметр 
                        игнорируется. 
 
MOUSE                   Активизирует функции мыши. Настройка по     mse 
(работает в REALMODE)   умолчанию. 
 
NETWORK                 Разрешает программе DOS получать доступ     net 
(работает в REALMODE)   к сетевым дискам и принтерам. Настройка 
                        по умолчанию. 
 
PRIVATECFG              Позволяет программе DOS использовать пер-   cfg 
(работает в REALMODE)   сональный файл CONFIG.SYS. He является 
                        настройкой по умолчанию. 
 
REALMODE                Запускает программу в реальном режиме DOS.  dos 
                        He является настройкой по умолчанию. 
 
RETAINVRAM              Дает указание сохранить видеопамять.        rvm 
                        Этот параметр игнорируется. 
 
UNIQUESETTINGS          Запускает программы DOS в отдельных DOS-    uus 
                        сеансах. Не является настройкой по 
                        умолчаний. 
 
USEHMA                  Дает указание использовать НМА (верхние     hma 
                        адреса памяти). Значение по умолчанию. 
 
VESA                    Дает программам DOS получать доступ к       vsa 
(работает в REALMODE)   продвинутым графическим возможностям. 
 
WINDOWED                Запускает приложение в окне, а не в         win 
                        полноэкранном режиме. Настройка по 
                        умолчанию. 
 
WINLIE                  Не позволяет программам DOS обнаруживать    lie 
                        W95. Не яаляется параметром по умолчанию. 
 
XMSLOCKED               Дает указание блокировать память XMS.       Xml 

В файле APPS.INF доступны, но не реализованы следующие параметры:

DISPLAYTBAR (dtb) Отображает панель инструментов.
EXCLMOUSE (exm) Разрешает режим монопольного использования мыши
QUICKEDIT (qme) Активизирует для мыши режим быстрого редактирования
WARNIFACTIVE (wia). Позволяет подавать предупреждения, если приложение
DOS еще активно

Справочник по разделам
В нижеприведенных таблицах описаны все ключевые слова и значения, ассоци-
ированные с конкретными разделами. Синтаксис раздела [Version] приведен ни-
же. Квадратные скобки используются для обозначения начала нового раздела.
Для того чтобы настройки INF были понятны W95 и реестру, квадратные скобки
обязательно должны присутствовать.

[Version] 
Signature=$CHICAGO$ 
Class=name_of_class 
Provider=%File_creator% 
LayoutFile=filename.inf 

Ключевое слово Значение       Описание 
 
Signature      $Chicago$    Задает операционную систему для INF-файла. 
                            На момент написания большинства INF-файлов 
                            кодовое название Windows 95 было следующим: 
                            Chicago. 
 
Class         name_of_class Указывает класс, который будет определен в ре- 
                            естре. Список общих классов устройств, которые 
                            вы можете ввести сюда, приведен в данном при- 
                            ложении ранее. 
 
LayoutFile     filename.inf Эта строка определяет имя INF-файла, содержа- 
                            щего имена исходного диска и файлов, которые 
                            должны быть включены для инсталляции этого 
                            устройства. Если его не определить, то по умол- 
                            чанию файл имеет имя LAYOUT.INF. Если вы не 
                            включите эти данные в раздел Version, то должны 
                            будете включить в файл APPS.INF разделы 
                            SourceDiskName и SourceDiskFiles. 

Синтаксис раздела [Manufacturer] приведен ниже.

[Manufacturer] 
"manufacturer" %string_value%=manufacturer_section 

Информация раздела [Manufacturer]

Ключевое слово          Описание 
 
"manufacturer"          Имя производителя этого устройства, заключенное в 
                        кавычки. Сюда можно включить любую строку. Это клю- 
                        чевое слозо является необязательным. 
 
%string_value%          Указывает имя строки, включенной в раздел Stings 
                        INF-файла. Строки должны быть заключены в символы 
                        процента (%). 
 
manufacturer_section    Указывает на раздел Manufacturer Name в INF-файле. 

Раздел [Manufacturer Name] включает описания устройства для указанного уст-
ройства Ключевые слова, используемые в этом разделе, описаны в таблице.
Синтаксис этого раздела выглядит следующим образом:

[name_of_manufacturer] 
description of deviсe=install_section,ID_of_device[compatible_device_IDs,...] 

Информация раздела [Manufacturer Name] 
 
Ключевое слово           Описание 
 
description_of_device      Описание инсталлируемого устройства. 
install_section            Указывает имя раздела Install для этого устройства. 
ID_of_device               Идентификатор (ID) инсталлируемого устройства. 
[compatible_device_IDs,...] Содержит Ссылки на устройства, совместимые с 
                            данным. В этот список можно включить несколько 
                            устройств, разделив их запятыми. 

Раздел [File List] можно использовать для указания файлов, которые вы хоти-
те скопировать, переименовать или удалить. В зависимости от элемента разде-
ла [Install] вы можете использовать три следующих синтаксических параметра:

[file_list section] 
new_filename, old_filename 

Эта конструкция используется для элементов RenFiles. Допускается вклююние
любого количества элементов new_filename, old_filename.

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

[file_list section] 
filename 

Параметр filename обозначает имя файла, который вы хотите удалить.

Для элемента CopyFiles используется следующий синтаксис. Параметры
source_filename и temporary_filename в этой конструкции являются необязате-
льными.

[file_list section] 
destination_filename,source_filename,temporary_filename 

Ниже приведен образец синтаксиса раздела [Install]. Этот раздел включает
дополнительные разделы INF-файла, которые содержат описания устройства. В
правой части выражения, после знака равенства, можно указать несколько зна-
чений, разделенных запятыми.

[name_of_install_section] 
LogConfig=section_name 
Copyfiles=file_list_section 
Renfiles=file_list_section 
DelFiles=file_list_section 
UpdateInis=UpdateIni_section_name 
UpdateIniFields=UpdateIniFields_section_name 
AddReg=AddRegitry_section 
DelReg=DelRegitry_section 
Ini2Reg=IniToRegistry_section 
UpdateCfgSys=UpdateConfig_section 
UpdateAutoBat=UpdateAutoexec_section 
Reboot или Restart 

Информация раздела [Install]

Ключевое слово             Значение         Описание 
 
[name_of_install_section]                    Содержит имя устройства, соответ- 
                                             ствующего информации, приведен- 
                                             ной в этом разделе. В разделе 
                                             ManufacturerName INF-файла дол- 
                                             жна присутствовать ссылка на 
                                             этот раздел 
 
LogСonfig                section_name        Содержит информацию о разделах 
                                             логической конфигурации уст- 
                                             ройства. Значения section_name 
                                             указывают на разделы INF-файла 
                                             в которых содержится информа- 
                                             ция о данном устройстве. 
 
CopyFiles             file_list_section      Содержит информацию, необходимую 
                                             для копирования указанного файла 
                                             или файлов в каталог, указанный 
                                             в разделе File_List. Вы можете 
                                             дать системе указание скопировать 
                                             отдельный файл. Для этого перед 
                                             именем файла необходимо включить 
                                             символ @. При этом файл будет 
                                             скопирован в каталог 
                                             DefaultDestDir, определенный в 
                                             разделе DestinationDir INF-файла. 
 
RenFiles             fiie_list_section       Позволяет переименовать указан- 
                                             ный файл. Представляет собой 
                                             указатель на раздел File_List 
                                             INF-файла. 
 
DelFiles             file_list_section       Позволяет удалить указанный 
                                             файл. Представляет собой указа- 
                                             тель на раздел FileList INF-файла. 
 
UpdateInis          UpdateIni_section_name   Позволяет указать Значение INI- 
                                             файла, которое вы хотите изме- 
                                             нить через INF-файл. Представля- 
                                             ет собой указатель на раздел 
                                             Update INI. 
 
UpdatelniFields UpdateIniFields_section_name Позволяет изменять, замещать 
                                             или удалять отдельные элементы 
                                             значений INI-файла (в отличие от 
                                             предыдущего параметра, который 
                                             изменял все значение целиком). 
                                             Этот параметр представляет со- 
                                             бой указатель на раздел Update 
                                             IniFields. 
 
AddReg                AddRegistry_section    Позволяет указать подключ или 
                                             значение, которые требуется до- 
                                             бавить в реестр. Представляет 
                                             собой указатель на раздел Add 
                                             Registry. 
 
DelReg                Del_Registry_section   Позволяет указать подключ или 
                                             значение, которые требуется уда- 
                                             лить из реестра. Представляет 
                                             собой указатель на раздел Delete 
                                             Registry 
 
Ini2Reg            IniToRegistry_section     Перемещает в реестр строки и 
                                             разделы из INI-файла. Представ- 
                                             ляет собой указатель на раздел 
                                             Ini to Registry. 
 
UpdateCfgSys        UpdateConfig_section     Содержит указатель на раздел 
                                             Update Config. в этом разделе 
                                             находятся команды, которые 
                                             должны быть добавлены, удалены 
                                             или переименованы в файле 
                                             CONFIG.SYS. 
 
UpdateAutoBat     UpdateAutoexec_section     Содержит указатель на раздел 
                                             Update AutoExec. В этом разделе 
                                             находятся команды, которые мо- 
                                             дифицируют файл AUTOEXEC.BAT. 
 
Reboot или Restart                           Команды, вызывающие перезапуск 
                                             системы или перезагрузку ком- 
                                             пьютера после завершения про- 
                                             граммы установки. 

Ниже приведен пример синтаксиса раздела [Logical Configuration]. Раздел
[LogConfig] необходимо указать в разделе [Install]. Этот раздел содержит
информацию о конфигурации системных ресурсов, включая IRQ, порты ввода/вы-
вода, каналы DMA и т. д. Для каждого включаемого элемента программа Setup
создает запись логической конфигурации в двоичном формате и включает эту
информацию в реестр в раздел driver. INF-файлы могут содержать несколько
(или ни одного) разделов [Logical Configuration]. Ключевые слова и значения
этого раздела описаны в таблице.

[LogConfig Section name] 
ConfigPriority=value_of_priority 
MemConfig=menory_range_settings 
I/OConfig=ioport_settings 
IRQConfig=irq_sectings 
DMAConfig=dma_settings 


Ключевое слово          Значение             Описание 
 
ConfigPriority         value_of_priority     Содержит значение приоритета 
                                             конфигурации для данного устрой- 
                                             ства. 
 
MemConfig          memory_range_settings     Указывает диапазон памяти для 
                                             данного устройства. 
 
I/OConfig           ioport_settings          Позволяет указать для устройства 
                                             конфигурацию портов ввода/вывода. 
 
IRQConfig            irq_settings            Содержит СПИСОК допустимых IRQ 
                                             для данного устройства. Если 
                                             устройство не использует IRQ, 
                                             не следует включать эту 
                                             строку в INF-файл. 
 
DMAConfig             dma_settings           Указывает допустимые значения 
                                             DMA для данного устройства. 

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


Ниже приведен пример синтаксиса раздела [Update AutoExec]. Имя раздела
[UpdateAutoBat] должно быть указано в разделе [Install]. Этот раздел соде-
ржит команды, манипулирующие строками в файле AUTOEXEC.BAT. Ключевые слова
и значения этого раздела приведены в таблице.

[Update_autobat_section] 
CmdDelete=command 
CmdAdd=command 
UnSet=environmentvariablename 
PreFixPath=%ldid% 
RemOldPath=%ldid% 
TmpDir=%ldid% 

Ключевое слово        Значение              Описание 
 
CmdDelete               command         Указывает команду, которая должна 
                                        быть удалена из файла AUTOEXEC.BAT. 
                                        Эта строка обрабатывается перед 
                                        строкой CmdAdd. 
 
CmdAdd                  command         Указывает команду, которую требуется 
                                        добавить в файл AUTOEXEC.BAT. 
 
UnSet          environmentvariablename  Указывает переменную окружения, кото- 
                                        рую вы хотите удалить из файла 
                                        AUTOEXEC.BAT. 
 
PreFixPath               %ldid%         Позволяет включить предопределенную 
                                        фиксированную переменную path в форме 
                                        логического идентификатора каталога 
                                        (logical directory identificator, LDID). 
 
RemOldPath               %ldid%         Позволяет указать путь, который должен 
                                        быть удален из файла AUTOEXEC.BAT. 
 
TmpDir                   %ldid%         Позволяет указать временный каталог на 
                                        время установки. 

Ниже приведен пример синтаксиса раздела [Update Config]. Имя раздела
[Update_config_section] должно быть задано в разделе [Install]. Этот раздел
содержит команды манипуляции со строками в файле CONFIG.SYS. Ключевые слова
и значения этого раздела описаны в таблице.

[Update_config_section] 
DevRename=current_name,new_name 
DevDelete=driver_name 
DevAddDev=driver_name,configkeyword 
Stacks=dos_stack_values 
Buffers=dos_buffer_values 
Files=dos_buffer_values 
LastDrive=dos_lastdrive_value 

Ключевое слово               Значение                 Описание 
 
DevRename             current_name,new_name   Позволяет переименовать драйверы 
                                              устройств, вызываемые из файла 
                                              CONFIG.SYS. Раздел может содержать 
                                              несколько строк DevRename. 
                                              Записи DevRename обрабатываются 
                                              первыми, прежде, чем начнется 
                                              обработка каких-либо других 
                                              записей раздела. 
                                               
DevDelete               driver_name           Позволяет указать драйверы 
                                              устройств, которые должны быть 
                                              удалены из файла CONFIG.SYS. 
                                              Раздел может содержать несколько 
                                              записей DevDelete. 
 
DevAddDev          driver_name,configkeyword  Позволяет указать новый драйвер, 
                                              который должен быть добавлен в 
                                              файл CONFIG.SYS. Раздел может 
                                              содержать несколько записей 
                                              DevAddDev. 
 
Stacks            dos_stack_values            Указывает значение Stacks= в 
                                              файле CONFIG.SYS. 
                                               
Buffers           dos_buffer_values           Указывает значение Buffers= в 
                                              файле CONFIG.SYS. 
 
Files             dos_file_values             Указывает значение Files= в 
                                              файле CONFIG.SYS. 
                                               
LastDrive         dos_lastdrive_value         Указывает значение lastdrive= 
                                              в файле CONFIG.SYS. 

Ниже приведен пример синтаксиса раздела [Update INI]. Раздел [Update INI]
необходимо указать в разделе [Install] записью UpdateINIs. Этот
раздел добавляет, удаляет или замещает записи в указанном INI-фаЙле.
Ключевые слова и значения для этого раздела описаны в таблице.

[Update_ini_section] 
ini-file,ini-section,original_entry,new_entry, options 
 
Значение            Описание 
 
options             Необязательные флаги операции, которые могут принимать 
                    одно из следующих значений 
 
   0                Значение по умолчанию. Ищет ключ (имя записи) 
                    original_entry, игнорируя его значение. Если ключ при- 
                    сутствует, соответствующая запись заменяется на 
                    new_entry. Если original_entry равна NULL, new_entry 
                    добавляется безусловно. Если new_entry равна NULL, 
                    original_entry удаляется. 
 
   1                Ищет запись original_entry по ключу и значению. Обнов- 
                    ление выполняется только в том случае, когда совпадают и 
                    ключ, и значение записи original_entry. 
 
   2                Ищет запись, ключ которой совпадает с указанным в 
                    original entry. Если запись уже существует, она не за- 
                    мещается значением, указанным вами в new_entry. 
 
   3                Ищет запись, ключ и значение которой совпадают с 
                    указанными в original_entry. Если такая запись существует, 
                    она замещается new_entry. 

Ниже приведена синтаксическая конструкция раздела [Update IniFields].
Имя раздела [UpdatelniFields] должно быть указано элементом
[UpdatelniFieldsl в разделе [Install]. Утверждения этого замещают,
добавляют или удаляют поля в указанной записи INI-файла. В отличие от
раздела [Update INI], команды из данного раздела работают с фрагмента-
ми записей, а не с записями в целом.

[update_inifields_section] 
ini-file,ini-section,profile_name,old_field,new_field 

Если в строке INI-файла для указанной записи присутствовал комментарий,
он удаляется. Модификаторы old_field и new_field являются необяза-
тельными.

Раздел [Add Registry] позволяет добавлять в реестр ключи и значения.
Кроме того, существует необязательная возможность установить фактиче-
ское значение. Имя раздела [add_registry_section] должно быть задано
элементом AddReg раздела [Install]. Синтаксис раздела выглядит следую-
щим образом:

[add_registry_section] 
reg_root_string 

В этот раздел вы можете включить подключи, имена значений и
(необязательно) сами значения.

Раздел [Delete Registry] используется для удаления из реестра подклю-
чен и имен значений. Синтаксис этого раздела выглядит следующим обра-
зом:

[del_registry_section] 
reg_root_string,subkey 

Имя этого раздела должно быть указано элементом DelReg в разделе
[Install]. Каждый элемент, включенный в этот раздел, удалит из реестра
подключ или значение.

Раздел [Ini to Registry] позволяет перемещать в реестр строки и разде-
лы из INI-файла. Эта операция или создает в реестре новый элемент, или
подключ или значение.

Имя раздела [ini_to_registry section] должно быть указано элементом
lni2Reg в разделе [Install].

Раздел [DestinationDirsI позволяет определить каталог назначения для
раздела [File_List]. Ссылка на имя раздела [DestinationDirs] должна
присутствовать в одном из следующих трех элементов раздела [Install]:
DelFiles, CopyFiles или RenFiles. Синтаксис раздела приведен ниже.

Более подробную информацию можно найти в таблице.

[DestinationDirs] 
file_list=ldid,subdirectory 
DefaultDestDir=ldid,subdirectory 

Ключевое слово       Значение             Описание 
 
file_list             ldid,subdirectory    Указывает имя раздела FileList. 
 
                      subdirectory         Указывает каталог, находящийся 
                                           в каталоге ldid. Это значение 
                                           необязательно. 
                                            
                      ldid                 Указывает логический идентификатор 
                                           диска. Список допустимых значений 
                                           ldid приведен далее. 
 
DefaulDestDir                              Позволяет указать каталог-приемник 
                                           по умолчанию для всех неупомянутых 
                                           разделов File_List. Этот параметр 
                                           не является обязательным. По умол- 
                                           чанию W95 использует каталог 
                                           LDID_WIN. 

Раздел [SourceDisksFilesj используется для указания исходных файлов,
используемых в процессе инсталляции. Кроме того, с помощью этого разде-
ла можно указать исходные диски, содержащие эти файлы. Синтаксис раз-
дела очень прост:

[SourceDisksFiles] 
name_of_source_disk=disk_number 

Элемент disk_number определяется в разделе [SourceDisksNames], кото-
рый использует следующий синтаксис:

[SourceDisksNames] 
disk_ordinal=description_of_disk,label,serial_number 

Раздел [ClassInstall] устанавливает новый класс устройства в разделе
реестра [Class]. Синтаксис раздела [ClassInstall] приведен ниже.
Подробную информацию о значениях и элементах, которые используются в
этом разделе, можно найти в таблице выше.

[ClassInstall] 
CopyFiles=fils_list_section 
RenFiles=fils_list_section 
DelFiles=fils_list_section 
UpdateInis=UpdateIni_section_name 
UpdateIniFields=UpdateIniFields_section_name 
AddReg=AddRegistry_section 
DelReg=DelRegistry_section 

Наконец, последним разделом INF-фаила является раздел [Strings]. Этот
раздел определяет один или несколько строковых ключей. Синтаксис этого
раздела приведен ниже.

[Strings] 
string_key="valve" 

Ключевое слово string_key обозначает строковый ключ, формирующийся
из буквенно-цифровых символов, например, MfgName. Хотя раздел
[Strings] обычно является последним в INF-файле, строковые ключи
можно использовать везде, где допустимо употребление строк.
Программа Setup подставляет вместо строкового ключа строку, заданную
элементом "value" и в дальнейшем использует именно ее, например:
MSFT="Microsoft"
Встпетив строку MSFT. поогоамма Setup интерпретирует ее как Microsoft

Значения LDID
В таблице перечислены допустимые значения LDID (logical disk identifier),
которые вы можете использовать в INF-файлах.


  ID           Обозначает 
   
  00           Пустой LDID; используется для создания нового LDID 
  01           Исходное устройство:\путь 
  02           Временный каталог Setup; используется только в процессе 
                                                     установки W95 
  03           Каталог Uninstall 
  04           Каталог Backup 
  10           Каталог Windows 
  11           Каталог SYSTEM 
  12           Каталог lOsubsys 
  13           Каталог COMMAND 
  14           Каталог Control Panel 
  15           Каталог Printers 
  16           Каталог Workgroup 
  17           Каталог INF 
  18           Каталог Help 
  19           Каталог Administration 
  20           Каталог Fonts 
  21           Каталог Viewers 
  22           Каталог VMM32 
  23           Каталог Color 
  25           Каталог Shared 
  26           Каталог Winboot 
  27           Машинно-зависимый каталог 
  28           Каталог Winboot Host 
  30           Корневой каталог загрузочного устройства 
  31           Корневой каталог хост-диска виртуального загрузочного устройства 
  32           Каталог с прежней версией Windows (если есть) 
  33           Каталог с прежней версией MS-DOS (если есть)DB 
 




Что из себя представляет Self?


Что из себя представляет Self?



Self - это явное задание экземпляра класса в его методе.

Например для твоей формы это указание на саму форму:

procedure TForm1.Button1Click(Sender: TObject);
begin
  showmessage(self.classname+#13#10+self.name);
end;

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

Автор ответа: Vit
Взято с Vingrad.ru





Чтобы понять, что такое self надо понять что такое метод класса. Метод класса - это просто функция(процедура) который имеет дополнительный неявный параметр - указатель на экземпляр класса. То есть:

TMy=class
  x:integer;
  procedure Proc(val:integer);
end;

procedure TMy.Proc(val:integer);
begin
  x:=val;
end;

После компиляции это будет практически то же самое, что:

procedure Proc(self:TMy;val:integer);
begin
  self.x:=val;
end;

То есть на самом деле в методе Proc обращаясь к x мы на самом деле обращаемся к self.x, просто переменная self опускается. В скомпилированном коде нет такого понятия как классы - есть только код и память. Все методы классов превращаются в обыкновенные функции, в которым качестве первого параметра передается указатель на область памяти где лежит созданный пользователем экземпляр класса, который они и используют для чтения или записи(а так же для вызова) того, что мы называем членами класса.

var
  m1,m2:TMy;
begin
  .....
  m1.Proc(4); // -> Proc(m1,4)
  m2.Proc(4); // -> Proc(m2,4)
end;


Автор ответа: Fantasist
Взято с Vingrad.ru




Что из себя представляет TWebBrowser?


Что из себя представляет TWebBrowser?



Взято из FAQ:
Перевод материала с сайта members.home.com/hfournier/webbrowser.htm

Веббраузер это Microsoft's Internet Explorer в виде ActiveX контрола.
Его можно импортировать в Delphi IDE и размещать на форме на равне с другими компонентами. Поэтому, чтобы превратить Ваше приложение в браузер, достаточно воспользоваться всей мощью IE.





Что такое базы данных?


Что такое базы данных?



Итак базы данных существуют следующих видов:

1) Древовидные - простейший пример - Windows Registry, файловая система FAT и XML - здесь информация хранится в древовидной структуре и доступ осуществляется через "путь", т.е. указание всех узлов от корневого до нужного. Например: "c:\My Docs\MyPictures\Me.jpg". Недостатки этого способа хранения данных является очень медленный поиск, если не известен путь и очень плохая устойчивость к повреждениям структуры. Преимущество - возможность хранить в классифицированном виде очень разнородную информацию и очень быстрый поиск при знании ключа. Эти базы данных мы разбирать здесь не будем.

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

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

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




Что такое Цвет?


Что такое Цвет?



Если Edit1.text это String то что такое Edit1.font.color?


TColor - это Integer, чтоб задать нужный цвет можно пользовать константы, а можно в числовом виде:

Edit1.font.color:=$223344

где 22 - яркость красного цвета, может быть в пределах от 00 до FF
где 33 - яркость зеленого цвета, может быть в пределах от 00 до FF
где 44 - яркость синего цвета, может быть в пределах от 00 до FF

Например:

Edit1.font.color:=$000000- черный
Edit1.font.color:=$FFFFFF - белый
Edit1.font.color:=$00FF00 - зеленый

Всего определено 256*256*256 цветов

В примерах я использовал шестнадцатиричные значения так как так проще, но можно и десятичные, если разберетесь какой это цвет

Edit1.font.color:=123456

Автор ответа: Vit
Взято с Vingrad.ru




Можно использовать константы типа clred, clblack, cllime, clgreen...
Для работы с цветом можно использовать следующие функции
RGB(r,g,b:byte):tcolor //получаешь цвет по 3 составляющим
GetRValue(color:tcolor)
GetGValue(color:tcolor)//получаешь значение интенсивности цвета.
GetBValue(color:tcolor)

Автор ответа: Mikel
Взято с Vingrad.ru


Для хранения цвета существует свой собственный тип, который называется TColor. Этот тип содержит информацию, как о самом цвете, так и том, каким образом его заменить, если, например, цветовая палитра системы не поддерживает этот цвет (скажем, установлено всего 256 цветов, а цвет, заданный в переменной, вылезает далеко за пределы этих 256 цветов).

Тип TColor состоит из четырех байт. Первый байт - указатель на замену цвета (о нем поговорим позже). Второй байт - яркость красного цвета от 0 до 255 (от 00 до FF). Третий байт - яркость зеленого цвета от 0 до 255 (от 00 до FF). И, наконец, четвертый байт - яркость синего цвета, также, от 0 до 255 (от 00 до FF).

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

Поговорим теперь о первом байте - указателе на замену цвета. Итак, этот байт может принимать три различных значения - ноль ($00), единицу ($01) или двойку ($02). Что это значит:

Ноль ($00) - цвет, который не может быть воспроизведен точно, заменяется ближайшим цветом из системной палитры.
Единица ($01) - цвет, который не может быть воспроизведен точно, заменяется ближайшим цветом из палитры, которая установлена сейчас.
Двойка ($02) - цвет, который не может быть воспроизведен точно, заменяется ближайшим цветом из палитры, которую поддерживает текущее устройство вывода (в нашем случае - монитор).
Видимо, всегда лучше устанавливать значение первого байта равным нулю ($00), по крайней мере, так происходит при получении типа TColor при помощи функции RGB.

И, напоследок, несколько примеров:



$00FFFFFF - белый цвет;
$00000000 - черный цвет;
$00800000 - темно-красный цвет.


Взято из





Что такое DirectShow?


Что такое DirectShow?





На этот раз речь пойдет о DirectShow. Для чего нам может понадобиться DirectShow?
DirectShow - это архитектура для воспроизведения, перехвата и обработки потоков мультимедиа. Звучит туманно? Поясняю - c помощью этого API можно:
проигрывать мультимедийные файлы различного формата, такие как MPEG (Motion Picture Experts Group), AVI (Audio-Video Interleaved), MP3 (MPEG Audio Layer-3), DVD и конечно WAV;
перехватывать видео-поток с различного рода TV-карт, видеокамер и т.п.;
создавать нестандартные обработчики мультимедиа-потоков и свои собственные форматы файлов (что, впрочем, вряд ли понадобится простым смертным);
обращаться непосредственно к видео и аудио потокам, чтобы выводить их на Surface DirectDraw (что для нас как раз интересно).
Звучит заманчиво. Но для чего это может понадобиться, спросите Вы, вспоминая родной и привычный MediaPlayer. Представьте себе, что Вы запрограммировали трехмерный мир, с анимированными спрайтами, трехмерными объектами и т.п. И в отсвете выстрелов очередной "бродилки-стрелялки", пораженный пользователь нового шедевра, видит видео клип, воспроизводимый прямо на костях очередного пораженного монстра. :-) Каково? Убедил? Тогда продолжим.
Кстати, раз уж упомянули DirectDraw - DirectShow интегрирован с DirectX так, что использует DirectDraw и DirectSound для вывода изображения и звука, и, при наличии аппаратного ускорения, автоматически им воспользуется.

Для работы с DirectShow Вам понадобятся:
иметь некоторое представление о технологии COM (Component Object Model) - хотя быть знатоком этой технологии вовсе не обязательно - просто достаточно знать, что для получения COM-интерфейса нужно вызвать QueryInterface;
скачать заголовочные файлы DirectShow API, переведенные на Delphi в рамках проекта JEDI - (http://www.delphi-jedi.org/DelphiGraphics/DirectX/DX5Media.zip) и либо поместить их в каталог Delphi\Lib либо добавить путь к каталогу, в котором они находятся в установках Delphi Library Path.
DirectShow скорее всего уже установлен на Вашем компьютере - он входит в стандартную поставку Windows 9x, Windows NT 4 (Service Pack 3 и выше), Windows 2000 (если Вы программируете для UNIX или DOS - то я вообще не понимаю зачем Вы читаете эту статью).

Основы DirectShow

В концепции DirectShow мультимедийные данные - это поток, который проходит через несколько обрабатывающих блоков. Блоки, обрабатывающие поток данных, передают данные по цепочке друг другу, таким образом можно представить себе несколько "устройств", каждое из которых выполняет какую-то обработку данных и передает их соседнему "устройству". Эти "устройства" или "блоки обработки" данных называют фильтрами. Цепочка, по которой передаются данные, содержит несколько фильтров, связанных определенным образом.
В DirectShow имеются готовые фильтры, из которых, словно из детских кубиков, программист может выстроить ту или иную цепочку обработку данных, кроме того, конечно, можно создать свои, нестандартные фильтры.
Для создания такой "цепочки обработки" (которая, кстати, официально называются Filter Graph - "граф фильтров" или, в несколько вольном переводе - "схема соединения фильтров"), так вот для создания схемы соединения фильтров, предназначен самый базовый и лежащий в основе всех основ компонет DirectShow, под названием Filter Graph Manager - Менеджер Графа Фильтров.
Например, программа показывающая видео из AVI-файла может построить такой граф фильтров:

В этом примере пять фильтров, первый (File Source) просто читает данные с диска, второй фильтр (AVI Splitter) разделяет данные на кадры и передает упакованные видео данные фильтру AVI Decompressor, который их распаковывает и передает фильтру Default DirectSound Device, выводящему звук. AVI Decompressor передает распакованные данные фильтру Video Renderer, который выводит кадры видео на экран.
Фильтры делятся на три типа:
Фильтры-источники (Source filters) - эти фильтры просто получают данные из какого-то источника, с диска (как фильтр File Source (Async) на рисунке), с CD или DVD дисковода или с TV- карты или карты, к которой подключена цифровая видеокамера.
Фильтры-преобразователи (Transform filters) - эти фильтры как видно из названия преобразуют поток данных, проходящий через них каким-либо образом, например - разделяет поток данных на кадры, производят декомпрессию и т.п. На нашем рисунке к таким фильтрам относятся AVI Splitter и AVI Decompressor.
Фильтры вывода (Renderer filters) - фильтры, которые получают полностью обработанные данные и выводят их на монитор, звуковую карту, пишут на диск или выводят на еще какое-нибудь устройство.
Итак из фильтров-кубиков можно высстраивать граф. Делается это с помощью интерфейса IGraphBuilder. Создать объект типа IGraphBuilder можно так:

CoCreateInstance(CLSID_FilterGraph,nil,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,MyGraphBuilder);

Здесь переменная MyGraphBuilder имеет тип IGraphBuilder; идентификатор класса CLSID_FilterGraph и IID_IGraphBuilder обьявлены в файле DShow.pas, поэтому не забудьте добавить

usesDShow.pas 

Итак, интерфейс IGraphBuilder получен. Можно построить граф фильтров, такой, какой нам нужно. Впрочем, все не так сложно, IGraphBuilder достаточно интеллектуален, он может сам, автоматически, построить граф, в зависимости от того какие файлы мы собираемся воспроизводить. Интерфейс IGraphBuilder имеет метод RenderFile, который получает имя файла в качестве параметра и, в зависимости от типа файла (которое определяется по расширению и по специальным сигнатурам в файле), сканирует реестр, в поисках необходимой для построения графа информации, создает необходимые фильтры и строит граф, предназначенный для воспроизведения файлов этого типа (WAV, AVI, MP3, MPG и т.д.).

После построения графа DirectShow готов к воспроизведению. Для управления потоком данных через граф обработки предназначен интерфейс IMediaControl - он имеет методы Run, Pause и Stop (названия говорят сами за себя)

Давайте попробуем все это на примере:


uses
  ... DShow, ActiveX,ComObj;

var
  MyGraphBuilder : IGraphBuilder;
  MyMediaControl : IMediaControl;
begin

CoInitialize(nil);
{получаем интерфейс IGraphBuilder}
CoCreateInstance(CLSID_FilterGraph,nil,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,MyGraphBuilder);

{вызываем RenderFile - граф фильтров строится автоматически}
MyGraphBuilder.RenderFile('cool.avi',nil);

{получаем интерфейс ImediaControl}
MyGraphBuilder.QueryInterface(IID_IMediaControl,MyMediaControl);

{Примечание - MyMediaControl - переменная типа IMediaControl}

{проигрываем видео}
MyMediaControl.Run;

{ждем пока пользователь не нажмет ОК (видео воспроизводится в отдельном (thread) потоке)}
ShowMessage('Нажмите OК');

CoUninitialize;

end;

Если Вы не поленитесь скопировать этот кусок кода в Delphi и запустить его то заметите, что avi-файл проигрывается в отдельном окошке, которое не принадлежит нашему приложению. Для управления окошком, в котором воспроизводится видео предназначен специальный интерфейс IVideoWindow. Получить этот интерфейс можно из экземпляра IGraphBuilder, вызвав QueryInterface и передав в качестве идентификатора интерфейса константу IID_IvideoWindow.
Интерфейс IVideoWindow содержит методы для управления заголовком, стилем, местоположением и размерами окошка в котором проигрывается видео.
Давайте попробуем переделать наш пример так, чтобы видео выводилось не в отдельном окошке, а, скажем на компоненте TPanel, расположенном в нашей форме. Добавьте на форму компонет TPanel, пусть он называется Panel1.

uses
  ... DShow, ActiveX,ComObj;


procedure TForm1.Button1Click(Sender: TObject);
var
  MyGraphBuilder : IGraphBuilder;
  MyMediaControl : IMediaControl;
  VideoWindow : IVideoWindow;

begin

CoInitialize(nil);
{получаем интерфейс IGraphBuilder}
CoCreateInstance(CLSID_FilterGraph,nil,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,MyGraphBuilder);


{вызываем RenderFile - граф фильтров строится автоматически}
MyGraphBuilder.RenderFile('C:\Program Files\Borland\Delphi5\Demos\Coolstuf\cool.avi',nil);

{получаем интерфейс ImediaControl}
MyGraphBuilder.QueryInterface(IID_IMediaControl,MyMediaControl);
{Примечание - MyMediaControl - переменная типа IMediaControl}

{получаем интерфейс IVideoWindow}
MyGraphBuilder.QueryInterface(IID_IVideoWindow,VideoWindow);
{Примечание - VideoWindow - переменная типа IVideoWindow}

{располагаем окошко с видео на панель}
VideoWindow.Set_Owner(Self.Panel1.Handle);
VideoWindow.Set_WindowStyle(WS_CHILD OR WS_CLIPSIBLINGS);
VideoWindow.SetWindowPosition(0,0,Panel1.ClientRect.Right,Panel1.ClientRect.Bottom);

{проигрываем видео}
MyMediaControl.Run;

ShowMessage('Нажмите OК');

CoUninitialize;
end;

Надеюсь это проще, чем Вы ожидали?


DirectShow и DirectX

Для того, чтобы использовать DirectShow совместно с DirectShow нужно разобраться с понятием Multimedia Streaming (потоки мультимедиа).
Multimedia Streaming - это архитектура, используемая в DirectShow для облегчения жизни программиста. Эта архитектура позволяет работать с мультимедиа данными, как с абстрактным потоком, не вдаваясь в подробности форматов хранения мультимедиа-файлов или специфику устройств-источников мультимедиа. Используя эту архитектуру, программист концентрируется не на расшифровке и преобразовании данных, а на управлении потоком данных, кадрами видео или аудио семплами.
На рисунке изображена иерархия объектов Multimedia Streaming

На вершине иерархии находится базовый объект Multimedia Stream, который является контейнером для объектов Media Stream. Объект Multimedia Stream может содержать один или несколько объектов Media Stream. В то время как каждый объект типа Media Stream предназначен для работы с данными какого-то одного типа (видео, аудио и т.п.) - Multimedia Stream - просто содержит методы для обращения к содержащимся в нем объектам Media Stream и не зависит от типа данных.
Объект типа Stream Sample, доступ к которому можно получить из Media Stream - позволяет управлять непосредственно элементами мультимедийного потока (для видео каждый Sample - это кадр видеоизображения, для аудио он может содержать несколько семплов звука).
Однако хватит теории. Давайте перейдем к делу. Попробуем создать необходимые объекты, чтобы вывести видео на Surface DirectX. Для этого нам понадобится обращаться к кадрам видео изображения (т.е. к обьекту типа Stream Sample). Значит, придется пройтись по всей цепочке иерархии, чтобы добраться до обьектов StreamSample. Вообще цепочка обьектов, которую предстоит создать выглядит так:
IAMMultiMediaStream
+ IDirectDrawMediaStream
+ IDirectDrawStreamSample

Сравните это с нашим рисунком. Как видите на вершине находится объект типа MultiMediaStream, который будет содержать MediaStream конкретного, нужного нам типа (IDirectDrawMediaStream), а уж с помощью него мы получим доступ к конкретным видео кадрам через интерфейс IDirectDrawStreamSample.
Итак сейчас мы создадим объект типа IAMMultiMediaStream. Этот интерфейс унаследован от IMultimediaStream и содержит, кроме прочего, функцию OpenFile, которая автоматически строит граф фильтров для воспроизведения файла.


CoCreateInstance(CLSID_AMMultiMediaStream, nil, CLSCTX_INPROC_SERVER, IID_IAMMultiMediaStream, AMStream);

Здесь переменная AMStream имеет тип IAMMultiMediaStream.
Мы создали контейнер для мультимедийных потоков. Сверяемся с рисунком - мы на верхнем уровне иерархии. У нас есть объект типа IMultimediaStream - теперь в этот контейнер нужно проинициализировать и добавить один или несколько мультимедиа потоков, нужного нам типа. Сначала инициализация:

AMStream.Initialize(STREAMTYPE_READ,
  AMMSF_NOGRAPHTHREAD, nil);

При инициализации указываем, что будут создаваться мультимедиа потоки для чтения, передав значение STREAMTYPE_READ (другие варианты STREAMTYPE_WRITE, STREAMTYPE_TRANSFORM).

Создадим теперь мультимедиа потоки для видео и звука:

AMStream.AddMediaStream(DDraw, MSPID_PrimaryVideo, 0, NewMediaStremVideo);
    AMStream.AddMediaStream(nil, MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NewMediaStremAudio);

Вызываем метод OpenFile - файл загружается, и автоматически строится граф фильтов:

AMStream.OpenFile('cool.avi', 0);

Осталось направить видео поток мультимедиа поток на Surface. Вот процедура, которая делает это:

procedure TForm1.RenderStreamToSurface(Surface : IDirectDrawSurface; MMStream : IMultiMediaStream);
var
PrimaryVidStream : IMediaStream;
DDStream  :  IDirectDrawMediaStream;
Sample : IDirectDrawStreamSample; 
RECT : TRect;
ddsd :  TDDSURFACEDESC;
Z : DWORD;
begin
    MMStream.GetMediaStream(MSPID_PrimaryVideo, PrimaryVidStream);
    PrimaryVidStream.QueryInterface(IID_IDirectDrawMediaStream, DDStream);
    ddsd.dwSize := sizeof(ddsd);
    DDStream.GetFormat(ddsd, Palitra, ddsd, Z);
    rect.top:=(480-ddsd.dwHeight)div 2; rect.left:=(640 - ddsd.dwWidth) div 2;
    rect.bottom := rect.top+ddsd.dwHeight;    rect.right := rect.left+ddsd.dwWidth;
    DDStream.CreateSample(Surface, Rect, 0, Sample);
    MMStream.SetState(STREAMSTATE_RUN);
end;


Как видите, в этой процедуре сначала получаем интерфейс типа IDirectDrawMediaStream (соответствующий второму уровню иерархии на нашем рисунке), потом из него получаем объект типа IDirectDrawStreamSample (переменная Sample), который соответствует третьему уровню иерархии нашего рисунка.

Теперь остается вызывать в цикле (в демо-программе это делается по таймеру - здесь для простоты опускаем):

hr:=Sample.Update(0 , 0, nil, 0);

   if hr = $40003 {MS_S_ENDOFSTREAM} then
     MMStream.Seek(0);

Метод IDirectDrawStreamSample.Update выводит очередной кадр на Surface. При достижении конца потока он вернет ошибку с кодом $40003 (MS_S_ENDOFSTREAM), я в этом случае просто перематываю поток к началу, методом Seek.

Полностью программу, фрагменты кода из которой здесь приведены можно скачать здесь <<URL>>.
В этой программе инициализируется DirectDraw, создается Surface , а затем на него выводится видео из avi-файла.

Пока все о DirectDraw - надеюсь эта информация послужит для Вас отправной точкой в написании чего-то потрясающего! :-)


Автор: JINX (Elchin Aziz Ali OglI)
EMail: aziz@telebot.com, error@softhome.net
CopyLeft 2000.

Взято с сайта

Анатолия Подгорецкого
по материалам fido7.ru.delphi.*



Что такое DOM?


Что такое DOM?



Взято из FAQ:
Перевод материала с сайта members.home.com/hfournier/webbrowser.htm  
 

Document Object Model это платформенно независимый интерфейс,
позволяющий программам и скриптам динамически обновлять и
изменять содержимое, структуру и стиль документов. Вопрос: Где можно почитать документацию по DOM? Ответ: Обзор материалов по DOM на W3C site , а так же FAQ.
Не забудьте заглянуть на Document object на сайте Microsoft.




Что такое иконка на System Tray?


Что такое иконка на System Tray?




Иконка на Tray'е это просто картинка, а не окно какой-либо программы (исследование системы с помощью Microsoft Spy++ for Windows 95 показывает, что это не окно вообще). System Tray отслеживает события мыши над иконкой и, в случае надобности, показывает ToolTip для этой иконки. Так же он отсылает сообщения о всех действиях мыши над иконкой окну, которое поместило иконку на Tray. Таким образом, нельзя поместить программу на Tray. Любая программа может добавить стоько иконок на Tray, сколько ей необходимо. При этом главное окно программы не обязано исчезать или минимизироватся - примером может служить Microsoft Internet Mail, помещающая иконку " конверт" на Tray в случае появления новых писем.

Взято из FAQ:




Что такое MIDAS (multi-tired distributed application service)?


Что такое MIDAS (multi-tired distributed application service)?





MIDAS - multi-tired distributed application service suite- это технология Borland для создания многоуровневых приложений баз данных. Применение данной архитектуры позволяет быстро разрабатывать простые в сопровождении и установке, надежные, распределенные БД. Трехуровневое приложение баз данных содержит несколько компонентов (слоев):

а) Слой БД. Хранит данные. Выполняет функции хранения информации, обеспечения целостности и непротиворечивости данных. Пример -локальные (dBase, Paradox) и серверные БД (Oracle, Sybase, MS SQL), текстовые файлы и т.д.

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

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

Применение данной схемы позволяет создать клиентское приложение, которое практически не требует настройки и сопровождения, вся логика работы с БД сосредоточена в среднем слое (сервере приложений). Соответственно при доработке алгоритмов доступа к БД необходимо лишь переустановить сервер приложений. MIDAS предназначен для обеспечения связи между слоем бизнес логики и презентационным слоем. Он позволяет организовать взаимодействие тонкого клиента с сервером приложений. При этом сервер приложений взаимодействует с реляционной БД (чаще всего данные хранятся именно в этой форме) как и обычные приложения работы с БД, разработанные в Delphi. Тонкий клиент для конечного пользователя ничем не отличается от обычного (толстого) клиента БД. Разница в том, что толстый клиент через BDE, ADO, компоненты прямого доступа к серверам БД и другие библиотеки работает с БД, а тонкий клиент взаимодействует с сервером приложений, используя MIDAS. Сервер приложений скрывает от клиента детали доступа и обработки БД. На компьютере с тонким клиентом не нужно устанавливать и настраивать BDE, ADO, клиентскую часть сервера БД. Необходимо лишь иметь небольшие по объему dll, которые легко переносить вместе с exe файлом тонкого клиента. В качестве тонкого клиента может использоваться и Web браузер. Разработка пользовательского интерфейса тоже мало чем отличается от обычного клиента. Особенности - необходимость размещения и настройки одного из компонентов доступа к серверу приложений (DCOMConnection, SocketConnection, WebConnection, CorbaConnection) и вместо Table, Query, StoredProc использовать компонент TСlientDataSet. Сервер приложений, как правило, имеет весьма несложный пользовательский интерфейс (чаще одну главную форму). Да он ему и не нужен. Сердце сервера приложений - это удаленный модуль данных (Remote Data Module). В зависимости от протокола связи TRemoteDataModule, MTSDataModule, TCORBADataModule. Внутри удаленного модуля данных расположены невизуальные компоненты доступа к данным. Каждому компоненту, который должен быть доступен тонкому клиенту необходимо сопоставить компонент - TDataSetProvider. Кроме того, для автоматического запуска серверов приложений по запросу клиента и реализации стратегии безопасности доступа бывает необходимо иметь дополнительную программу SCM (service control manager).

Создание трехуровневого приложения

Итак, создадим наше первое приложение для просмотра таблицы animals.dbf БД DBDEMOS. Как указывалось выше нам необходимо разработать сервер приложений и тонкого клиента (слой БД - это dbf файл).

Создание сервера приложений

Создадим новое приложение, используя пункт меню File / New Application. Созданная при этом форма Form1 будет главной формой сервера приложений. Далее создадим удаленный модуль данных, в него будут помещаться невизуальные компоненты доступа к данным и в нем сосредотачивается вся функциональность сервера приложений. Отличие его от обычного модуля данных в том, что удаленный модуль данных обеспечивает возможность тонким клиентам получать данные с сервера приложений. Выберем пункт меню File / New и в появившемся диалоге перейдем к закладке Miltitier

Выберем значок Remote Data Module и нажмем кнопку ОК (Замечание в случае использования CORBA необходимо выбирать CORBA Data Module). После этого на экране появляется диалог RemoteDataModuleWizard. Заполним поле CoClass Name базовым именем нашего удаленного модуля MyRDM. Обратите внимание, что к указанному имени будет добавлена буква T в наименовании класса и I в наименовании интерфейса для управления удаленным модулем. Остальные поля оставьте как есть (мы пишем простейшего сервера). Нажмем кнопку OK. В проект будет добавлен модуль Unit2, содержащий удаленный модуль данных. С закладки DataAccess добавим компонент TTable и свяжем его с таблицей animals.dbf алиаса DBDEMOS и активируем (свойства DatabaseName установим в DBDEMOS, TableName в animals.d, Active в true. Напомню, что порядок установки свойств важен). Теперь для того, чтобы сделать данную таблицу доступной тонкому клиенту необходим еще один компонент TDataSetProvider. Он расположен на закладке Midas. Чтобы связать DataSetProvider с TTable (как впрочем и с другими компонентами доступа к данным) установим свойство DataSet первого равным Table1. Результат наших усилий можно увидеть на рис.3. Осталось запустить сервер приложений на выполнение. Во-первых, чтобы увидеть наши труды, а во-вторых, чтобы при первом запуске сервер приложений произвел необходимые действия по своей регистрации в реестре.

Удаленный модуль данных
В принципе сервер приложений готов и работоспособен (без написания кода !!!), однако внесем последний штрих - счетчик подключений клиентов. Для этого на главную форму поместим два компонента TLabel. Свойство Caption одного установим в "Количество подключений", а второго в "0". Вид главной формы представлен на рис.4.

В обработчики события OnCreate удаленного модуля инкрементируем значение счетчика

withForm1.Label2 do
  Caption := IntToStr(StrToInt(Caption) + 1);


а в OnDestroy того же компонента декрементируем


with Form1.Label2 do
  Caption := IntToStr(StrToInt(Caption) - 1);



Создание тонкого клиента

Теперь настало время взяться за написание клиента. Создадим новое приложение, использующее в качестве протокола связи с сервером сокеты. Выбрав File / New Application в меню, на главную форму установим компонент TSocketConnection с закладки Midas. Данный компонент обеспечивает взаимодействие с сервером приложений. Далее нам необходимо запустить программу Borland Socket Server (расположена в Delphi/Bin/scktsrvr.exe). Данная программа обрабатывает запросы клиентов, передает их серверу приложений и запускает его, если раньше он не был запущен. Программы, выполняющие данные функции называют SCM (service control manager). Запуск Borland Socket Server необходим лишь в случае использования протокола сокетов. При запуске Borland Socket Server помещает свой значок в панель задач.

Настроим SocketConnection1. Значение свойства ServerName выберем из выпадающего списка и установим равным Project1.MyRDM, таким образом мы указываем к какому серверу приложений присоединяться. Затем необходимо указать на какой машине находится данный сервер. Для этого надо установить либо свойство Address в значение IP адреса или выбрать из списка значений свойства Host имя Вашего PC. Наконец, установим свойство Connected в true. О-о-пс, если все было выполнено верно, запустится сервер приложений и его счетчик клиентов будет установлен в 1. Для доступа к данным в тонком клиенте вместо TTable, TQuery используется TClientDataset. Разместим на главной форме его и мы, взяв с закладки Midas. Значение свойства RemoteServer установим в SocketConnection1, ProviderName в DataSetProvider1 (вспомним, что разместили его в удаленном модуле данных сервера приложений). Внимание, порядок установки этих свойств важен. Активизируем TClientDataSet, установив свойство Active в true. Далее порядок проектирования не отличается от разработки обычного приложения БД. Т.е. размещаем на форме DataSource, DBGrid, DBNavigator.Набор свойств, которые нужно установить приведен в таблице 1.

Таблица 1
DataSource1
DataSet ClientDataSet1
DBGrid1, DBNavigator
DataSource DataSource1

Если все выполнено правильно, то в сетке просмотра появятся данные. Вид главной формы приведен на рис.5. Ну вот, теперь можно запустить клиента. При этом на запущенном сервере приложений счетчик увеличится до2. Можно запустить еще несколько экземпляров клиентов, загнуть пальцы и сделать умное лицо. :)))

Какую из технологий (протоколов) распределенных вычислений лучше использовать с MIDAS ?
Протокол обеспечивает механизм вызова сервера приложений и соединения с ним клиента.
На данный момент Delphi поддерживает четыре протокола организации распределенных вычислений:


DCOM - технология Microsoft для создания и использования удаленных объектов автоматизации.
Достоинства:
а) Встроена в Windows 98,NT,2000. Может быть установлен в Windows 95, как дополнительная опция. Это не требует запуска дополнительных приложений на стороне сервера для управления подключением клиентов.
б) Реализован автоматический запуск сервера приложений при вызове его клиентом и автоматическое закрытие при отсутствии клиентов.
Недостатки:
а) Существуют проблемы с работой DCOM в сетях без контроллера домена NT. Поэтому использовать эту технологию в полной мере можно лишь при наличии в сети сервера с ОС Windows NT, 2000.
б) В DCOM нет встроенных средств обеспечения прозрачности положения сервера приложений (location transparency), т.е другими словами всегда нужно указывать на каком компьютере расположен сервер приложений. Данное ограничение можно сгладить применением SimpleObjectBroker.
в) Использовать DCOM можно лишь на платформе Windows.

Sockets - самый простой из протоколов организации распределенных вычислений. В его основе лежит использование сокетов TCP/IP.
Достоинства:
а) Требует минимум установленных компонентов ОС.
б) Может функционировать в любой сети Windows (c выходом Kylix надеюсь и в Linux), использующей TCP/IP.
Недостатки:
а) Требует постоянно запущенного на сервере менеджера подключений клиентов (ScktSrvr.exe).
б) Отсутствие механизмов обеспечения безопасности, другими словами все серверы приложений данной машины могут быть использованы с любого клиента, имеющего доступ по TCP/IP.

WebConnection - использует HTTP.
Достоинства:
а) Позволяет организовать вызов объекта с машины находящейся за пределами сегмента сети, защищенного файрволом.
Недостатки:
а) Требует установки на стороне клиента Wininet.dll (поставляется с IE 3 и выше).
б) Web сервер IIS 4 (и выше ) или Netscape enterprise 3.6 (и выше).

CORBA - использует соответствующую спецификацию OMG. Проще говоря CORBA - независимый от ОС стандарт взаимодействия объектов в распределенной системе.
Достоинства:
а) Независимость от ОС.
б) Наличие встроенного механизма обеспечения прозрачности положения сервера приложений. Т.е не нужно волноваться за то, где запущен сервер приложений, он будет автоматически найден.
в) Возможность выбора между автоматическим запуском сервера приложений при подключении клиента или запуска "вручную".
Недостатки:
а) Требуется установка дополнительного программного обеспечения (брокера объектных запросов - хотя бы на одной машине в сети).
б) Более сложная установка и настройка (по сравнению с DCOM) сервера приложений при автоматическом запуске.
в) Использование в Delphi COM для реализации CORBA

Таким образом можно дать следующие рекомендации по выбору протокола;
Если Вы новичок в MIDAS, то для изучения лучше всего используйте DCOM, установив сервер приложений и клиента на одной машине.
Если Ваша БД буде использоваться только с ОС Windows в сетях с контроллером домена Windows NT,2000 - используйте DCOM.
Если Вы не уверены, в том что в сети будет контроллер домена, то используйте либо CORBA, либо сокеты
В случае, если необходимо обеспечить запуск серверов приложений на любой машине в сети и конфигурация сети может меняться (или заранее неизвестны имена машин, где будут функционировать сервера приложений) лучше использовать CORBA.
Если Ваши сервера приложений должны быть доступны не только в локальной сети, но и "снаружи" - WebConnection подойдет лучше всего.
Когда Вы не хотите забивать себе голову (а надо бы) DCOM-ми, CORBA-ми, stab-ми, skeleton-ми, правами доступа итд SocketConnection поможет Вам быстро слабать многослойную БД.

Взято с






Что такое порт? Правила для работы с портами


Что такое порт? Правила для работы с портами



Взято из FAQ:http://blackman.km.ru/myfaq/cont4.phtml
Автор Дмитрий Кузан, Известно что в компьютере очень много собрано различных устройств , возникает вопрос как операционная система общается с ними. Для этого и служит порт, то есть эта «дверь» через которую программа (операционная система) может управлять данным устройством (считывать данные, заносить их).Причем я разделяю порты на две категории (это чисто мое разделение) - порты общеизвестные (COM LPT) и порты внутренние ,служащие для связи с внутренними устройствами ЭВМ. 2.Некоторые правила для работы с портами Следует иметь в виду что при разработке программ имеющих дело
работы с портами следует учитывать следующие факторы :
а) Стараться использовать функции высокого уровня для доступа к портам (в частности WinAPI) и не прибегать к низкоуровневым операциям чтения/записи портов. Если вы все-таки решили писать низкоуровневое чтение то эти процедуры нужно выносить в отдельную DLL или VXD, по следующим причинам - известно, что операционная система Windows95/98 а особенно NT являются по своей сути многозадачными системами. То есть если ваша программа обращается конкретно к порту не через динамический вызов функции DLL или VXD ( использования механизма DLL) а напрямую то это может сказаться на корректной работе системы или даже завалить ее. И даже если в Windows95/98 такой подход вполне может работать то в Windows NT вследствие его архитектуры не разрешит непосредственное чтение/запись напрямую, а использование механизма DLL или VXD позволяет обойти эту проблему.
б)Если вы работаете с каким-то нестандартным портом ввода-вывода
(например портом хранящим состояние кнопок пульта ДУ TVTunera то наверняка в комплекте поставки родного софта найдется DLL или VXD для управления этим устройством и отпадет нужда писать код, так я при работе с пультом ДУ TVTunerа использую стандартную DLL поставляемую в комплекте, это сразу решило вопросы связанные с управлением портами данного тюнера)Итак, отступление ? немного практики…
Маленький пример для работы с портами
(первый пример был уже опубликован в королевстве Дельфи
и представлял собой пример работы с весами ПетрВес)

function PortInit : boolean; //инициализация
var f: THandle;   
    ct: TCommTimeouts;  
    dcb: TDCB;  
begin
f := Windows.CreateFile(PChar('COM1'), GENERIC_READ or   
GENERIC_WRITE,  
FILE_SHARE_READ or FILE_SHARE_WRITE,  
nil, OPEN_EXISTING,  
FILE_ATTRIBUTE_NORMAL, 0);  
if (f < 0) or not Windows.SetupComm(f, 2048, 2048)or not  
Windows.GetCommState(f, dcb) then exit; //init error dcb.BaudRate := скоpость;  
dcb.StopBits := стоп-биты;  
dcb.Parity := ?етность;  
dcb.ByteSize := 8;  
if not Windows.SetCommState(f, dcb) or   
   not Windows.GetCommTimeouts(f, ct) then exit; //error  
ct.ReadTotalTimeoutConstant := 50;  
ct.ReadIntervalTimeout := 50;  
ct.ReadTotalTimeoutMultiplier := 1;  
ct.WriteTotalTimeoutMultiplier := 0;  
ct.WriteTotalTimeoutConstant := 10;  
if not Windows.SetCommTimeouts(f, ct)  
   or not Windows.SetCommMask(f, EV_RING + EV_RXCHAR + EV_RXFLAG + EV_TXEMPTY)  
  then exit; //error  
result := true;  
end;

function DoneComm: boolean; //закpыть поpт
begin
  result := Windows.CloseHandle(f);
end; 

function PostComm(var Buf; size: word): integer; //пеpеда?а в поpт
  var p: pointer; i: integer;
begin
p := @Buf;  
result := 0;  
while size > 0 do   
begin  
  if not WriteFile(f, p^, 1, i, nil) then exit;  
  inc(result, i); inc(integer(p)); dec(size);  
  Application.ProcessMessages;  
end;  
end; 

function ReadComm(var Buf; size: word): integer; //пpием из поpта
  var i: integer; ovr: TOverlapped;
begin
  fillChar(buf, size, 0);
  fillChar(ovr, sizeOf(ovr), 0); i := 0; result := -1;
  if not windows.ReadFile(f, buf, size, i, @ovr) then exit;
  result := i;
end; 

Данный пример был взят мной из многочисленный FAQ посвященных в DELPHI в сети ФИДО
Итак,для работы с портами COM и LPT нам понадобится знание функций Windows API. Вот подробное описание функций, которые нам нужны (в эквиваленте C) для работы с портами.
(извините за возможный местами неточный перевод ,если что поправьте меня если что не так перевел)

CreateFile HANDLE CreateFile( LPCTSTR lpFileName,// указатель на строку PCHAR с именем файла
DWORD dwDesiredAccess,// режим доступа
DWORD dwShareMode,// share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes,// указатель на атрибуты
DWORD dwCreationDistribution,// how to create
DWORD dwFlagsAndAttributes,// атрибуты файла
HANDLE hTemplateFile // хендл на temp файл
); Пример кода на Дельфи
< вырезано>
CommPort := 'COM2'; 
hCommFile := CreateFile(Pchar(CommPort), 
GENERIC_WRITE, 0, nil, 
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
0);


< вырезано>
Параметры
LpFileName
Указатель на строку с нулевым символом в конце (PCHAR) ,
которая определяет название создаваемого объекта (файл,
канал, почтовый слот, ресурс связи (в данном случае порты),
дисковое устройство, приставка, или каталог)
DwDesiredAccess
Указывает тип доступа к объекту ,принимает значение
GENERIC_READ - для чтения
GENERIC_WRITE - для записи (смешивание с GENERIC_READ
операцией GENERIC_READ and GENERIC_WRITE предостовляет полный доступ )
dwShareMode
Набор разрядных флагов, которые определяют как объект может быть разделен по доступу к нему.
Если dwShareMode - 0, объект не может быть разделен.
Последовательные операции открытия объекта будут терпеть неудачу,
пока маркер(дескриптор) открытого объекта не будет закрыт.
Фактически предоставляется монопольный доступ. Чтобы разделять объект(цель), используйте комбинацию одних или большее количество следующих значений:
FILE_SHARE_DELETE (Только для Windows NT)
FILE_SHARE_READ
FILE_SHARE_WRITE
LpSecurityAttributes
Указатель на структуру SECURITY_ATTRIBUTES, которая определяет
может ли возвращенный дескриптор быть унаследован дочерними процессами.
Если lpSecurityAttributes НУЛЕВОЙ, маркер не может быть унаследован.
Используется только в windows NT.
dwCreationDistribution
Определяет поведение функции если объект уже существует и
как он будет открыт в этом случае Принимает одно из следующих значений :
CREATE_NEW
Создает новый объект (файл) Выдает ошибку если указанный объект (файл) уже существует.
CREATE_ALWAYS
Создает новый объект (файл) Функция перезаписывает существующий объект (файл)
OPEN_EXISTING
Открывает объект (файл) Выдает ошибку если указанный объект (файл) не существует.(Для более детального смотрите SDK)
OPEN_ALWAYS
Открывает объект (файл), если он существует. Если объект (файл) не существует,
функция создает его, как будто dwCreationDistribution были CREATE_NEW.
TRUNCATE_EXISTING
Открывает объект (файл). После этого объект (файл) будет
усечен до нулевого размера.Выдает ошибку если указанный объект (файл) не существует.
DwFlagsAndAttributes
Атрибуты объекта (файла) , атрибуты могут комбинироваться
FILE_ATTRIBUTE_ARCHIVE
FILE_ATTRIBUTE_COMPRESSED
FILE_ATTRIBUTE_HIDDEN
FILE_ATTRIBUTE_NORMAL
FILE_ATTRIBUTE_OFFLINE
FILE_ATTRIBUTE_READONLY
FILE_ATTRIBUTE_SYSTEM
FILE_ATTRIBUTE_TEMPORARY
HTemplateFile
Определяет дескриптор с GENERIC_READ доступом к временному объекту(файлу).
Временный объект(файл)поставляет атрибуты файла и расширенные атрибуты
для создаваемого объекта (файла)
ИСПОЛЬЗУЕТСЯ ТОЛЬКО В WINDOWS NT Windows 95: Это значение должно быть установлено в Nil.
Возвращаемые значения Если функция преуспевает, возвращаемое значение - открытый дескриптор
к указанному объекту(файлу). Если файл не существует - 0.
Если произошли функциональные сбои, возвращаемое значение - INVALID_HANDLE_VALUE.
Чтобы получить расширенные данные об ошибках, вызовите GetLastError. Обратите внимание !
Для портов, dwCreationDistribution параметр должен быть OPEN_EXISTING,
и hTemplate должен быть Nil. Доступ для чтения-записи должен быть определен явно. SECURITY_ATTRIBUTES Структура содержит описание защиты для объекта и определяет,
может ли дескриптор быть унаследован дочерними процессами.
typedef struct _SECURITY_ATTRIBUTES
{ DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES; Параметры NLength
Определяет размер, в байтах, этой структуры.
Набор это значение к размеру структуры SECURITY_ATTRIBUTES В Windows NT
функции которые используют структуру SECURITY_ATTRIBUTES, не
LpSecurityDescriptor
Дескриптор указывающий на описатель защиты для объекта,
Если дескриптор ПУСТОЙ объект может быть назначен в наследование дочерними процессами.
BInheritHandle
Определяет, унаследован ли возвращенный дескриптор, когда новый дескриптор, создан.
Если это значение принимает ИСТИНУ новый дескриптор наследует от головного.
Замечания
Указатель на структуру SECURITY_ATTRIBUTES используется
как параметр в большинстве функций работы с окнами в Win32 API.
---------------------
Структура DCB Структура DCB определяет установку управления для последовательного порта ввода-вывода
(нам она понадобится для разбора примера с программой управления весами ПетрВес) Примечание : В местах где нельзя дать точный перевод
будет дано определение на английском из MSDK и приблизительный его перевод
Описание в эквиваленте C typedef struct _DCB { // dcb
DWORD DCBlength; // Размер DCB
DWORD BaudRate; // Скорость пересылки данных в бодах;
// текущая скорость в бодах
DWORD fBinary: 1; // binary mode, no EOF check
// двоичный режим , не проверять конец
// данных (по умолчанию значение = 1)
DWORD fParity: 1; // Включить проверку четность (по умолчанию
// значение = 1)
DWORD fOutxCtsFlow:1; // CTS управление потоком выхода
DWORD fOutxDsrFlow:1; // DSR управление потоком выхода
DWORD fDtrControl:2; // DTR Тип управления потоком скорости
// передачи данных
DWORD fDsrSensitivity:1; // DSR sensitivity (чувствительность)
DWORD fTXContinueOnXoff:1; // XOFF continues Tx (стоп-сигнал
// продалжает выполнение)
DWORD fOutX: 1; // XON/XOFF out flow control (СТАРТ-
// СИГНАЛ / СТОП-СИГНАЛ для управления
// выходящим потоком (по умолчанию
// значение = 1)
DWORD fInX: 1; // XON/XOFF in flow control (СТАРТ-
// СИГНАЛ / СТОП-СИГНАЛ для управления
// входящим потоком (по умолчанию
// значение = 1)
DWORD fErrorChar: 1; // enable error replacement (включить
// проверку погрешностей по умолчанию=1)
DWORD fNull: 1; // enable null stripping (отвергать
// пустой поток данных (по умолчанию=1))
DWORD fRtsControl:2; // RTS управление потоком данных
DWORD fAbortOnError:1; // abort reads/writes on error
// (проверять операции чтения/записи
// по умолчанию=1)
DWORD fDummy2:17; // reserved ЗАРЕЗЕРВИРОВАНО
WORD wReserved; // not currently used НЕ ДЛЯ
// ИСПОЛЬЗОВАНИЯ
WORD XonLim; // transmit XON threshold (порог
// чувствительности старт-сигнала)
WORD XoffLim; // transmit XOFF threshold (порог
// чувствительности стоп-сигнала)
BYTE ByteSize; // Бит в байте (обычно 8)
BYTE Parity; // 0-4=no,odd,even,mark,space
// (четность байта)
BYTE StopBits; // 0,1,2 = 1, 1.5, 2 (стоповые биты)
char XonChar; // Tx and Rx XON character (вид
// старт сигнал в потоке)
char XoffChar; // Tx and Rx XOFF character (вид
// стоп сигнал в потоке)
char ErrorChar; // error replacement character (какой
// сигнал погрешности,его вид)
char EofChar; // end of input character (сигнал
// окончания потока)
char EvtChar; // received event character РЕЗЕРВ
WORD wReserved1; // reserved; do not use НЕ ДЛЯ
// ИСПОЛЬЗОВАНИЯ
} DCB;

with Mode do
Begin  
BaudRate := 9600;  
ByteSize := 8;  
Parity := NOPARITY;  
StopBits := ONESTOPBIT; // одино?ный стоп-бит  
Flags := EV_RXCHAR + EV_EVENT2;  
End;   

Параметры : DCBlength
Размер DCB структуры.
BaudRate
Определяет скорость в бодах, в которых порт оперирует.
Этот параметр может принимать фактическое значение скорости в бодах,
или один из следующих стандартных индексов скорости в бодах:
CBR_110 CBR_19200
CBR_300 CBR_38400
CBR_600 CBR_56000
CBR_1200CBR_57600
CBR_2400CBR_115200
CBR_4800CBR_128000
CBR_9600CBR_256000
CBR_14400 fBinary
Определяет, допускается ли двоичный (бинарный) способ передачи данных.
Win32 API не поддерживает недвоичные (небинарные)
способы передачи данных в потоке порта, так что этот параметр
должен быть всегда ИСТИНЕН.
Попытка использовать ЛОЖЬ в этом параметре не будет работать.
Примечание : Под Windows 3.1 небинарный способ передачи допускается,
но для работы данного способа необходимо заполнит параметр
EofChar который будет восприниматься конец данных.
fParity
Определяет, допускается ли проверка четности.
Если этот параметр ИСТИНЕН, проверка четности допускается
fOutxCtsFlow
CTS (clear-to-send) управление потоком выхода
fOutxDsrFlow
DSR (data-set-ready) управление потоком выхода
fDtrControl
DTR (data-terminal-ready) управление потоком выхода
Принимает следующие значения :
DTR_CONTROL_DISABLE
Отключает линию передачи дынных
DTR_CONTROL_ENABLE
Включает линию передачи дынных
DTR_CONTROL_HANDSHAKE
Enables DTR handshaking. If handshaking is enabled,
it is an error for the application to adjust the line by using the EscapeCommFunction function.
Допускает подтверждению связи передачи данных
Если подтверждение связи допускается, это - погрешность для того чтобы регулировать(корректировать)
линию связи, используя функцию EscapeCommFunction.
fDsrSensitivity
Specifies whether the communications driver is sensitive to the state of the DSR signal.
If this member is TRUE, the driver ignores any bytes received, unless the DSR modem input line is high.
Определяет возможна ли по порту двухсторонняя передача в ту и в другую сторону сигнала.
fTXContinueOnXoff
Определяет, останавливается ли передача потока ,
когда входной буфер становится полный, и драйвер передает сигнал XoffChar.
Если этот параметр ИСТИНЕН, передача продолжается после того,
как входной буфер становится в пределах XoffLim байтов, и драйвер передает
сигнал XoffChar, чтобы прекратить прием байтов из потока .
Если этот параметр ЛОЖНЫЙ, передача не продолжается до тех пор ,
пока входной буфер не в пределах XonLim байтов,
и пока не получен сигнал XonChar, для возобновления приема .
fOutX
Определяет, используется ли управление потоком СТАРТ-СИГНАЛА / СТОП-СИГНАЛА
в течение передачи потока порту. Если этот параметр ИСТИНЕН, передача останавливается,
когда получен сигнал XoffChar и начинается снова, когда получен сигнал XonChar.
fInX
Specifies whether XON/XOFF flow control is used during reception. If this member is TRUE,
the XoffChar character is sent when the input buffer comes
within XoffLim bytes of being full, and the XonChar character is sent
when the input buffer comes within XonLim bytes of being empty.
Определяет, используется ли управление потоком СТАРТ-СИГНАЛА / СТОП-СИГНАЛА
в течение приема потока портом. Если этот параметр ИСТИНЕН,сигнал XoffChar посылается ,
когда входной буфер находится в пределах XoffLim байтов, а сигнал XonChar посылается
тогда когда входной буфер находится в пределах XonLim байтов или является пустым
fErrorChar
Определяет, заменены ли байты, полученные с ошибками четности особенностью,
указанной параметром ErrorChar Если этот параметр ИСТИНЕН, и fParity ИСТИНЕН, замена происходит.
fNull
Определяет, отвергнуты ли нулевые(пустые) байты. Если этот параметр ИСТИНЕН,
нулевые(пустые) байты, будут отвергнуты при получении их.
fRtsControl
RTS управление потоком " запрос пересылки " .
Если это значение нулевое, то по умолчанию устанавливается RTS_CONTROL_HANDSHAKE.
Принимает одно из следующих значений:
RTS_CONTROL_DISABLE
Отключает строку RTS, когда устройство открыто
RTS_CONTROL_ENABLE
Включает строку RTS
RTS_CONTROL_HANDSHAKE
Enables RTS handshaking. The driver raises the RTS line
when the " type-ahead" (input)
buffer is less than one-half full and lowers
the RTS line when the buffer is more than three-quarters full.
If handshaking is enabled, it is an error for the application
to adjust the line by using the EscapeCommFunction function.
Допускает RTS подтверждение связи. Драйвер управляет потоком пересылки.
RTS выравнивается , когда входной буфер - меньше чем половина полного и
понижается, когда буфер - больше 2/3 полного .Если подтверждение связи
допускается, это используется для регулирования передачи данных
EscapeCommFunction.
RTS_CONTROL_TOGGLE
Specifies that the RTS line will be high if bytes are available for transmission.
After all buffered bytes have been sent, the RTS line will be low.
Определяет, что буфер будет высокий при подготовке данных для передачи.
После того, как все байты отосланы, буфер RTS будет низок.
FAbortOnError
Определяет, закончена ли операции чтения/записи, если происходит погрешность.
Если этот параметр ИСТИНЕН, драйвер закрывает все операции
чтения/записи с состоянием погрешности при возникновении оной.
Драйвер не будет принимать никакие дальнейшие действия,
пока не дождется подтверждения погрешности в передоваемых
(принимаемых) данных, вызывая функцию ClearCommError.
fDummy2
ЗАРЕЗЕРВИРОВАНО Microsoft
wReserved
ЗАРЕЗЕРВИРОВАНО Microsoft
XonLim
Определяет минимальное число байтов, находящихся во в
XoffLim
Определяет максимальное число байтов, находящихся во входном буфере прежде,
чем будет генерирована подача СТОП-СИГНАЛА. Максимальное число байтов,
позволенных во входном буфере вычитается из размеров, в байтах, самого входного буфера.
ByteSize
Определяет число битов в байтах, переданных и полученных.
Parity
Определяет схему четности, которую нужно использовать.
Этот параметр может быть одним из следующих значений:
EVENPARITY
MARKPARITY
NOPARITY
ODDPARITY
StopBits
Определяет число стоповых битов, которые нужно использовать.
Этот параметр может быть одним из следующих значений:
ONESTOPBIT1 stop bit
ONE5STOPBITS1.5 stop bits
TWOSTOPBITS2 stop bits
XonChar
Определяет значение СТАРТ-СИГНАЛА для передачи и приема.
XoffChar
Определяет значение СТОП-СИГНАЛА для передачи и приема.
ErrorChar
Определяет значение СИГНАЛА ОШИБКИ (генерируемого при ошибке четности) для передачи и приема.
EofChar
Определяет значение сигнала конца данных.
EvtChar
Определяет значение сигнала события.
wReserved1
ЗАРЕЗЕРВИРОВАНО Microsoft
Дополнение : Когда структура DCB использует «ручной» выбор конфигурации ,
следующие ограничения используются для ByteSize и StopBits параметров :
Число информационных разрядов должно быть от 5 до 8 битов.
Использование 5 информационных разрядов с 2 стоповыми битами -
недопустимая комбинация, как - 6, 7, или 8 информационных разрядов с 1.5 стоповыми битами.

Взято с Vingrad.ru