Форум: "Основная";
Текущий архив: 2002.12.23;
Скачать: [xml.tar.bz2];
ВнизКак получить ВСЕ Caption ы контролов на форме? Найти похожие ветки
← →
BlackTiger (2002-12-10 20:41) [0]Как получить ВСЕ Caption"ы контролов на форме?
Мне необходимо сохранить их в файле в виде
<имя контрола>=<его caption>
А потом загрузить все обратно.
Типа многоязычность получается.
← →
asmith (2002-12-10 21:06) [1]for nIndex := 0 to myForm.ControlCount - 1 do
SaveToFile(myForm.Controls[nIndex].Caption);
← →
Юрий Зотов (2002-12-10 22:49) [2]> asmith (10.12.02 21:06)
Сами пробовали?
1. Свойство TControl.Caption - protected. Поэтому код даже не скомпилируется.
2. Контрол может лежать не на форме, а, например, на панели. Тогда в список myForm.Controls он не попадает.
Тут надо немного иначе.
type
TFriendControl = class(TControl);
...
for i := 0 to ComponentCount - 1 do
if Components[i] is TControl then
with TFriendControl(Components[i]) do
if Caption <> "" then ...
← →
Kibitzer (2002-12-10 23:00) [3]
> Юрий Зотов © (10.12.02 22:49)
> Тут надо немного иначе.
Где:
TFriendControl = class(TControl)
public
property Caption;
end;
;)
← →
MBo (2002-12-10 23:05) [4]>Kibitzer
Не нужно. protected члены класса, объявленного в том же модуле, доступны и так.
← →
Kibitzer (2002-12-10 23:23) [5]
> MBo © (10.12.02 23:05)
> >Kibitzer
> Не нужно. protected члены класса, объявленного в том же
> модуле, доступны и так.
И правда. :))
Не думал, что так тоже считается :-/
← →
Юрий Зотов (2002-12-10 23:38) [6]> Kibitzer
:о)
← →
BlackTiger (2002-12-11 17:11) [7]Спасибо, конечно, но наличие Caption у контрола совсем не обязательно, а использовать try - довольно убогое решение.
Я нашел код, который проверяет наличие какого либо свойства (проверял только для Caption) в библиотеке IniLang.
Если кому надо, то вот он
function HasProperty(comp:TComponent;prop:String):boolean;
begin
result:=(getPropInfo(comp.classInfo,prop)<>nil) and comp.name<>"");
end;
Используется так
if HasProperty(Button1, "Caption") then begin
// ...
end;
Правда для TNT-компонентов приходится извращаться и определять класс компонента более точно.
var
ws: WideString;
wsl: TWideStringList;
begin
wsl := TWideStringList.Create(nil);
//...
if HasProperty(Self.Controls[i], "Caption") then begin
if Self.FindComponent(Self.Controls[i].Name) is TTntButton then
begin
with TTntButton(Self.FindComponent(Self.Controls[i].Name)) do
begin
wsl.Add(Self.Controls[i].Name+"="+Caption);
end;
end;
end;
//...
wsl.SaveUnicode := true;
wsl.SaveToFile("Captions.txt")
wsl.Free;
"is TComponent" использовать нельзя, т.к. тогда Caption читается как string, а не как WideString, и все unicode летит нафиг.
Может можно по-оптимальней? А то необходимо описывать каждый класс контролов отдельно, а класса типа TTntControl я вроде не нашел.
← →
Бурундук (2002-12-11 18:24) [8]>Self.FindComponent(Self.Controls[i].Name)
Ну ты и загнул... Я б так не смог.
По сути:
Используй RTTI
var CompCaption: string;
if Has...
CompCaption := GetPropValue(Controls[i], "Caption") // - получение заголовка в виде AnsiString не зависимо от типа.
Это сработает, даже если у какой-нибудь кнопки св-во Caption имеет тип Integer :)))
← →
BlackTiger (2002-12-11 18:51) [9]То, что загнул - полностью огласен :-)
НО (!!!) прикол в том, что не могу достучаться до Caption у TMenuItem (TTntMenuItem). В списке Self.Controls[] они отсутствуют, при этом Self.ComponentCount указывает на количество компонент большее, чем можно адресовать в Self.Components[].
Ну и как получить/установить надписи на элементах меню по имени компонента?
← →
Бурундук (2002-12-11 19:03) [10]Так ведь TMenuItem - потомок TComponent, а не TControl,
и естественно, что его в Controls[] нет.
Зато он есть в Components[].
>Self.ComponentCount указывает на количество компонент большее, >чем можно адресовать в Self.Components[].
А вот это я не врубился.
Если тебе нужны TMenuItemы - то надо организовать
проход по всем компонентам (а не контролам):
for i := 0 to ComponentCount - 1 do
if GetPropInfo(Components[i], "Caption") <> nil then
ЧегоТоТам.Add(GetPropValue(Components[i], "Caption"));
PS Зачем ты везде Self таскаешь?
Это имеет смысл, только если у тебя код внутри with находится
(и не просто with, а with чего-то с такими же свойствами)
← →
Юрий Зотов (2002-12-11 19:10) [11]> наличие Caption у контрола совсем не обязательно
Неправда. Все контролы имеют свойство Caption, только не у всех оно опубликовано.
> Ну и как получить/установить надписи на элементах меню по
> имени компонента?
uses
TypInfo;
...
S := GetStrProp(Components[i], "Caption");
...
SetStrProp(Components[i], "Caption", "Закрыть");
← →
BlackTiger (2002-12-11 19:26) [12]:-)))
Совсем торможу уже... Пора отдыхать, отдыхать, отдыхать...
Я просто пытался найти TMenuItem в Controls[], а не в Components[].
И используя ComponentCount рыться в Controls[].
2Юрий Зотов:
GetStrProp результат какого типа возвращает? String (PChar, ShortString)?
Если да, то он мне не поможет, тк TNT-компоненты имеют Caption типа WideString и все данные потеряются, а в этом-то и вся фишка.
З.Ы.: Мое личное АААААААААААфигенное спасибо разработчикам TNT-компонентов!!!
← →
Бурундук (2002-12-11 19:38) [13]Привожу реализацию GetStrProp
function GetStrProp(Instance: TObject; PropInfo: PPropInfo): string;
begin
case PropInfo^.PropType^.Kind of
tkString: GetShortStrPropAsLongStr(Instance, PropInfo, Result);
tkLString: GetLongStrProp(Instance, PropInfo, Result);
tkWString: GetWideStrPropAsLongStr(Instance, PropInfo, Result);
// Автоматическое преобразование из WideString в AnsiString
else
Result := "";
end;
end;
Если же тебе надо получить именно WideString, то стандартных
доступов к WideString св-вам в RTTI я не вижу,
по крайней мере в D5.
Я полагаю, получить WideString через RTTI можно только
через функцию-Getter,
причём надо учитывать след. частные случаи:
1) старший байт адреса ф-и = $FE (если память мне не изменяет)- это не ф-я,
а смещение самого поля относительно начала объекта (-$FE, соотв)
2) -"- $FF: индекс виртуальной ф-и в VMT (тоже - $FF)
3) просто статический метод.
← →
Бурундук (2002-12-11 19:56) [14]Только наоборот: $FE - вирт. ф-я, $FF - поле.
И это справедливо для D5, для D6 проверь сам.
(И посмотри в typinfo - может, в D6 уже есть более
удобный доступ к WideString св-вам).
И если у тебя только один компонент с таким Caption"ом
и больше не предвидится -
то, может, проще явно привести и не извращаться.
← →
Бурундук (2002-12-11 20:29) [15]Ф-я доступа к WideString св-вам для D5:
type
PVMTAsArray = ^VMTAsArray;
VMTAsArray = array[0..$FFFF]of Pointer;
function GetWStrProp(Instance: TObject; const PropName: string): WideString;
var PGetCode: Pointer;
Getter: TWStrGet;
Field: Pointer;
HiByte: Byte;
begin
PGetCode := GetPropInfo(Instance, "W")^.GetProc;
HiByte := Cardinal(PGetCode) shr 24;
TMethod(Getter).Data := Instance;
if HiByte = $FF then
begin
Cardinal(Field) := Cardinal(PGetCode)and $FFFFFF + Cardinal(Instance);
Result := WideString(Field^);
end else
if HiByte = $FE then
begin
TMethod(Getter).Code :=
PVMTAsArray(Instance.ClassType)[(Cardinal(PGetCode) and $FFFFFF) div 4];
// не индекс, а смещение - я ошибся
Result := Getter();
end
else
begin
TMethod(Getter).Code := PGetCode;
Result := Getter();
end;
end;
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.12.23;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.008 c