FAQ VCL
Компилятор, RTTI

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика

Как определить, запущена Delphi или нет?

// Способ первый
if FindWindow('TAppBuilder', nil) <> 0 then
   ShowMessage('Delphi запущен');

// Способ второй
procedure TForm1.Button1Click(Sender: TObject);
const
  A1: array[0..12] of char = 'TApplication'#0;
  A2: array[0..13] of char = 'TAlignPalette'#0;
  A3: array[0..18] of char = 'TPropertyInspector'#0;
  A4: array[0..11] of char = 'TAppBuilder'#0;
var
  H1, H2, H3, H4: Hwnd;
  s: string;
begin
  H1 := FindWindow(A1, nil);
  H2 := FindWindow(A2, nil);
  H3 := FindWindow(A3, nil);
  H4 := FindWindow(A4, nil);
  s := 'No';
  if (H1 <> 0) and (H2 <> 0) and (H3 <> 0) and (H4 <> 0) then
    s := 'Yes';
  Form1.Caption := s;
end;

// Способ третий
function DelphiLoaded: Boolean;

  function WindowExists(ClassName, WindowName: PChar): Boolean;
  begin
    if FindWindow(ClassName, WindowName) <> 0 then
      WindowExists := True
    else
      WindowExists := False;
  end;

begin
  DelphiLoaded := False;
  if WindowExists('TPropertyInspector', nil) then
    if WindowExists('TAlignPalette', 'Align') then
      if WindowExists('TApplication', nil) then
        if WindowExists('TAppBuilder', nil) then
          DelphiLoaded := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if DelphiLoaded then
    ShowMessage('Yes')
  else
    ShowMessage('No');
end;


Как определить версию компилятора?

procedure TForm1.Button1Click(Sender: TObject);
const
  Version =
  {$IFDEF VER80}  'Delphi1';              {$ENDIF}
  {$IFDEF VER90}  'Delphi2';              {$ENDIF}
  {$IFDEF VER100} 'Delphi3';              {$ENDIF}
  {$IFDEF VER120} 'Delphi4';              {$ENDIF}
  {$IFDEF VER130} 'Delphi5';              {$ENDIF}
  {$IFDEF VER140} 'Delphi6';              {$ENDIF}
  {$IFDEF VER150} 'Delphi7';              {$ENDIF}
  {$IFDEF VER160} 'Delphi8';              {$ENDIF}
  {$IFDEF VER170} 'Delphi9 (2005)';       {$ENDIF}
  {$IFDEF VER180} 'Delphi10 (2006)';      {$ENDIF}
  {$IFDEF VER185} 'Delphi11 (2007)';      {$ENDIF}
  {$IFDEF VER190} 'Delphi11 (2007) .NET'; {$ENDIF}
  {$IFDEF VER200} 'Delphi12 (2009)';      {$ENDIF}
  {$IFDEF VER210} 'Delphi14 (2010)';      {$ENDIF}
  {$IFDEF VER220} 'Delphi15 (XE)';        {$ENDIF}
  {$IFDEF VER230} 'Delphi16 (XE2)'
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER240} 'Delphi17 (XE3)'
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER250} 'Delphi18 (XE4)'
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER260} 'Delphi19 (XE5)'
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER270} 'Delphi20 (XE6)'
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER280} 'Delphi21 (XE7)'
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER290} 'Delphi22 (XE8)'
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER300} 'Delphi23 (10 Seattle)'    // https://docwiki.embarcadero.com/RADStudio/Seattle/en/Compiler_Versions
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER310} 'Delphi24 (10.1 Berlin)'   // https://docwiki.embarcadero.com/RADStudio/Berlin/en/Compiler_Versions
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER320} 'Delphi25 (10.2 Tokyo)'    // https://docwiki.embarcadero.com/RADStudio/Tokyo/en/Compiler_Versions
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER330} 'Delphi26 (10.3 Rio)'      // https://docwiki.embarcadero.com/RADStudio/Rio/en/Compiler_Versions
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER340} 'Delphi27 (10.4 Sydney)'   // https://docwiki.embarcadero.com/RADStudio/Sydney/en/Compiler_Versions
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER350} 'Delphi28 (11 Alexandria)' // https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Compiler_Versions
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER360} 'Delphi29 (12 Athens)'     // https://docwiki.embarcadero.com/RADStudio/Athens/en/Compiler_Versions
    {$IFDEF CPUX86} + ' x86'; {$ENDIF}
    {$IFDEF CPUX64} + ' x64'; {$ENDIF}
  {$ENDIF}
  {$IFDEF VER93}  'CBuilder1';            {$ENDIF}
  {$IFDEF VER110} 'CBuilder3';            {$ENDIF}
  {$IFDEF VER125} 'CBuilder4';            {$ENDIF}
  {$IFDEF VER135} 'C++Builder5';          {$ENDIF}
  {$IFDEF VER145} 'C++Builder6';          {$ENDIF}
  {$IFDEF VER155} 'C++Builder7';          {$ENDIF}
  {$IFDEF KYLIX}  'Kylix1';               {$ENDIF}
  {$IFDEF KYLIX2} 'Kylix2';               {$ENDIF}
  {$IFDEF KYLIX3} 'Kylix3';               {$ENDIF}
  {$IFDEF KYLIX4} 'Kylix4';               {$ENDIF}
begin
   ShowMessage( Format( 'Для компиляции был использован %s', [Version] ) );
end;


Как выводить свои собственные сообщения при компилляции?

Формат команды:
{$MESSAGE HINT|WARN|ERROR|FATAL 'text string'}

Варианты использования:
{$MESSAGE 'Появился новый hint!'}
{$MESSAGE Hint 'И это тоже hint!'}
{$MESSAGE Warn 'А это уже Warning'}
{$MESSAGE Error 'Эта строка вызовет ошибку компиляции!'}
{$MESSAGE Fatal 'А это фатальная ошибка компиляции!'}

Пример: 
destructor TumbSelectionTempTable.Destroy;
begin
  {$MESSAGE Warn ' - remember to free all allocated objects'}
  ClearAllOuterWorldFold;
  if FSubjectsTempTableCreated then
    DropTempTable(FTableName);

  FOuterWorldsFolded.Free;
  FQuery.Free;
  inherited;
end;


Как добавлять записи в TODO лист?

procedure TForm1.FormCreate(Sender: TObject);
begin
  // TODO 1 -oOwner -cCategory : Description
end;

1           : число от 1 до 5 в колонке '!'
-o          : колонка Owner
-c          : колонка Category
Description : описание заметки

Чтобы пометить запись как выполненную  необходимо заменить TODO на DONE


Как отличить DesignTime от RunTime?

if csDesigning in ComponentState then
  {...} // Designtime
else
  {...} // RunTime


Как показать свое сообщение в окне Event Log во время отладки приложения?

// Окно Event Log вызывается сочетанием клавиш Ctrl+Alt+V
OutputDebugString( 'ха-ха, привет из под дебага :)' );


Как получить индекс элемента перечисления по его символьному представлению?

uses
  {...,} TypInfo;

type
  TTestEnum = (Val1, Val2, Val3, Val4);

// Так можно сделать во всех версиях Delphi
procedure _GetEnumValue(Val: string);
var
  Index: TTestEnum;
begin
  Index := TTestEnum(GetEnumValue(TypeInfo(TTestEnum), Val));
  ShowMessage(IntToStr(Integer(Index)));
end;

// А этот вариант не работает в Delphi 7 и более ранних,
// зато работает в Delphi 2010 (в других не проверял)
procedure _GetEnumValue(Val: string);
var
  Index: TTestEnum;
begin
  Index := TTestEnum(GetEnumValue(TypeInfo(TTestEnum), Val));
  if Index = TTestEnum.Val2 then
    ShowMessage('Yes');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  _GetEnumValue('Val2');
end;


Как получить символьное представление элемента перечисления по его индексу?

// Способ первый
uses
  {...,} TypInfo;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Caption := GetEnumName(TypeInfo(TWindowState), Ord(wsMaximized));
end;

// Способ второй
uses
  {...,} Rtti;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Caption := TRttiEnumerationType.GetName(wsMaximized);
end;


Как получить информацию о утечках памяти?

// Код будет работать во всех версиях Delphi начиная с BDS2006.
// При запуске главной формы включаем "ловушку".
// По завершению работы приложения, если запуск был из под IDE, будет показано окошко с краткой информацией о утечках памяти.
procedure TfmMain.FormCreate(Sender: TObject);
begin
  // Отлавливаем утечки памяти
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;
end;


Как определить, есть ли некоторое свойство (например, Hint) у объекта?

// Способ первый
uses
  {...,} TypInfo;

// Таким образом можно узнать о наличие только published property
procedure TForm1.Button1Click(Sender: TObject);
begin
  if GetPropInfo(Button1.ClassInfo, 'Hint') <> nil then
    ShowMessage('Оно есть!');
end;

// Способ второй
type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    {...}
  end;

{...}

implementation

uses
  {...,} TypInfo;

function HasProp(Comp: TComponent; const Prop: string): Boolean;
var
  PropList: PPropList;
  NumProps, i: Integer;
begin
  Result := False;
  GetMem(PropList, getTypeData(Comp.ClassInfo)^.PropCount * SizeOf(Pointer));

  try
    NumProps := GetPropList(Comp.ClassInfo, tkProperties, PropList);
    for i := 0 to Pred(NumProps) do
    begin
      if CompareText(UpperCase(PropList[i]^.Name), UpperCase(Prop)) = 0 then
      begin
        Result := True;
        Break;
      end;
    end;
  finally
    FreeMem(PropList, getTypeData( Comp.ClassInfo)^.PropCount * SizeOf(Pointer));
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if HasProp(Edit1, 'TextHint') then
    ShowMessage('Свойстао есть.');
end;

При использовании материала - ссылка на сайт обязательна