Может кто объяснит подробнее особенности применения директив вызовов процедур: register, pascal, cdecl, stdcall, safecall.
В чём отличия, когда и какие надо применять, какие преимущества и недостатки?

 

Разница в способе передачи параметров в функцию и возврата параметров из функции.

stdcall - юзается (вроде) а винапях. Передача аргументов справа налево. Стек очищает вызываемая процедура. Возвращает разультат в EAX (помойму)

pascal - юзалось в вин16апи. Передача в аргументов слева направо. Стек очищает вызываемая. В паскале результат возвращался в al, ax или в dx:ax. Как в Дельфи - не помню, вероятно а EAX.

register - передача всего через регистры процессора. Как именно - зависит от компилятора.

cdecl - не помню. Вроде тоже, что и stdcall, только стек чистит вызывающая процедура

 

Каким образом можно использовать переменную типа String в качестве имени процедуры?

 

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

 

Code:

{©Drkb v.3(2007): www.drkb.ru,

®Vit (Vitaly Nevzorov) - Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.}

 

For i:=0to Maximum doif i mod step = 0then

begin

end;

 

Переменная Step и есть нужный шаг

 

 

Автор:Vit  

Взято из http://forum.sources

Paramcount - показывает сколько параметров передано

Paramstr(0) - это имя с путем твоей программы

Paramstr(1) - имя первого параметра

Paramstr(2) - имя второго параметра и т.д.

 

Если ты запускаешь:

с:\myprog.exe /a -b22 c:\dev

 

то Paramcount будет равен 3

Paramstr(0) будет равен с:\myprog.exe

Paramstr(1) будет равен /a

Paramstr(2) будет равен -b22

Paramstr(3) будет равен c:\dev

 

Code:

 

{ .... }

 

type

VA_FN = function(const par1, par2{, ...}: Pointer): Boolean;

cdecl varargs;

 

{ .... }

 

//

// varargs without "external" keyword

//

function fn(const par1, par2{, ...}: Pointer): Boolean; cdecl;

var

last_arg: Pointer absolute par2;

ptr_args: array[0..MAXLONG shr2] of Pointer absolute last_arg;

dw_args: array[0..MAXLONG shr2] of Cardinal absolute last_arg;

s_args: array[0..MAXLONG shr2] of PChar absolute last_arg;

w_args: array[0..MAXLONG shr2] of WideString absolute last_arg;

begin

// ptr_args[1] is first optional argument

Result := (ptr_args[1] {par3} = Pointer(1)) and

(dw_args[2] {par4} = 2) and

(string(ptr_args[3]) = 'CHAR') and

(w_args[4] = 'WCHAR');

end;

 

procedure test_fn;

begin

// VA_FN typecast

VA_FN(@fn)({par1}nil, {par2}nil, {par3}Pointer(1), {par4}2, {par5}'CHAR',

{par6}WideString('WCHAR'));

end;

 

 

 

Взято с сайтаhttp://www.swissdelphicenter.ch/en/tipsindex

Code:

var

X1, X2: Byte;

begin

X1 := X2 xor X2;

X2 := X1 xor X2; // X2 = X1

X1 := X1 xor X2; // X1 = X2

 

 

Code:

{ You maybe have to access just a part of a GUID. }

 

 

{ Const for the function Format(...) }

const

fsGUID: string = 'D1: $%s'#13#10'D2: $%s'#13#10'D3: $%s'#13#10 +

'D4: $%s $%s $%s $%s $%s $%s $%s $%s';

fsGUIDParts: string = 'D%d:%s';

 

// Type for the GUID part to be shown

type

 

TGUIDPART = (guidp_NoFormat, guidp_All, guidp_D1,

guidp_D2, guidp_D3, guidp_D4);

 

{ This GUIDToStringEx function give you the full GUID string

according with then format string FStr (you can change it !!!) }

function GUIDToStringEx(Guid: TGuid; FStr: string): string; overload;

begin

Result := Format(FStr,

[IntToHex(GUID.D1, 8),

IntToHex(GUID.D2, 4),

IntToHex(GUID.D3, 4),

IntToHex(GUID.D4[0], 2),

IntToHex(GUID.D4[1], 2),

IntToHex(GUID.D4[2], 2),

IntToHex(GUID.D4[3], 2),

IntToHex(GUID.D4[4], 2),

IntToHex(GUID.D4[5], 2),

IntToHex(GUID.D4[6], 2),

IntToHex(GUID.D4[7], 2)

]);

end;

 

{ This GUIDToStringEx function give you the part of the GUID

to be shown, according to the part type GUIDPart }

function GUIDToStringEx(Guid: TGuid; Part: TGUIDPART): string; overload;

var

i: Integer;

S: string;

begin

S := '';

case Part of

guidp_NoFormat: S := GUIDToString(Guid);

guidp_All: S := GUIDToStringEx(Guid, fsGUID);

guidp_D1: S := Format(fsGUIDParts, [1, ' $' + IntToHex(GUID.D1, 8)]);

guidp_D2: S := Format(fsGUIDParts, [2, ' $' + IntToHex(GUID.D2, 4)]);

guidp_D3: S := Format(fsGUIDParts, [3, ' $' + IntToHex(GUID.D3, 4)]);

guidp_D4:

begin

for i := 0to7do S := S + ' $' + IntToHex(GUID.D4[i], 2);

S := Format(fsGUIDParts, [4, S]);

end;

else

S := '?';

end;

Result := S;

end;

 

{ How to use the different GUIDToStringEx functions }

 

procedure TForm1.Button1Click(Sender: TObject);

var

NewGUID: TGUID;

begin

{ Create a new GUID }

NewGUID := StringToGUID(CreateClassID);

 

{ Standard formated GUID string }

label1.Caption := GUIDToStringEx(NewGUID, guidp_NoFormat) +

#13#10 +

 

{ Full formated GUID string acc. with fsGUID}

GUIDToStringEx(NewGUID, fsGUID) +

#13#10 +

 

{ Full formated GUID string with default formating}

GUIDToStringEx(NewGUID, guidp_All) +

#13#10 +

 

{ Part D3 of the GUID only }

GUIDToStringEx(NewGUID, guidp_D3);

end;

 

 

Взято с сайтаhttp://www.swissdelphicenter.ch/en/tipsindex

BEEP , для дельфи , который работает, как в B.Pascal 7.0

 

Я применяю следующий код, однако он работает только под Win9x/me

(Под WinNT/2000/XP вы можете использовать Beep(Tone, Duration)

- задавать тон и продолжительность звучания).

 

 

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

 

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

Наблюдаются многочисленные глюки при прорисовке, сообщения системы об ошибках и перерасходе ресурсов без видимых причин, вплоть до убиения приложения системой или краха системы. Характерно для Windows линии 9X, у которых максимальное количество графических и оконных ресурсов (GDI и USER) сильно ограничено.

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

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

 

ТИПОВЫЕ РЕШЕНИЯ.

 

1. Уменьшить количество автоматически создаваемых форм. Создавать тяжелые формы в тот момент, когда они понадобятся, и уничтожать при закрытии. При этом нужно следить за своевременной очисткой и проверкой глобальных ссылок на формы.
2. У динамически создаваемых компонентов устанавливать владельца и родителя. Подробности - в статье "Жизнь и смерть в режиме run-time".
3. Большое количество форм не всегда оправдано. Если пользователь не получает дополнительных удобств от того, что может открыть много форм (часто он не может их увидеть одновременно или работает постоянно с одной), то это неверное архитектурное решение.
  Интерфейс MDI - хорошая концепция. Но всякое техническое решение имеет свою область применения. Это удобно, когда пользователю нужно работать с однотипными объектами в разных окнах и переходить от одного к другому, причем количество их заранее неизвестно, и допускается изменение размеров окна. Примеры - работа с документами (Word, Excel, etc.).
4. Как правило, многочисленные элементы управления не нужны пользователю одновременно (вспомните о правиле 7±2 - именно таково среднее количество объектов, за которыми человек может следить одновременно, не напрягаясь). Их можно разделить на группы и расположить на страницах компонента TPageControl. Таким способом можно скрыть видимую сложность очень большого интерфейса по вводу и редактированию данных.
  Если группы компонентов однотипны (меняются только данные), то решение еще более упрощается, с одновременным снятием нагрузки на ресурсы системы. Компонент TTabControl, который внешне выглядит также, как и TPageControl, содержит только одну группу контролов, а программист по событию смены закладки OnChange имеет возможность сменить данные.
5. Большое количество регулярно расположенных контролов TEdit, TLabel успешно заменяется на TStringGrid, специально для этого предназначенный. Кроме всего прочего, он имеет удобную прокрутку, размеры таблицы не будут ограничены размерами формы.
  В случае, если нужно много TComboBox, применяют следующую хитрость. Для визуализации используют TStringGrid, а для редактирования в текущую ячейку вставляют TComboBox, устанавливая ему размеры и координаты по ячейке и набивая его программно (если набор элементов меняется). Один и тот же экземпляр редактирующего контрола используется во всех ячейках, поскольку он не нужен одновременно везде. Эта же техника используется и в VCL для редактирования ячеек TStringGrid, TDBGrid.
  Есть масса компонентов типа TStringGrid сторонних разработчиков, которые расширяют возможности стандартного.
6. DB-aware визуальные компоненты - такие как TDBGrid - способны обрабатывать огромный объем данных, не требуя при этом пропорциональное количество ресурсов GDI/USER. В конце концов, если не хочется связываться с СУБД, можно загнать информацию в TClientDataSet и кормить из него DB-aware controls на форме. Одновременно получаешь все прелести сортировки и фильтрации данных.
  В случае сложного набора контролов для каждой записи, при необходимости видеть несколько таких групп одновременно, хорошо подходит компонент TDBCtrlGrid.
7. Следует стремиться уменьшить количество компонентов - потомков TWinControl (например - TButton), заменяя их на потомки TGraphicControl (пример - TSpeedButton). Последние не используют объекты USER, поскольку не являются окнами в понятиях Windows.
8. Рекомендуется разрабатывать и эксплуатировать ресурсоемкие приложения в среде Windows NT и ее наследников (2000, XP).

 

Автор:Александр Малыгин

 

 

Взято с http://delphiworld.narod

Передача параметров процедуры и функции в дельфи: 

Code:

Type Ta=arrayof something;

Var a:Ta;

 

 

 

 

 

Code:

// функция Chameleon, возвращающая тип сгенерированного исключения

 

unit Unit1;

 

interface

 

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls,

Forms, Dialogs, StdCtrls;

 

type

MyBoolean = class

public

Value: boolean;

end;

 

MyInteger = class

public

Value: integer;

end;

 

MyClass = class

public

Value: TStrings;

end;

 

TForm1 = class(TForm)

Button1: TButton;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

procedure MyProc;

function Chameleon: boolean;

end;

 

var

 

Form1: TForm1;

 

implementation

 

{$R *.DFM}

 

function TForm1.Chameleon: boolean;

var

b: MyBoolean;

i: MyInteger;

c: MyClass;

r: integer;

begin

r := Random(3);

case r of

0:

begin

b := MyBoolean.Create;

raise b;

end;

1:

begin

i := MyInteger.Create;

raise i;

end;

2:

begin

c := MyClass.Create;

raise c;

end;

end;

end;

 

procedure TForm1.MyProc;

begin

try

Chameleon;

except

on MyBoolean do

ShowMessage('Функция возвратила класс MyBoolean');

on MyInteger do

ShowMessage('Функция возвратила класс MyInteger');

on MyClass do

ShowMessage('Функция возвратила класс MyClass');

end;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

begin

Chameleon;

end;

 

end.

 

Взгляните на тип данных Variant в D2: следующий код

 

Code:

function AnyType(const TypeParm: integer): Variant;

begin

case TypeParm of

1: Result := 1;

2: Result := 2.0;

3: Result := 'Три';

4: Result := StrToDate('4/4/1944');

end;

end;

 

 

 

абсолютно бестолковый, но полностью корректный!

 

Следующий код содержит объявление трех функций, принимающих на входе один и тот же параметр, но выдающих результаты различных типов (результат физичиски один и тот же, и занимает он 4 байта). Я не думаю, что можно одурачить delphi, чтобы с помощью этого метода возвратить строку. Это может привести к разрушению менеджера кучи. Вместо этого вызывайте необходимую вам функцию. Каждый вызов передается MyFuncRetAnything, а P1 определяет возвращаемый тип. Если хотите, можете написать другую обертку, делающую для вас еще и приведение типов.

 

3 вызова, 1 код.

 

Я понимаю, что это в действительности не то, что нужно, по я просто хотел продемонстрировать другой способ. (вы можете возвращать строки как тип PChar, который также занимает 4 байта). Вы должны использовать некоторую память, распределяемую вызовом процедуры (может быть передавать результаты как P2?).

 

Code:

{моя форма имеет 3 метки, одну кнопку и этот код}

 

var

MyFuncRetInt: function(P1, P2: Integer): Integer;

MyFuncRetBool: function(P1, P2: Integer): LongBool;

MyFuncRetPointer: function(P1, P2: Integer): Pointer;

 

function MyFuncRetAnything(P1, P2: Integer): Integer;

var

RetPointer: Pointer;

RetBool: LongBool;

RetInteger: Integer;

begin

RetPointer := nil;

RetBool := False;

RetInteger := 4711;

case P1 of

1: Result := Integer(RetPointer);

2: Result := Integer(RetBool);

3: Result := RetInteger;

end;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

begin

if MyFuncRetBool(2, 1900) then

Label1.Caption := 'True'

else

Label1.Caption := 'False';

Label2.Caption := IntToStr(MyFuncRetInt(3, 1900));

Label3.Caption := IntToHex(Integer(MyFuncRetPointer(1, 1900)), 16);

end;

 

initialization

MyFuncRetInt := @MyFuncRetAnything;

MyFuncRetBool := @MyFuncRetAnything;

MyFuncRetPointer := @MyFuncRetAnything;

 

end.

 

 

 

 

 

Взято сhttp://delphiworld.narod