у меня есть пример потомка TBitmap
:
TMyBitmap = class(TBitmap)
public
constructor Create; override;
end;
constructor TMyBitmap.Create;
begin
inherited;
Beep;
end;
Во время выполнения я создаю один из этих TMyBitmap
объектов, загружаю в него изображение и помещаю его в TImage
формы:
procedure TForm1.Button1Click(Sender: TObject);
var
g1: TGraphic;
begin
g1 := TMyBitmap.Create;
g1.LoadFromFile('C:\...\example.bmp');
Image1.Picture.Graphic := g1;
end;
Внутри TPicture.SetGraphic
вы можете видеть, что он делает копию изображения, создавая новый и вызывая .Assign
на только что созданном клоне:
procedure TPicture.SetGraphic(Value: TGraphic);
var
NewGraphic: TGraphic;
begin
...
NewGraphic := TGraphicClass(Value.ClassType).Create;
NewGraphic.Assign(Value);
...
end;
Строка, в которой строится новый графический класс:
NewGraphic := TGraphicClass(Value.ClassType).Create;
правильно вызывает мой конструктор, и все хорошо.
я хочу сделать что-то подобное, я хочу клонировать TGraphic
:
procedure TForm1.Button1Click(Sender: TObject);
var
g1: TGraphic;
g2: TGraphic;
begin
g1 := TMyBitmap.Create;
g1.LoadFromFile('C:\...\example.bmp');
//Image1.Picture.Graphic := g1;
g2 := TGraphicClass(g1.ClassType).Create;
end;
За исключением того, что он никогда не вызывает мой конструктор и не вызывает конструктор TBitmap
. Он вызывает только TObject
конструктор. После строительства:
g2.ClassName: 'TMyBitmap'
g2.ClassType: TMyBitmap
Тип правильный, но он не вызывает мой конструктор, но вызывает идентичный код в другом месте.
Почему?
Даже в этом гипотетическом надуманном примере это все еще проблема, потому что конструктор TBitmap
не вызывается; переменные внутреннего состояния не инициализируются допустимыми значениями:
constructor TBitmap.Create;
begin
inherited Create;
FTransparentColor := clDefault;
FImage := TBitmapImage.Create;
FImage.Reference;
if DDBsOnly then HandleType := bmDDB;
end;
Версия в TPicture:
NewGraphic := TGraphicClass(Value.ClassType).Create;
декомпилируется в:
mov eax,[ebp-$08]
call TObject.ClassType
mov dl,$01
call dword ptr [eax+$0c]
mov [ebp-$0c],eax
Моя версия:
g2 := TGraphicClass(g1.ClassType).Create;
декомпилируется в:
mov eax,ebx
call TObject.ClassType
mov dl,$01
call TObject.Create
mov ebx,eax
Обновить один
Вынесение "клонирования" в отдельную функцию:
function CloneGraphic(Value: TGraphic): TGraphic;
var
NewGraphic: TGraphic;
begin
NewGraphic := TGraphicClass(Value.ClassType).Create;
Result := NewGraphic;
end;
не помогает.
Обновление два
Ясно, что я четко предоставляю четкий снимок экрана с моим четким кодом, который ясно показывает, что мой четкий код явно представляет собой все, что есть. Четко:
Обновление три
Вот однозначная версия с OutputDebugString
s:
{ TMyGraphic }
constructor TMyBitmap.Create;
begin
inherited Create;
OutputDebugStringA('Inside TMyBitmap.Create');
end;
function CloneGraphic(Value: TGraphic): TGraphic;
var
NewGraphic: TGraphic;
begin
NewGraphic := TGraphicClass(Value.ClassType).Create;
Result := NewGraphic;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
g1: TGraphic;
g2: TGraphic;
begin
OutputDebugString('Creating g1');
g1 := TMyBitmap.Create;
g1.LoadFromFile('C:\Archive\-=Images=-\ChessvDanCheckmateIn38.bmp');
OutputDebugString(PChar('g1.ClassName: '+g1.ClassName));
OutputDebugStringA('Assigning g1 to Image.Picture.Graphic');
Image1.Picture.Graphic := g1;
OutputDebugString('Creating g2');
g2 := Graphics.TGraphicClass(g1.ClassType).Create;
OutputDebugString(PChar('g2.ClassName: '+g2.ClassName));
OutputDebugString(PChar('Cloning g1 into g2'));
g2 := CloneGraphic(g1);
OutputDebugString(PChar('g2.ClassName: '+g2.ClassName));
end;
И необработанные результаты:
ODS: Creating g1 Process Project2.exe ($1138)
ODS: Inside TMyBitmap.Create Process Project2.exe ($1138)
ODS: g1.ClassName: TMyBitmap Process Project2.exe ($1138)
ODS: Assigning g1 to Image.Picture.Graphic Process Project2.exe ($1138)
ODS: Inside TMyBitmap.Create Process Project2.exe ($1138)
ODS: Creating g2 Process Project2.exe ($1138)
ODS: g2.ClassName: TMyBitmap Process Project2.exe ($1138)
ODS: Cloning g1 into g2 Process Project2.exe ($1138)
ODS: g2.ClassName: TMyBitmap Process Project2.exe ($1138)
ODS: g1.ClassName: TMyBitmap Process Project2.exe ($1138)
И отформатированные результаты:
Creating g1
Inside TMyBitmap.Create
g1.ClassName: TMyBitmap
Assigning g1 to Image.Picture.Graphic
Inside TMyBitmap.Create
Creating g2
g2.ClassName: TMyBitmap
Cloning g1 into g2
g2.ClassName: TMyBitmap
g1.ClassName: TMyBitmap
Обновление четыре
Я попытался отключить все параметры компилятора, которые мог:
Примечание. Не выключайте Extended syntax
. Без него вы не можете присвоить Result
функции (Необъявленный идентификатор Результат).
Обновление пять
Следуя предложению @David, я попытался скомпилировать код на некоторых других машинах (все Delphi 5):
- Иэн Бойд (я): Неудачно (Windows 7 64-бит)
- Dale: Fails (Windows 7 64-бит)
- Дэйв: Неудачно (Windows 7 64-бит)
- Крис: Неудачно (Windows 7 64-бит)
- Джейми: Неудачно (Windows 7 64-бит)
- Джей: Неудачно (Windows XP 32-бит)
- Сервер сборки клиента: сбой (32-разрядная версия Windows 7)
g1.ClassType
все ещеTMyBitmap
прямо перед последней строкой моего обработчика событий. - person Ian Boyd   schedule 17.03.2011