Solusi Remy (jawaban yang diterima untuk pertanyaan tertaut) akan berfungsi dengan baik dalam kode 64-bit. Apakah ada alasan Anda memilih jawaban yang lebih hacky yang diposting Cosmin daripada jawaban Remy?
- personKen White  schedule04.03.2016
comment
Karena saya memiliki grafik dalam aliran, saya memerlukan kelas grafis untuk memuatnya dengan benar. Saya tidak dapat menggunakan trik dengan memuat file dan melihat kelas grafis mana yang digunakan... Saya tahu FindRegisteredPictureFileFormats adalah peretasan tetapi berfungsi dengan baik dalam 32bit. Tetapi jika saya bisa mendapatkan hasilnya melalui cara lain, tentu saja saya dapat mengadaptasi kode saya!
- personFrédéric SCHENCKEL  schedule05.03.2016
comment
Anda dapat memodifikasi kode Remy untuk memuat dari aliran alih-alih dari file dan menggunakan metode yang sama, tanpa menggunakan kode perakitan yang bukan lintas platform (dan itu mencakup Windows 32/64 bit).
- personKen White  schedule05.03.2016
comment
Dari mana Anda mendapatkan alirannya? Basis Data, Sumber Daya, ...?
- personSir Rufo  schedule05.03.2016
comment
Tahukah Anda format apa yang didukung? Atau apakah Anda menulis kode yang dicolokkan ke aplikasi host?
- personDavid Heffernan  schedule05.03.2016
comment
Wah, banyak sekali komentar yang berisik di sini. Jawaban Remy tampaknya mengatasi masalah XY yang dinyatakan dalam komentar yang dihapus.
- personFree Consulting  schedule05.03.2016
comment
Ya, aplikasi ini disusun oleh plugin sehingga format gambar yang tersedia dapat bervariasi dari aplikasi yang menulis streaming dan aplikasi yang menggunakannya. Saya harus memilih yang tersedia dari platform baca dan tidak perlu yang dari platform tulis. Tentu saja saya dapat mengubah perilaku ini tetapi ini berarti saya akan kehilangan sedikit fleksibilitas dan platform Win32 berperilaku berbeda dari Win64.
- personFrédéric SCHENCKEL  schedule05.03.2016
comment
@Ken, Sejauh yang saya tahu itu LoadFromFile yang memeriksa kelas yang tepat, LoadFromStream membutuhkan kelas yang tepat secara langsung atau apakah saya salah? Tentu saja kompatibilitas lintas platform juga akan baik-baik saja!!!
- personFrédéric SCHENCKEL  schedule05.03.2016
comment
Memodifikasi unit Graphics.pas juga bukan solusi yang paling menarik karena saya menggunakan paket, akan agak sulit membuat semua paket mengandalkan Graphics.pas yang saya modifikasi.
- personFrédéric SCHENCKEL  schedule05.03.2016
Saya yakin unit ini melakukan apa yang Anda cari. Saya sudah mengujinya pada Windows 32 bit dan 64 bit, dengan paket runtime dan tanpa. Saya belum mengujinya dengan alokasi memori top-down, tapi saya tidak yakin ada bug pemotongan pointer.
unit FindRegisteredPictureFileFormats;
{$POINTERMATH ON}
interface
uses Classes, Contnrs;
// Extracts the file extension + the description; Returns True if the hack was successful,
// False if unsuccesful.
function GetListOfRegisteredPictureFileFormats(List: TStrings): Boolean;
// This returns the list of TGraphicClass registered; True for successful hack, false
// for unsuccesful hach
function GetListOfRegisteredPictureTypes(List: TClassList): Boolean;
implementation
uses Graphics;
type
TRelativeCallOpcode = packed record
OpCode: Byte;
Offset: Integer;
end;
PRelativeCallOpcode = ^TRelativeCallOpcode;
TLongAbsoluteJumpOpcode = packed record
OpCode: array [0 .. 1] of Byte;
Destination: Cardinal;
end;
PLongAbsoluteJumpOpcode = ^TLongAbsoluteJumpOpcode;
TReturnTList = function: TList;
// Structure copied from Graphics unit.
PFileFormat = ^TFileFormat;
TFileFormat = record
GraphicClass: TGraphicClass;
Extension: string;
Description: string;
DescResID: Integer;
end;
function FindFirstRelativeCallOpcode(StartOffset: NativeUInt): NativeUInt;
var
Ram: ^Byte;
i: Integer;
PLongJump: PLongAbsoluteJumpOpcode;
begin
Ram := nil;
PLongJump := PLongAbsoluteJumpOpcode(@Ram[StartOffset]);
if (PLongJump^.OpCode[0] = $FF) and (PLongJump^.OpCode[1] = $25) then
{$IF Defined(WIN32)}
Result := FindFirstRelativeCallOpcode(PNativeUInt(PLongJump^.Destination)^)
{$ELSEIF Defined(Win64)}
Result := FindFirstRelativeCallOpcode(PNativeUInt(PLongJump^.Destination + StartOffset + SizeOf(PLongJump^))^)
{$ELSE}
{$MESSAGE Fatal 'Architecture not supported'}
{$ENDIF}
else
begin
for i := 0 to 64 do
if PRelativeCallOpcode(@Ram[StartOffset + i])^.OpCode = $E8 then
Exit(StartOffset + i + PRelativeCallOpcode(@Ram[StartOffset + i])
^.Offset + 5);
Result := 0;
end;
end;
procedure FindGetFileFormatsFunc(out ProcAddr: TReturnTList);
var
Offset_from_RegisterFileFormat: NativeUInt;
Offset_from_RegisterFileFormatRes: NativeUInt;
begin
Offset_from_RegisterFileFormat := FindFirstRelativeCallOpcode(NativeUInt(@TPicture.RegisterFileFormat));
Offset_from_RegisterFileFormatRes := FindFirstRelativeCallOpcode(NativeUInt(@TPicture.RegisterFileFormatRes));
if (Offset_from_RegisterFileFormat = Offset_from_RegisterFileFormatRes) then
ProcAddr := TReturnTList(Pointer(Offset_from_RegisterFileFormat))
else
ProcAddr := nil;
end;
function GetListOfRegisteredPictureFileFormats(List: TStrings): Boolean;
var
GetListProc: TReturnTList;
L: TList;
i: Integer;
begin
FindGetFileFormatsFunc(GetListProc);
if Assigned(GetListProc) then
begin
Result := True;
L := GetListProc;
for i := 0 to L.Count - 1 do
List.Add(PFileFormat(L[i])^.Extension + '=' + PFileFormat(L[i])
^.Description);
end
else
Result := False;
end;
function GetListOfRegisteredPictureTypes(List: TClassList): Boolean;
var
GetListProc: TReturnTList;
L: TList;
i: Integer;
begin
FindGetFileFormatsFunc(GetListProc);
if Assigned(GetListProc) then
begin
Result := True;
L := GetListProc;
for i := 0 to L.Count - 1 do
List.Add(PFileFormat(L[i])^.GraphicClass);
end
else
Result := False;
end;
end.
personDavid Heffernanschedule05.03.2016
comment
Terima kasih banyak ini berhasil!! Catatan: Pemeriksaan overflow dan debug Dcu perlu dinonaktifkan. Dengan debug Dcus yang diaktifkan, pengujian Offset_from_RegisterFileFormat = Offset_from_RegisterFileFormatRes menjadi salah.
- personFrédéric SCHENCKEL; 07.03.2016