Рисование прозрачного TMetaFile на TCanvas в Delphi

Я хотел бы нарисовать прозрачный TMetaFile на холсте, который используется для печати водяных знаков.

Проблема в том, что функция AlphaBlend не распознает TMetaFile.Handle как источник, поскольку ожидает дескриптора холста.

Я создал 32-битное растровое изображение с прозрачностью, но рисование на нем заставит белый фон, поэтому на холсте вы можете увидеть прямоугольник с альфа-смешением. Как нарисовать прозрачный TMetaFile на экране / холсте принтера?

TMetaFile, безусловно, прозрачный, я тестировал его на простой веб-странице с помощью IE с нестандартным цветом фона. Исходный код:

procedure TPainter.DrawAlpha(ACanvas: TCanvas; ARect: TRect; AGraphic: TMetafile; AAlpha: Byte);
var
  bmp: TBitmap;
  bf: BLENDFUNCTION;
begin
  bmp := TBitmap.Create;
  try
    bmp.PixelFormat := pf32bit;
    bmp.SetSize(ARect.Right - ARect.Left, ARect.Bottom - ARect.Top);
    bmp.Transparent := True;
    bmp.Canvas.Brush.Color := clNone;
    bmp.Canvas.Brush.Style := bsClear;
    bmp.Canvas.FillRect(Rect(0, 0, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top));
    bmp.Canvas.StretchDraw(Rect(0, 0, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top), AGraphic);

    bf.BlendOp := AC_SRC_OVER;
    bf.BlendFlags := 0;
    bf.SourceConstantAlpha := 230;
    bf.AlphaFormat := 0;

    AlphaBlend(
      ACanvas.Handle,
      ARect.Left,
      ARect.Top,
      ARect.Right - ARect.Left,
      ARect.Bottom - ARect.Top,
      bmp.Canvas.Handle,
      0,
      0,
      ARect.Right - ARect.Left,
      ARect.Bottom - ARect.Top,
      bf
    );
  finally
    bmp.Free;
  end;
end;

person too    schedule 22.10.2010    source источник


Ответы (1)


Если вы посмотрите официальную документацию MSDN, вы получите следующее заявление: http://msdn.microsoft.com/en-us/library/dd183351(VS.85).aspx

Ошибка возникает (и функция возвращает FALSE), если контекст исходного устройства идентифицирует расширенный контекст устройства метафайла.

Мое первое предположение заключалось в том, что даже если MSDN говорит только о контексте исходного устройства, ваш код никогда не будет работать с AlphaBlend, который предназначен для работы между двумя растровыми изображениями.

Но после второго исследования в типах перечисления метафайлов есть специальный тип записи TEMRAlphaBlend. Так что все должно работать как положено.

Что вы используете для отображения своего метафайла? Нам понадобится код, который вы используете для отображения здесь метафайла.

Я советую сохранить ваш метафайл в файл emf, а затем использовать emfexplorer для проверки его контекста.

Мы разработали модуль с открытым исходным кодом, названный SynGdiPlus, для рисования метафайла с использованием GDI +, следовательно, со сглаживанием в чистом Delphi. Но мы еще не реализовали тип записи TEMRAlphaBlend. Если вам будет интересно иметь рисунок сглаживания в вашем приложении, я мог бы изучить его реализацию.

person A.Bouchez    schedule 22.10.2010
comment
Я не показываю этот метафайл, его просто нужно перерисовать на TCanvas, который представляет собой экран во время предварительного просмотра страницы и принтер во время печати изображения. Я использовал SynGdiPlus, но надеюсь, что есть стандартный способ WinApi рисовать WMF на холсте с учетом его прозрачности и с помощью Alpha. Все работает нормально, когда создается временное растровое изображение, но я не знаю, как сделать это растровое изображение прозрачным, чтобы AlphaBlend распознавал прозрачные области и не касался целевого холста в этих областях. - person too; 22.10.2010
comment
Хорошо, поэтому я предполагаю, что этот метафайл отображается стандартным методом Draw, поскольку TMetaFile наследуется от TGraphic. Он должен работать, как ожидалось. Вы тестировали с использованием TBitmap.Canvas вместо TMetaFile только для тестирования? - person A.Bouchez; 22.10.2010