Sabes 0 / 0 / 1 Регистрация: 05.02.2016 Сообщений: 33 |
||||
1 |
||||
24.06.2018, 00:26. Показов 13696. Ответов 12 Метки нет (Все метки)
Нужно чтобы при нажатии на кнопку создавался новый компонент Image, который находится правее предыдущего. И все работает без ошибок, но только если на форме отсутствует Label. Как только я добавлю Label в любое место, при создании компонента вылетает ошибка «invalid class typecast». При этом если на форме будет StaticText1, который подобен Label ошибка вылетать не будет.
Ошибка так же вылетает на компонент DbText, и на все IW-компоненты.
0 |
northener пофигист широкого профиля 4681 / 3117 / 857 Регистрация: 15.07.2013 Сообщений: 17,967 |
||||
24.06.2018, 01:55 |
2 |
|||
вылетает ошибка «invalid class typecast» Это сообщение выдаётся при использовании оператора as и только при его использовании!
не годится. Заведите свой список именно картинок.
При этом если на форме будет StaticText1, который подобен Label ошибка вылетать не будет. TStaticText не является наследником TControl и естественно в список Controls не включается.
1 |
0 / 0 / 1 Регистрация: 05.02.2016 Сообщений: 33 |
|
24.06.2018, 02:01 [ТС] |
3 |
northener, Спасибо, теперь я понял. Я смогу избежать ошибок если будут использовать Components, вместо Controls?
0 |
пофигист широкого профиля 4681 / 3117 / 857 Регистрация: 15.07.2013 Сообщений: 17,967 |
|
24.06.2018, 02:10 |
4 |
Нет, не сможете. Список Components ещё шире, чем список Controls. Вам нужно сделать свой список/массив, который будет хранить указатели только на ваши картинки.
0 |
0 / 0 / 1 Регистрация: 05.02.2016 Сообщений: 33 |
|
24.06.2018, 02:36 [ТС] |
5 |
northener, Не подскажите как сделать такой список/массив? Или литературу где это описано, потому что я к сожалению не знаю как это сделать.
0 |
пофигист широкого профиля 4681 / 3117 / 857 Регистрация: 15.07.2013 Сообщений: 17,967 |
|
24.06.2018, 02:50 |
6 |
Если до вечера воскресенья никто вам не даст пример кода, я его напишу. А литературы где это описано нет.
0 |
0 / 0 / 1 Регистрация: 05.02.2016 Сообщений: 33 |
|
24.06.2018, 03:12 [ТС] |
7 |
northener, Буду очень признателен за пример кода.
0 |
5243 / 4191 / 1038 Регистрация: 29.08.2013 Сообщений: 26,510 Записей в блоге: 3 |
|
24.06.2018, 08:26 |
8 |
Массив вы умеете добавлять?
0 |
krapotkin 5606 / 4380 / 1396 Регистрация: 14.04.2014 Сообщений: 19,579 Записей в блоге: 19 |
||||||||||||||||
24.06.2018, 09:31 |
9 |
|||||||||||||||
Delphi 2010+
OnCreate
OnDestroy
Добавление элемента
0 |
0 / 0 / 1 Регистрация: 05.02.2016 Сообщений: 33 |
|
25.06.2018, 03:47 [ТС] |
10 |
krapotkin, Работаю в Delphi 7 и вылетает ошибка на то что программа не знает TObjectList. Как я понял это потому что в Delphi 7 отсутствует Generics.Collections. Есть ли другой способ? Или придется скачивать новую версию?
0 |
Модератор 8590 / 5733 / 2306 Регистрация: 21.01.2014 Сообщений: 24,568 Записей в блоге: 3 |
|
25.06.2018, 04:33 |
11 |
Есть ли другой способ? Есть. И Вам про него уже сказали — динамический массив объектов типа TImage
придется скачивать новую версию? Как бы давно пора…
0 |
krapotkin 5606 / 4380 / 1396 Регистрация: 14.04.2014 Сообщений: 19,579 Записей в блоге: 19 |
||||
25.06.2018, 07:41 |
12 |
|||
Работаю в Delphi 7 еще раз внимательно прочел ваш вопрос. пытался найти что-то про Delphi 7
Delphi 2010+ для D7
0 |
Модератор 8590 / 5733 / 2306 Регистрация: 21.01.2014 Сообщений: 24,568 Записей в блоге: 3 |
|
25.06.2018, 08:16 |
13 |
Для семерки еще надо в uses добавить Contnrs
0 |
When I try to cast Array of Integer
to TArray<Integer>
in a procedure I get an error E2089 Invalid typecast
. How can I type cast it so that it will work?
program Project11;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Math;
type
TArrayManager<T> = record
class procedure Shuffle(var A: TArray<T>); static;
end;
class procedure TArrayManager<T>.Shuffle(var A: TArray<T>);
var
I, J: Integer;
Temp: T;
begin
for I := High(A) downto 1 do
begin
J := RandomRange(0, I);
Temp := A[I];
A[I] := A[J];
A[J] := Temp;
end;
end;
procedure Test(var A: Array of Integer);
begin
TArrayManager<Integer>.Shuffle(TArray<Integer>(A)); // Invalid typecast????
end;
var
A: Array of Integer;
begin
// TArrayManager<Integer>.Shuffle(TArray<Integer>(A)); // Works
Test(A);
end.
asked Jul 8, 2014 at 17:03
You cannot cast an open array parameter to a dynamic array. They are simply incompatible. If you wish to operate on a slice of the array, without copying, I’m afraid that you will need to pass the array and the indices separately. Like this:
procedure Foo(var A: TArray<Integer>; Index, Count: Integer);
begin
// operate on A[Index] to A[Index+Count-1]
end;
answered Jul 8, 2014 at 22:32
David HeffernanDavid Heffernan
602k42 gold badges1076 silver badges1491 bronze badges
0
The type «array of X» means something different as a parameter than as a variable. Here it’s an open array, which is actually something very different from a dynamic array.
If you want to pass around a dynamic array, you should make the param type TArray<integer>
.
answered Jul 8, 2014 at 17:14
Mason WheelerMason Wheeler
82.6k50 gold badges270 silver badges478 bronze badges
20
Your problem is in this part:
if (Components[I] as TImage).Name = 'imgd' + sID then
begin (Components[I] as TImage)
.Free;
end;
if (Components[I] as TLabel).Name = 'lbld' + sID then
begin (Components[I] as TLabel)
.Free;
end;
An as
cast in Delphi is basically an assertion cast: you’re saying that you’re sure it will be that type, and if it’s not, to raise an invalid cast exception. Right now, you’re asserting that every single component will be both a TImage
and a TLabel
, which obviously will never be true.
What you probably really want to do is this:
if (Components[I] is TImage) and (Components[I].Name = 'imgd' + sID) then
begin
Components[I].Free;
end;
if (Components[I] is TLabel) and (Components[I].Name = 'lbld' + sID) then
begin
Components[I].Free;
end;
You don’t actually need the casts in there, since Name
is a property on the TComponent
base class.
EDIT: A few points as noted by Andreas in the comments:
First, if you’re iterating over a collection and removing items from it, you need to work backwards. To illustrate why, let’s remove all even numbers from this list:
[1, 3, 5, 2, 4, 6]
So if we do something like this:
for i := 0 to list.Length - 1 do
begin
if list[i] mod 2 = 0 then
begin
list.Remove(i);
end;
end;
On the first three iteration, we find numbers that are not even. So far so good. But on #4, (i = 3), we have an even number. We remove it from the list. The list is now [1, 3, 5, 4, 6]
. Now we increment i
to 4. Element #4 in this new list is the 6; we’ve skipped the 4! This only works if you’re counting backwards, because then deleting things only rearranges the work you’ve already done, not the work you still have left to do.
Also, the Components
collection on the form will contain all of your components, in whatever order they were set up in the form designer. It’s not particularly likely that whatever image you called imgd1
will be component #1 in that collection. If you’re looking for any components of those types with a name starting with imgd
or lbld
followed by a number, you’ll probably want to write a custom name validation function that checks for that. But checking if the number is the same as I
is more or less useless as I
is completely arbitrary here.
|
|
|
Пожалуйста, выделяйте текст программы тегом [сode=pas] … [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как «свернуть» программу в трей.
3. Как «скрыться» от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
… (продолжение следует) …
Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.
Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка — 60 дней. Последующие попытки бан.
Мат в разделе — бан на три месяца…
Invalid typecast
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Member Рейтинг (т): 3 |
Вот есть некая процедура и один из её параметров это свой тип например: type TA1 = packed array[0..15] of byte; и я хочу вызвать эту процедуру но уже с использованием другого типа который по сути тот же самый, и получаю ошибку — Invalid typecast procedure proc(Value: Ta1); begin …….. end; … var ab: Tbytes; aab: array of byte; begin proc(ab); — Invalid typecast proc(aab); — Invalid typecast end; Понятное дело, что можно свести всё к одному типу, но на этот перебор будет уходить время, переписывать процедуры тоже плохой вариант, поэтому вопрос может как-то можно сделать то что я хочу с минимальной затратой ресурсов ? Сообщение отредактировано: Jiro — |
min@y™ |
|
Full Member Рейтинг (т): 10 |
переписать только функцию: procedure proc(const Value; const ASize: DWORD); var ptr: pbyte; begin ptr:= @Value; // далее — работа через ptr^ end; |
Filka |
|
Senior Member Рейтинг (т): 144 |
type PA1 = ^TA1; TA1 = packed array[0..15] of byte; … begin Proc(PA1(@ab[0])^); Proc(PA1(@aab[0])^); end; ? Сообщение отредактировано: Filka — |
MBo |
|
Параметр — открытый массив (Value: array of Byte) не подойдёт? P.S. Пример не соответствует фразе |
leo |
|
Jiro Другой вариант — передавать массив по указателю на первый элемент type pA1 = ^TA1; TA1 = packed array[0..15] of byte; procedure proc(Value: pA1); … proc(@ab[0]); //при таком вызове ab м.б. и статическим и динамическим |
Jiro |
|
Member Рейтинг (т): 3 |
Всем thx. |
ViktorXP |
|
а зачем? в процедуру передается строгий тип на 16 байт по ссылке, ты же хочешь впихнуть туда динамический тип. Компилятор в данном случае уже контролировать не сможет. в нутри функции тоже отследить динамический массив не получится (так как функция думает что это статический массив). и это приведет только к одному, к AV. но как вариант можно решить проблему за счет хелперов или операторов helper uses System.Math; type TBytesHelper = record helper for TBytes public function toTA1: TA1; end; { TBytesHelperHelper } function TBytesHelper.toTA1: TA1; begin FillChar(Result, sizeof(Result), 0); if Length(Self) > 0 then Move(Self[0], Result, Min(sizeof(Result), Length(Self))); end; //use proc(ab.toTA1); operator type TMyRecord = record private InternalArray: TBytes; public constructor Create(arr: TBytes); overload; constructor Create(Memory: PByte; Size: NativeInt); overload; class operator Implicit(Value: TMyRecord): TA1; end; { TMyRecord } constructor TMyRecord.Create(arr: TBytes); begin InternalArray := arr; end; constructor TMyRecord.Create(Memory: PByte; Size: NativeInt); begin SetLength(InternalArray, size); if Size > 0 then Move(Memory^, InternalArray[0], Size); end; class operator TMyRecord.Implicit(Value: TMyRecord): TA1; begin FillChar(Result, sizeof(Result), 0); if Length(Value.InternalArray) > 0 then Move(Value.InternalArray[0] ,Result, Min(sizeof(Result), Length(Value.InternalArray))); end; //use var Array1: TBytes; rc: TMyRecord; … Array1 := TBytes.Create(1,2,3,4,5,6,7,8,9,0); rc := TMyRecord.Create(Array1); proc(rc); //или попроще proc(TMyRecord.Create(TBytes.Create(1,2,3,4,5,6,7,8,9,0))); Сообщение отредактировано: ViktorXP — |
Fr0sT |
|
Цитата ViktorXP @ FillChar(Result, sizeof(Result), 0); Хм, с каких пор Result стал получать осмысленное значение до вызова функции? Добавлено Цитата Jiro @ и я хочу вызвать эту процедуру но уже с использованием другого типа который по сути тот же самый, и получаю ошибку — Invalid typecast Не тот же самый. Динамический массив и фиксированный массив — два физически очень разных типа. Если не имеешь возможности переделать модуль — да, только пиши конверторы из своего типа в используемый. Либо добавляй обертки типа function proc_mytype(A: Tbytes) begin proc(TBytesToTA1(A)); end; |
leo |
|
Цитата Fr0sT @ Хм, с каких пор Result стал получать осмысленное значение до вызова функции?
С незапамятных — для сложных типов Result передается как дополнительный var-параметр и соотв-но содержит то, что в нем было до вызова функции. |
Fr0sT |
|
leo, забавно, спасибо. Хотя это скорее хакофича, и рассчитывать на нее не стоит, к тому же это повергает в когнитивный диссонанс читающего код |
ViktorXP |
|
Цитата Fr0sT @ Хотя это скорее хакофича, и рассчитывать на нее не стоит, к тому же это повергает в когнитивный диссонанс читающего код
???? Result является полноценной переменной (параметром) и всегда таким был То что ты не использовал эту возможность (хотя я уверен что использовал. просто сам этого не знал или не задумывался об этом) не коем образом не делает ее «хаком». Добавлено Сообщение отредактировано: ViktorXP — |
^D^ima |
|
ViktorXP |
Fr0sT |
|
ViktorXP, покажи мне реально оправданный пример использования предыдущего значения Result. |
ViktorXP |
|
для начала (что бы я не быть голословным) загляним в Object Pascal Language Guide то есть функцию function MyFunc(): Integer; можно рассматривать как function MyFunc(): Integer; var Result: Integer absolute MyFunc;//так она не соберется но для наглядности сойдет также для наглядности мы можем рассмотреть эту функцию как процедуру с out параметром procedure MyFunc(out Result: Integer); поведения параметра result, с точки зрения паскаля, не будет ничем отличатся от поведения result функции. он также будет ругаться на забывчивость проинициализировать ее внутри процедуры и будет подчинятся всем другим «законам» языка. Предположу что тебя смущает ошибка «W1035 Return value of function ‘MyFunc’ might be undefined» при попытке считать значение из result (или выходя из функции) не проинициализировав ее перед этим. function MyFunc(): Integer; var I: Integer; begin if Result = 1 then // W1035 Return value of function ‘MyFunc’ might be undefined Exit(10); if I = 1 then // W1036 Variable ‘I’ might not have been initialized Exit(1); end;
Это связано с тем что сам «компилятор» не чистит стек для локальных переменных и результата. и там может находится все что угодно (мусор от предыдущих функций/процедур) function MyFunc(): string; begin if Result = » then // никакой ошибки не будет Exit(’empty’); end; В чем же есть оправдания использовать result сразу, без использования дополнительной переменной? function MyFunc(): Integer; var Ret: Integer; begin Ret := 0; … Result := ret; end; Подобный код появляется в двух случаях: человек раньше писал на с/с++ и он привык что результат нужно присваивать в конце; человек не знает о поведения result в паскале. type TMyChars = array[0..9] of char; function MyFunc(): TMyChars; var LocalParam: TMyChars; begin LocalParam := ‘0123456789’; Result := LocalParam; end; пс. я надеюсь что свою мысль я донес максимально доступно. Сообщение отредактировано: ViktorXP — |
Fr0sT |
|
ViktorXP, спасибо и уважуха за развернутый ответ, но ты меня не понял. По большей части это все азбука и мне, разумеется, известно. Возражения у меня вызвала вот эта конструкция function TBytesHelper.toTA1: TA1; begin FillChar(Result, sizeof(Result), 0); if Length(Self) > 0 then Move(Self[0], Result, Min(sizeof(Result), Length(Self))); end; т.к. в переопределенные типы я не вникал, то решил, что Result — это динамический массив, длину которого ты с какого-то перепугу используешь. Сейчас посмотрел — TA1 — статический массив, для него все верно. Т.ч. вопрос исчерпан. Хотя вот leo понял причину моего недоумения |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Delphi: Общие вопросы
- Следующая тема
[ Script execution time: 0,0483 ] [ 16 queries used ] [ Generated: 21.09.23, 09:55 GMT ]
Go Up to Error and Warning Messages (Delphi)
This error message is issued for type casts not allowed by the rules. The following kinds of casts are allowed:
— Ordinal or pointer type to another ordinal or pointer type
— A character, string, array of character or pchar to a string
— An ordinal, real, string or variant to a variant
— A variant to an ordinal, real, string or variant
— A variable reference to any type of the same size.
Note that casting real types to integer can be performed with the standard functions Trunc and Round.
There are other transfer functions like Ord and Chr that might make your intention clearer.
program Produce; begin Writeln( Integer(Pi) ); end.
This programmer thought he could cast a floating point constant to Integer, like in C.
program Solve; begin Writeln( Trunc(Pi) ); end.
In the Delphi language, we have separate Transfer functions to convert floating point values to integer.