Использование констант по файлам .dfm в студии embarcadero / RAD - PullRequest
2 голосов
/ 23 января 2020

У меня есть Windows Приложение Vcl, которое имеет несколько форм внутри. Я хотел стандартизировать макет для всех этих форм. Поэтому я хотел объявить некоторые константы, которые я могу применить ко всем моим файлам макета .dfm.

Например, эта главная из - это автоматически сгенерированная форма в IDE:

object frm_MainForm: Tfrm_MainForm
  Left = 0
  Top = 0
  Caption = 'Main Form'
  ClientHeight = 300
  ClientWidth = 400    
  Color = clBtnFace
end

Я хотел объявить что-то вроде:

AllFormHeight = 300
AllFormWidth = 400

, чтобы я мог применить ко всем формам, как показано ниже:

object frm_MainForm: Tfrm_MainForm
  Left = 0
  Top = 0
  Caption = 'Main Form'
  ClientHeight = AllFormHeight <--- Like this
  ClientWidth = AllFormWidth <--- And this
  Color = clBtnFace
end

Я пытался сделать что-то, почти похожее на цвет константа в Vcl.Graphics.hpp, но она не работает. Я использую Embarcadero RAD studio C ++ Builder 10.3. Я использовал C ++ для программирования и файл dfm в качестве файла пользовательского интерфейса.

1 Ответ

3 голосов
/ 24 января 2020

Пользовательские строковые идентификаторы CAN могут использоваться в DFM для целочисленных / перечислимых свойств. Для этого вам нужно вызвать RegisterIntegerConsts() в <System.Classes.hpp>, чтобы зарегистрировать ваши собственные пользовательские функции, которые конвертируют между строковыми идентификаторами и их порядковыми значениями. В вашем случае преобразование строк "AllFormHeight" и "AllFormWidth" в заданные c целочисленные значения и наоборот.

Например, именно так, как показано в примере DFM, допускается идентификатор clBtnFace для использования в свойстве Color.

Попробуйте:

#include <System.Classes.hpp>
#include <System.TypInfo.hpp>
#include <sysopen.h>

const int AllFormHeight = 300;
const int AllFormWidth = 400;

const TIdentMapEntry MyFormIdents[] = {
    {AllFormHeight, "AllFormHeight"},
    {AllFormWidth, "AllFormWidth"}
};

bool __fastcall MyFormIdentToInt(const String Ident, int &Int)
{
    return IdentToInt(Ident, Int, EXISTINGARRAY(MyFormIdents));
}

bool __fastcall MyIntToFormIdent(int Int, String &Ident)
{
    return IntToIdent(Int, Ident, EXISTINGARRAY(MyFormIdents));
}

// See http://bcbjournal.org/articles/vol3/9908/Registering_AnsiString_property_editors.htm
// for why this function is needed...
TTypeInfo* IntTypeInfo()
{
    TTypeInfo* typeInfo = new TTypeInfo;
    typeInfo->Name = "int";
    typeInfo->Kind = tkInteger;
    return typeInfo;

    /* alternatively:
    TPropInfo* PropInfo = GetPropInfo(__typeinfo(TForm), "ClientHeight");
    return *PropInfo->PropType;
    */
}

RegisterIntegerConsts(IntTypeInfo(), &MyFormIdentToInt, &MyIntToFormIdent);

Однако недостатком этого подхода является то, что свойства ClientHeight / ClientWidth используют int как их тип данных, ваши пользовательские идентификаторы будут применены к ЛЮБОМУ int свойству в ЛЮБОМ поточном классе. Вместо этого RegisterIntegerConsts() обычно используется только для более уникальных типов данных, например TColor, TFontCharset и т. Д. c.

. Вы не можете сами изменить свойства ClientHeight / ClientWidth на используйте другой тип данных, чтобы у вас было что-то уникальное для сопоставления ваших идентификаторов. Но вы можете определить свои собственные свойства, которые используют ваш собственный тип данных, который вы затем сможете отобразить. Или вы можете попробовать переопределить форму для метода DefineProperties() , чтобы создать «поддельные» свойства только для потоковой передачи DFM. В любом случае, вы можете при желании повторно объявить свойства ClientHeight / ClientWidth в своем классе Form, чтобы включить атрибут stored=false, чтобы они вообще не передавались в DFM. Ваши пользовательские свойства должны прочитать / установить свойства ClientHeight / ClientWidth внутри.

...