Ошибка в обработчиках событий
Александр!
Извиняюсь за длительный перерыв
Разбирался со связкой С++Builder/FR, кое-что кажется нашел. Во-первых,
про обработчики событий.
Как написано в хелпе
"AnsiString is the C++Builder analog for the Delphi long string type.
C++Builder implements the AnsiString type as a class. AnsiString is designed
to function like the Delphi long string type."
Таким образом, компилятор C++ генерит из паскалевского кода:
typedef AnsiString TfrxNotifyEvent;
И получается, что в C++Builder для custom dialog control, написанного на C++
для свойства типа например frxNotifyEvent элемент TTypeInfo.Name="AnsiString",
а для объектов ядра FR, написанных на Паскале
TTypeInfo.Name="TfrxNotifyEvent".
Это приводит к тому, что в дизайнере обработчики событий отображаются не на
своей вкладке и ведут себя как свойство типа String. Полечил я это
исправлением кода методов:
TfrxPropertyEditorCollection.GetPropertyEditor и
TfrxObjectInspector.SetSelectedObjects
предположив, что имя обработчика всегда начинается со строки "On" и тип
свойства AnsiString. Это, конечно, не совсем верно, но работает.
Можно ли это как-то пофиксить более грамотно?
Во-вторых, все-таки про регистрацию редакторов свойств.
Пусть у меня есть обертка вокруг TRxLookupEdit, т.е. класс, аналогичный по
сути TfrxDBLookupComboBox. Возьмем свойство ListField. В коде FR редактор на
это свойство регистрируется так:
frxPropertyEditors.Register(TypeInfo(String), TfrxDBLookupComboBox,
'ListField', TfrxDataFieldProperty);
Каким образом мне зарегистрировать редактор на это свойство типа AnsiString
в своем классе?
Вот ответ из FAQ of RU.CBUILDER:
***********
#include <dsgnintf.hpp>
#include <typinfo.hpp>
namespace Mycomponent
{
void __fastcall PACKAGE Register()
{
RegisterPropertyEditor(*(GetPropInfo((PTypeInfo)(TObject::ClassInfo(
__classid(TMyComponent))), "AnsiStringProperty")->PropType),
__classid(TMyComponent), "AnsiStringProperty",
__classid(TMyPropEditor));
}
}
Проблема в том, что дельфийский typeinfo(string) не имеет аналога в CB. Так
искомый typeinfo берется из RTTI самого компонента (там есть входы для всех
published пропертей). Если надо зарегистрировать PropertyEditor не для
конкретного компонента, то подойдет любой с пропертью типа AnsiString
(какой-нибудь TLabel->Caption).
***********
При таком подходе в дизайнере около свойства ListField появляется кнопка со
стрелкой, но список доступных полей не выпадает. Если же перписать класс
TfrxDataFieldProperty на C++ и зарегистрировать в качестве редактора свойства,
все работает правильно.
Может быть здесь тоже проблема несоответствия String/AnsiString?
Как быть с этим?
P.S. Проверено на 3.17 Ent
Извиняюсь за длительный перерыв
Разбирался со связкой С++Builder/FR, кое-что кажется нашел. Во-первых,
про обработчики событий.
Как написано в хелпе
"AnsiString is the C++Builder analog for the Delphi long string type.
C++Builder implements the AnsiString type as a class. AnsiString is designed
to function like the Delphi long string type."
Таким образом, компилятор C++ генерит из паскалевского кода:
typedef AnsiString TfrxNotifyEvent;
И получается, что в C++Builder для custom dialog control, написанного на C++
для свойства типа например frxNotifyEvent элемент TTypeInfo.Name="AnsiString",
а для объектов ядра FR, написанных на Паскале
TTypeInfo.Name="TfrxNotifyEvent".
Это приводит к тому, что в дизайнере обработчики событий отображаются не на
своей вкладке и ведут себя как свойство типа String. Полечил я это
исправлением кода методов:
TfrxPropertyEditorCollection.GetPropertyEditor и
TfrxObjectInspector.SetSelectedObjects
предположив, что имя обработчика всегда начинается со строки "On" и тип
свойства AnsiString. Это, конечно, не совсем верно, но работает.
Можно ли это как-то пофиксить более грамотно?
Во-вторых, все-таки про регистрацию редакторов свойств.
Пусть у меня есть обертка вокруг TRxLookupEdit, т.е. класс, аналогичный по
сути TfrxDBLookupComboBox. Возьмем свойство ListField. В коде FR редактор на
это свойство регистрируется так:
frxPropertyEditors.Register(TypeInfo(String), TfrxDBLookupComboBox,
'ListField', TfrxDataFieldProperty);
Каким образом мне зарегистрировать редактор на это свойство типа AnsiString
в своем классе?
Вот ответ из FAQ of RU.CBUILDER:
***********
#include <dsgnintf.hpp>
#include <typinfo.hpp>
namespace Mycomponent
{
void __fastcall PACKAGE Register()
{
RegisterPropertyEditor(*(GetPropInfo((PTypeInfo)(TObject::ClassInfo(
__classid(TMyComponent))), "AnsiStringProperty")->PropType),
__classid(TMyComponent), "AnsiStringProperty",
__classid(TMyPropEditor));
}
}
Проблема в том, что дельфийский typeinfo(string) не имеет аналога в CB. Так
искомый typeinfo берется из RTTI самого компонента (там есть входы для всех
published пропертей). Если надо зарегистрировать PropertyEditor не для
конкретного компонента, то подойдет любой с пропертью типа AnsiString
(какой-нибудь TLabel->Caption).
***********
При таком подходе в дизайнере около свойства ListField появляется кнопка со
стрелкой, но список доступных полей не выпадает. Если же перписать класс
TfrxDataFieldProperty на C++ и зарегистрировать в качестве редактора свойства,
все работает правильно.
Может быть здесь тоже проблема несоответствия String/AnsiString?
Как быть с этим?
P.S. Проверено на 3.17 Ent