Ответ 1
Обновление. Комментарий к этому ответу указывает способ отказа вашего кода. Порядок оценки bitmap.Handle
и bitmap.Canvas.Handle
имеет значение. Поскольку порядок оценки параметров undefined, ваша программа имеет поведение undefined. И это объясняет, почему программы x86 и x64 отличаются поведением.
Таким образом, вы можете решить проблему, назначив битмап-дескриптор и контекст устройства локальным переменным в соответствующем порядке, а затем передав их как аргументы GetDIBits
. Но я все же считаю, что код намного лучше избегать класса VCL TBitmap
и напрямую использовать вызовы GDI, как в приведенном ниже коде.
Я считаю, что ваша ошибка - передать обработчик bitmap и его обработчик холста. Вместо этого вы должны передать, например, контекст устройства, полученный вызовом CreateCompatibleDC(0)
. Или перейдите IconInfo.hbmColor
в GetDIBits
. Но не передавайте дескриптор TBitmap
и дескриптор его холста.
Я также не вижу никакой цели для созданного TBitmap
. Все, что вам нужно, это получить ширину и высоту IconInfo.hbmColor
. Вам не нужно создавать TBitmap
для этого.
Итак, если бы я был вами, я бы удалил TBitmap
и использовал CreateCompatibleDC(0)
для получения контекста устройства. Это должно значительно упростить код.
Вам также необходимо удалить растровые изображения, возвращенные вызовом, в GetIconInfo
, но я думаю, вы уже знаете это и удалили этот код из вопроса для простоты.
Откровенно говоря, объекты VCL просто мешают здесь. На самом деле гораздо проще напрямую вызвать функции GDI. Возможно, что-то вроде этого:
procedure Main;
var
res: Cardinal;
Bits: PRGBALine;
bitmap: Winapi.Windows.TBitmap;
DC: HDC;
buffer: TMyBitmapInfo;
BitmapInfo: TBitmapInfo absolute buffer;
BitsSize: Cardinal;
IconInfo: TIconInfo;
begin
if not GetIconInfo(LoadIcon(0, IDI_WINLOGO), IconInfo) then begin
Writeln('Error GetIconInfo: ', GetLastError);
Exit;
end;
try
if GetObject(IconInfo.hbmColor, SizeOf(bitmap), @bitmap) = 0 then begin
Writeln('Error GetObject');
Exit;
end;
BitsSize := BytesPerScanline(bitmap.bmWidth, 32, 32) * abs(bitmap.bmHeight);
Bits := AllocMem(BitsSize);
try
buffer := TMyBitmapInfo.Create(bitmap.bmWidth, abs(bitmap.bmHeight));
DC := CreateCompatibleDC(0);
res := GetDIBits(DC, IconInfo.hbmColor, 0, abs(bitmap.bmHeight), Bits, BitmapInfo,
DIB_RGB_COLORS);
DeleteDC(DC);
if res = 0 then begin
Writeln('Error GetDIBits: ', GetLastError);
Exit;
end;
Writeln('Succeed');
finally
FreeMem(Bits);
end;
finally
DeleteObject(IconInfo.hbmMask);
DeleteObject(IconInfo.hbmColor);
end;
end;