Текущий архив: 2006.11.26;
Скачать: CL | DM;
Вниз
Разр-тка TDigitEdit = class(TCustomEdit), как побороть сво-воText Найти похожие ветки
← →
ru_efim (2006-04-04 12:10) [0]Здравствуйте. Разрабатываю свой компонент на базе TcustomEdit для ввода десятичных чисел.
TDigitEdit = class(TCustomEdit)
Возникла следующая проблема. У TcustomEdit есть свойство Text унаследованное от TControl. Надо закрыть доступ к этому свойству. Чтобы оно не отображалось в инспекторе объектов, как сделать понятно, я его просто не публикую. Но в теле программы ни что не мешает мне вставить оператор DigitEdit1.Text:= ‘1u2’ ;, вот этого и надо предотвратить. Например, если не публиковать в TDigitEdit свойство MaxLength(оно введено непосредственно в TcustomEdit), то DigitEdit1.MaxLength:= .. выполнить будет не возможно.
Или какой метод надо переопределить, чтобы перед изменением свойства Text проводилась проверка нового значения этого свойства, ну и естественно, если значение не прошло проверку, была возможность отменить изменения. Дайте совет, пожалуйста.
← →
MBo © (2006-04-04 12:48) [1]А какие особые свойства должен иметь твой компонент? Если позволять вводить только числа - достаточно к стилю добавить ES_NUMBER
← →
icWasya © (2006-04-04 16:18) [2]пиши так
property Text write SetText;
и в процедуре SetText делай нужные проверки» Юрий Зотов:» Свойства невиртуальны, поэтому при изменении своего свойства Text метод SetText не вызовется. Кроме того, он статический да еще и приватный, так что перекрыть его тоже не получится. SetTextBuf тоже невиртуальный, перекрыть его тоже не выйдет.
← →
ru_efim (2006-04-04 23:22) [3]Спасибо за советы. Добавить к стилю ES_NUMBER поробую, возможно позволит освободится от ряда проверок. Но этого к сожалению не достаточно. На счет того что
"property Text write SetText; и в процедуре SetText делай нужные проверки", так что-то не получается. Мы заменяем TControl.Text, своим свойством ни как не связанным с наследуемым. Т.е. при присваивании нашему свойству Text значения, TControl.Text остается без изменений в то время как наш компонент отображает именно TControl.Text. Метод TControl.SetText перегрузить тоже не получится т.к. это метод класса TControl, а в базовом классе его нет. Дак что же делать.
← →
icWasya © (2006-04-05 11:19) [4]ну остаётся посмотреть исходники
procedure TControl.SetText(const Value: TCaption);
begin
if GetText <> Value then SetTextBuf(PChar(Value));
end;
procedure TControl.SetTextBuf(Buffer: PChar);
begin
Perform(WM_SETTEXT, 0, Longint(Buffer));
Perform(CM_TEXTCHANGED, 0, 0);
end;
procedure TControl.DefaultHandler(var Message);
var
P: PChar;
begin
with TMessage(Message) do
case Msg of
WM_GETTEXT:
begin
if FText <> nil then P := FText else P := "";
Result := StrLen(StrLCopy(PChar(LParam), P, WParam - 1));
end;
WM_GETTEXTLENGTH:
if FText = nil then Result := 0 else Result := StrLen(FText);
WM_SETTEXT:
begin
P := StrNew(PChar(LParam));
StrDispose(FText);
FText := P;
SendDockNotification(Msg, WParam, LParam);
end;
end;
end;
и попытаться переопределить реакцию на WM_SETTEXT» Юрий Зотов:» Вот это уже другое дело, но есть и более простое решение - перекрыть Change.
← →
DimaBr (2006-04-05 11:45) [5]Создайте своё свойство Text
property Text: string read GetText;
function TDigitEdit.GetText:string;
begin
Result := inherited Text;
end;
оно будет только для чтения и присвоить ему не получится» Юрий Зотов:» TCustomEdit(MyEdit).Text := "Вова";
Что получится?
← →
Юрий Зотов © (2006-04-05 11:49) [6]Перекрыть Change - и весь вопрос. Например, тупо "в лоб":
» Юрий Зотов:» FOldText - поле компонента.
procedure TDigitEdit.Change;
var
OldPos: integer;
begin
OldPos := SelStart;
try
StrToInt64(Text);
FOldText := Text;
inherited
except
on E: EConvertError do
begin
Text := FOldText;
SelStart := OldPos - 1
end
else
raise
end
end;
← →
DimaBr (2006-04-05 20:02) [7]
> » TCustomEdit(MyEdit).Text := "Вова";
ну, конечно я Вас уважаю, но можно в потомке и CNCommand(var Message: TWMCommand); message CN_COMMAND;
переопределить и в Change вообще не попадём.
← →
Юрий Зотов © (2006-04-05 20:37) [8]> DimaBr (05.04.06 20:02) [7]
Можно. И это правильно. Значит, разработчик потомка и не хотел, чтобы код попадал в Change - на то он и разработчик потомка. Component writer, а не прикладной батонокидатель. Но он обязан это сделать так, что уж если код не попадает в Change, то он не должен попадать туда никогда, каким бы образом к компоненту ни обращались и к какому бы типу его ни приводили. Иначе он полный чайник, а никакой не component writer.
А прикладному батонокидателю ничто не мешает написать в своей программе приведения типа а-ляTCustomEdit(FindComponent(...)).Text := "Вова"
и при этом он в полном праве ожидать корректного поведения компонента. А компонент вдруг поведет себя некорректно - и бедняга будет долго ломать голову над неожиданным багом, а потом скажет пару теплых слов в адрес разработчика компонента, который сделал поведение свойства зависимым от того, каким образом происходит обращение к этому свойству.. Приводим к TDigitEdit - работает, приводим к TСustomEdit - не работает. Налицо нарушение основополагающего принципа ООП.
Подчеркнутое и есть суть. Такого быть не должно.
Страницы: 1 вся ветка
Текущий архив: 2006.11.26;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.028 c