Форум: "Основная";
Текущий архив: 2002.09.12;
Скачать: [xml.tar.bz2];
ВнизTStrings * не считывается из DFM Найти похожие ветки
← →
murza (2002-08-26 12:21) [0]Есть небольшая проблема. Есть компонент. Есть свойство
__property TStrings *Definition = {read = FDefinition, write = SetDefinition};
На него, кстати, редактор повешен.
Строки замечательно пишутся в DFM. Проблема в том, что при чтении из DFM SetDefinition не вызывается. И еще он не вызывается приMyComponent1->Definition->Text = "String1\nString2";
Кажется он вызывается только приMyComponent1->Definition = MyStringList;
ЗЫ у меня BCB5
← →
Игорь Шевченко (2002-08-26 12:23) [1]Правильно кажется. TStrings - абстрактный класс
← →
murza (2002-08-26 12:24) [2]Чушь! Я ж не создаю TStrings. К тому же в TMemo Lines так же сделаны.
← →
Skier (2002-08-26 12:30) [3]murza
А оно у тебя опубликовано ? :)
← →
murza (2002-08-26 12:34) [4]Да, да __published. Редактор работает.
← →
Игорь Шевченко (2002-08-26 12:51) [5]Memo.Lines - TMemoStrings
← →
murza (2002-08-26 12:58) [6]
> Игорь Шевченко © (26.08.02 12:51)
> Memo.Lines - TMemoStrings
Позвольте...
C:\Program Files\Borland\CBuilder5\Source\Vcl\stdctrls.pas:
TCustomMemo = class(TCustomEdit)
private
FLines: TStrings;
...
public
...
property Lines: TStrings read FLines write SetLines;
end;
...
TMemo = class(TCustomMemo)
published
...
property Lines;
...
end;
...
procedure TCustomMemo.SetLines(Value: TStrings);
begin
FLines.Assign(Value);
end;
(Правда совсем непонятно, за счет чего перерисовывается)
← →
Skier (2002-08-26 13:04) [7]>murza
А как насчёт этого :
constructor TCustomMemo.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Width := 185;
Height := 89;
AutoSize := False;
FWordWrap := True;
FWantReturns := True;
FLines := TMemoStrings.Create;
TMemoStrings(FLines).Memo := Self;
end;
← →
murza (2002-08-26 13:08) [8]> Skier © (26.08.02 13:04)
Это не меняет дела (хотя теперь понятно, почему перерисовывается). Смотри вопрос.
← →
Skier (2002-08-26 13:10) [9]>murza
> Это не меняет дела
???
← →
murza (2002-08-26 13:11) [10]
> Skier © (26.08.02 13:10)
> ???
Хорошо, поясню:
> Есть небольшая проблема. Есть компонент. Есть свойство
> __property TStrings *Definition = {read = FDefinition, write
> = SetDefinition};
> На него, кстати, редактор повешен.
> Строки замечательно пишутся в DFM. Проблема в том, что при
> чтении из DFM SetDefinition не вызывается. И еще он не вызывается
> при MyComponent1->Definition->Text = "String1\nString2";
> Кажется он вызывается только при MyComponent1->Definition
> = MyStringList;
> ЗЫ у меня BCB5
Почему SetDefinition не вызывается?
← →
Игорь Шевченко (2002-08-26 13:13) [11]Код в студию
← →
Skier (2002-08-26 13:15) [12]>murza
> Кажется он вызывается
Это очень интересное словечко...На ощупь идёшь что ли ?
← →
murza (2002-08-26 13:40) [13]
> Игорь Шевченко © (26.08.02 13:13)
> Код в студию
Сами напросились. Разбирайте:
class PACKAGE TGlobFun : public TComponent
{
//...skipped...
private:
//...skipped...
GLOBFUNC FFunc;
TStrings * FDefinition;
protected:
//...skipped...
int __fastcall SetFunc(GLOBFUNC f);
void __fastcall SetDefinition(TStrings *Def);
public:
//...skipped...
void __fastcall EditFuncDefinition();
__published:
//...skipped...
__property TStrings *Definition = {read = FDefinition, write = SetDefinition};
};
//----------------------------------------
class TGlobFuncDefinitionPropertyEditor : public TPropertyEditor
{
__fastcall TGlobFuncDefinitionPropertyEditor (void)
: Dsgnintf::TPropertyEditor (Designer, 0) {}
TPropertyAttributes __fastcall GetAttributes ()
{ return TPropertyAttributes() << paDialog; }
AnsiString __fastcall GetValue() { return "(TStrings)"; }
void __fastcall Edit() { ((TGlobFun*)GetComponent(0))->EditFuncDefinition(); }
};
//----------------------------------------
void __fastcall TGlobFun::SetDefinition(TStrings *Def) {
// ShowMessage("TGlobFun::SetDefinition");
GLOBFUNC *pFunc;
pFunc = TextToFunc(Def);
if (pFunc != NULL) SetFunc(*pFunc);
delete pFunc;
}
//----------------------------------------
int __fastcall TGlobFun::SetFunc(GLOBFUNC f)
{
//...skipped...
FFunc = f;
//...skipped...
delete FDefinition;
FDefinition = FuncToText(&FFunc);
//...skipped...
}
//----------------------------------------
void __fastcall TGlobFun::EditFuncDefinition()
{
TGFCodeForm *GFCodeForm = new TGFCodeForm(Application, &FFunc, false);
if (GFCodeForm->ShowModal() == mrOk)
if (FFunc != *(GFCodeForm->ParsedFunc))
SetFunc(*(GFCodeForm->ParsedFunc));
GFCodeForm->Free();
}
А теперь по русски. Есть компонент - задача. Функция то бишь. И она должна по мановению волжебной палочки уметь превращаться в текст и обратно. Definition - свойство - набор строк тестового описания.
> Skier © (26.08.02 13:15)
> > Кажется он вызывается
> Это очень интересное словечко...На ощупь идёшь что ли ?
Если убрать комментарии:// ShowMessage("TGlobFun::SetDefinition");
В описанных случаях сообщение не показывается. "Кажется" выражает сомнение. Уж не вызывает ли BCB этот метод, игнорируя собщение.
← →
Skier (2002-08-26 13:50) [14]>murza
Хотелось бы взглянуть на код конструктора TGlobFun...
И какой класс реально в Definition...
← →
murza (2002-08-26 13:56) [15]
> Skier © (26.08.02 13:50)
> Хотелось бы взглянуть на код конструктора TGlobFun...
> И какой класс реально в Definition...
__fastcall TGlobFun::TGlobFun(TComponent* Owner)
: TComponent(Owner),FFunc(FHANSEN,2)
{
//...skipped...
FDefinition = FuncToText(&FFunc);
}
//----------------------------------------
TStringList *FuncToText(GLOBFUNC *Func)
{
//...skipped...
TStringList *Result = new TStringList;
//...skipped...
return Result;
}
← →
MBo (2002-08-26 14:18) [16]пример на Delphi
unit AA;
interface
uses classes,graphics,controls,Sysutils,dialogs;
type
TA=class(TCustomControl)
private
FLines: TStrings;
FCounter:Integer;
procedure SetLines(const Value: TStrings);
public
constructor Create(AOwner:TComponent);override;
procedure Paint;override;
published
property Lines:TStrings read FLines write SetLines;
end;
procedure Register;
implementation
{ TA }
constructor TA.Create(AOwner: TComponent);
begin
inherited;
FLines:=TStringList.Create;
Width:=200;
Height:=200;
end;
procedure TA.Paint;
var i:integer;
begin
inherited;
Canvas.Brush.Style:=bsClear;
Canvas.TextOut(0,0,"SetLines has been called "+IntToStr(FCounter)+" times");
for i:=0 to FLines.Count-1 do
Canvas.TextOut(0,12+i*12,Flines[i]);
end;
procedure TA.SetLines(const Value: TStrings);
begin
FLines.Assign(Value);
Inc(FCounter);
ShowMessage("SetLines called");
Refresh;
end;
procedure Register;
begin
RegisterComponents("Samples",[TA]);
end;
end.
-------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
A1.Lines:=Memo1.Lines;//setlines вызывается
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
A1.Lines.Assign(Memo2.Lines);//не вызывается, сразу идет TStrings.Assign
A1.Refresh;
end;
← →
murza (2002-08-26 14:33) [17]
> MBo © (26.08.02 14:18)
> A1.Lines:=Memo1.Lines;//setlines вызывается
понятно что вызывается
> A1.Lines.Assign(Memo2.Lines);//не вызывается
я думал что в таких ситуациях (неконстантный метод) сначала свойство читается, а потом записывается
А вообще надо вопрос надо было прочитать.
← →
Набережных С. (2002-08-26 16:07) [18]
> murza (26.08.02 12:21)
Исполнение конструкции MyComponent1->Definition->Text = "String1\nString2";
можно представить так:
var
St:TStrings;
St:=MyComponent1.FDefinition;
St.Text:="String1\nString2";
Теперь понятно?
← →
murza (2002-08-27 10:10) [19]Может быть и так.
Хотя я думал что иначе:
St:=MyComponent1.FDefinition;
St.Text:="String1\nString2";
MyComponent1.SetDefinition(St);
Потому что метод записи свойства Text неконстантный (не знаю есть ли такая терминология у дельфистов). Лень проверять. Но почему же они из DFM не считываются?
← →
Набережных С. (2002-08-27 15:36) [20]
> murza (27.08.02 10:10)
> Хотя я думал что иначе
Разумеется, нет. Получив указатель на объект(FDefinition), компилятор непосредственно вызывает его метод. После St:=MyComponent1.FDefinition и St, и MyComponent1.FDefinition указывают на один и тот-же объект и, соответственно, MyComponent1.SetDefinition(St) теряет всякий смысл.
То-же самое происходит и с DFM. Только в этом случае вызывается метод DefineProperties объекта, на который указывает FDefinition. Похоже, ты путаешь понятия объекта и указателя на него(а может, мне только так кажется:)). FDefinition содержит указатель на объект. И St после присвоения будет содержать тот-же указатель. Поройся в архивах этого форума - вопросы на подобные темы появляются здесь с удручающей регулярностью.
← →
murza (2002-08-28 12:10) [21]
> Набережных С. (27.08.02 15:36)
> Разумеется, нет. Получив указатель на объект(FDefinition),
> компилятор непосредственно вызывает его метод. После St:=MyComponent1.FDefinition
> и St, и MyComponent1.FDefinition указывают на один и тот-же
> объект и, соответственно, MyComponent1.SetDefinition(St)
> теряет всякий смысл.
>
Получается что мы можем написать delete Memo1->Lines; Печально...
> То-же самое происходит и с DFM. Только в этом случае вызывается
> метод DefineProperties объекта, на который указывает FDefinition.
> Похоже, ты путаешь понятия объекта и указателя на него(а
> может, мне только так кажется:)). FDefinition содержит указатель
> на объект. И St после присвоения будет содержать тот-же
> указатель. Поройся в архивах этого форума - вопросы на подобные
> темы появляются здесь с удручающей регулярностью.
Я ничего не понямаю. Причем здесь метод чтения? Разве при чтении из DFM не должен использоватся метод SetDefinition?
Мне это действительно нужно, так как изменения во время design-time не сохраняются (точнее, сохраняются, но не загружаются), а копирование - вставка игнорируется уже сделанные изменения.
← →
Набережных С. (2002-08-28 16:45) [22]Думаю, лучше всего поступить так. Погоняй под отладчиком вот этот пример:
TMyComponent = class(TComponent)
private
FDefinition: TStrings;
procedure SetDefinition(const Value: TStrings);
public
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
published
property Definition: TStrings read FDefinition write SetDefinition;
end;
constructor TMyComponent.Create(AOwner: TComponent);
begin
inherited;
FDefinition:=TStringList.Create;//или чего там у тебя
end;
destructor TMyComponent.Destroy;
begin
FDefinition.Free;
inherited;
end;
procedure TMyComponent.SetDefinition(const Value: TStrings);
begin
FDefinition.Assign(Value);
end;
var
MyComponent1: TMyComponent;
const
ComponentFile = "MyComponent.aaa";
procedure TForm1.Button1Click(Sender: TObject);
var
FS:TStream;
begin
if MyComponent1 = nil then MyComponent1:=TMyComponent.Create(Self);
// MyComponent1.Definition.Text:="Aaa"#13#10"Bbb";
MyComponent1.Definition:=Memo1.Lines;
FS:=TFileStream.Create(ComponentFile,fmCreate);
try
FS.WriteComponent(MyComponent1);
finally
FS.Free;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
FS:TStream;
begin
if MyComponent1 = nil then MyComponent1:=TMyComponent.Create(Self);
MyComponent1.Definition.Text:="";
Memo1.Lines.Text:="";
FS:=TFileStream.Create(ComponentFile,fmOpenRead);
try
FS.ReadComponent(MyComponent1);
Memo1.Lines.Assign(MyComponent1.Definition);
finally
FS.Free;
end;
end;
После этого, думаю, тебе все станет ясно.
P.S. На си уж сам переведи - все-таки здесь дельфийский форум :))
← →
murza (2002-08-29 11:13) [23]Большое спасибо, конечно, но я хочу сделать компонент и поставлять его пользователю, причем:
- компонент должен быть редактируемым в design-time и изменения должны сохраняться и учитываться в run-time
- компонент должен уметь копироваться-вставляться через буфер обмена.
Как ни странно это звучит, для сохранения всей информации об объекте я выбрал TStrings, в виду соображений: у других компонентов типа TMemo он стремируется, значит и у меня он будет стремироваться, и к тому мне нужен был экспорт/импорт в текст.
Теперь я все больше склоняюсь к мысли, что для того чтобы заставить строки стремироваться необходимо либо внутри использовать экземпляры другого типа, имеющего связь компонентом (наподобие TMemoStrings) либо перегрузить какой-либо из методов, унаследованных от TPersistent (насколько я понимаю, именно этот класс связан со стремированием).
Подскажите, прав ли я, и вкаком направлении мне лучше действовать.
Спасибо.
← →
Набережных С. (2002-08-29 14:56) [24]Извини, не понимаю твоей проблемы. Тот "компонент", который я привел в примере прелестно будет редактироваться в дизайне, и сохраняться в DFM, и загружаться оттуда. Если же тебе надо вмешаться в процесс выгрузки-загрузки, то нужно перекрыть метод DefineProperties у компонента, либо объявить потомка TStrinList и перекрыть у него.
Ты все-же поисследуй мой пример, включив отладочные DCU, заберись поглубже в исходники, НЕ ПОЖАЛЕЙ ВРЕМЕНИ, тогда и разберешься со всей этой "механикой".
← →
murza (2002-08-30 11:47) [25]Да я добился правильного заполнения поля FDefinition.
Вот только метод SetDefinition не вызывается.
Вот вам код:
class PACKAGE TMyComponent : public TComponent {
private:
protected:
TStrings *FDefinition;
void __fastcall SetDefinition(TStrings *Value);
public:
__fastcall TMyComponent(TComponent* Owner);
__fastcall ~TMyComponent();
virtual void __fastcall Assign(TPersistent* Source);
TMyComponent& operator=(TPersistent &Source);
__published:
__property TStrings * Definition = {read = FDefinition, write = SetDefinition};
};
//-------------------------------------------------------------
__fastcall TMyComponent::TMyComponent(TComponent* Owner) : TComponent(Owner) {
ShowMessage("TMyComponent::TMyComponent called");
FDefinition = new TStringList;
}
//---------------------------------------------------------------------------
__fastcall TMyComponent::~TMyComponent() {
ShowMessage("TMyComponent::~TMyComponent called");
delete FDefinition;
}
//---------------------------------------------------------------------------
void __fastcall TMyComponent::SetDefinition(TStrings *Value) {
ShowMessage("TMyComponent::SetDefinition called");
FDefinition->Assign(Value);
}
//---------------------------------------------------------------------------
void __fastcall TMyComponent::Assign(TPersistent* Source) {
ShowMessage("TMyComponent::Assign called");
try {
TMyComponent* MyComponent;
if ((MyComponent = dynamic_cast<TMyComponent*> (Source) ) != 0)
SetDefinition(MyComponent->FDefinition);
}
catch(...) {
ShowMessage("Error dynamic casting");
}
}
//---------------------------------------------------------------------------
TMyComponent& TMyComponent::operator=(TPersistent &Source) {
ShowMessage("TGlobFun::operator= called");
Assign(&Source);
return *this;
}
Ни оператор копирования, ни метод Assign, ни SetDefinition не вызываются.
ВОПРОС: Как мне лучше всего сделать так, чтоб при считывании из DFM мне можно было отловить заполнение свойства. Я же не могу делать это в конструкторе, который вызывается раньше.
← →
Набережных С. (2002-08-30 15:22) [26]Ответ:
unit Component1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TMyComponent = class(TComponent)
private
FDefinition: TStrings;
procedure SetDefinition(const Value: TStrings);
procedure Loaded;override;
public
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
procedure Assign(Source: TPersistent);override;
published
property Definition: TStrings read FDefinition write SetDefinition;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents("NSN Controls", [TMyComponent]);
end;
type
TMyStrings = class(TStringList)
protected
procedure DefineProperties(Filer: TFiler); override;
end;
{ TMyComponent }
procedure TMyComponent.Assign(Source: TPersistent);
begin
FDefinition.Assign((Source as TMyComponent).FDefinition);
inherited;
end;
constructor TMyComponent.Create(AOwner: TComponent);
begin
inherited;
FDefinition:=TMyStrings.Create;//или чего там у тебя
end;
destructor TMyComponent.Destroy;
begin
FDefinition.Free;
inherited;
end;
procedure TMyComponent.Loaded;
begin
//Здесь все свойства уже считаны из DFM
ShowMessage("Loaded!");
inherited;
end;
procedure TMyComponent.SetDefinition(const Value: TStrings);
begin
FDefinition.Assign(Value);
end;
{ TMyStrings }
procedure TMyStrings.DefineProperties(Filer: TFiler);
begin
if Filer is TWriter then ShowMessage("Me write!")
else ShowMessage("Me load!");{Filer is TReader}
inherited;//<-Здесь и происходит считывание и запись из/в DFM
end;
end.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.09.12;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.008 c