[Winapi] Wyświetlanie PNG na pulpicie

0

Witam,

mam problem z wyświetleniem obrazka w formacie PNG na pulpicie,
obrazek wyświetla się na wpół przezroczysty i nie mam pojęcia jak to naprawić,

po oknie rysuje w taki sposób:

procedure DrawLayered(Window:THandle);
var
  s   : string;
  tf  : textfile;
  i   : integer;
var
    blend:BLENDFUNCTION;
    P:TPoint;
    Ss:TSize;
    X,Y:integer;
    RGBAPixel:PRGBQuad;
    RGBPixel:PRGBTriple;
    APixel:PByte;
begin
  RGBA := CreateBitmap(250, 250, pf32bit);
  Rgbb := CreateBitmap(250, 250, pf24bit);
  A := CreateBitmap(250, 250, pf8bit);

  try
    png := tpngobject.Create;
    png.LoadFromFile('C:\1.png');
    png.CreateAlpha;

    a.Canvas.Brush.Color := clblack;
    a.Canvas.Rectangle(0,0,a.Height,a.width);

    rgbb.Canvas.Draw(0,0,png);
    a.Canvas.Draw(0,0,png);

    for Y := RGBA.Height-1 downto 0 do
      begin
        RGBAPixel:=RGBA.ScanLine[y];
        RGBPixel:=RGBb.ScanLine[y];
        APixel:=A.ScanLine[y];

        for X := 0 to RGBA.Width-1 do
          begin
            RGBAPixel.rgbReserved := APixel^;
            RGBAPixel.rgbRed := MulDiv(RGBPixel.rgbtRed, APixel^, 255);
            RGBAPixel.rgbGreen := MulDiv(RGBPixel.rgbtGreen, APixel^, 255);
            RGBAPixel.rgbBlue := MulDiv(RGBPixel.rgbtBlue, APixel^, 255);
            inc(RGBAPixel);
            inc(RGBPixel);
            inc(APixel);
          end;
      end;

  P.X := 0;
  P.Y := 0;
  Ss.cx := RGBA.Width;
  Ss.cy := RGBA.Height;
  blend.BlendOp := AC_SRC_OVER;
  blend.BlendFlags := 0;
  blend.AlphaFormat := AC_SRC_ALPHA;
  blend.SourceConstantAlpha := 255;
  UpdateLayeredWindow(Window, GetDC(0), nil, @Ss, rgba.Canvas.handle, @P, 0, @blend, ULW_ALPHA);
finally
  RGBA.Free;
  RGBb.Free;
  A.Free;
  end;
end;

tworzenie okna:

  Window:=CreateWindowEx(WS_EX_TOOLWINDOW or WS_EX_LAYERED, 'Aa',
  'Aa',WS_VISIBLE, 500, 20, 250, 250, GetDesktopListViewHandle, 0, hInstance, nil);

  SetWindowPos(Window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE);
  SetParent(Window, GetDesktopListViewHandle);
  DrawLayered(Window);

z rysowaniem po canvasie nie ma problemu, dopiero przy obrazie pojawia się problem.

Pomocy. 2 dzień się nad tym głowię.

0

Zapomniałem dodać

Przykładowy plik *.PNG:
http://img19.imageshack.us/i/99916180.png/

0

Marcov jak mozesz oczekiwac, ze ktos Ci pomoze skoro sam nie wlozysz odrobiny wysilku w przygotowanie nalezytego posta? W przykladzie brakuje definicji funkcji oraz zmiennych, kod jest niekompilowalny. Zadbaj o to nastepnym razem.

Kwestia Twojego problemu lezy w pobieraniu Alphy nie z tego miejsca co trzeba.

Pozdrawiam.

0

w takim razie poprawię się :)

funkcja Createbitmap:

function CreateBitmap(Width:integer; Height:integer; PixelFormat:TPixelFormat):TBitmap;
begin
result:=TBitmap.Create;
result.Width:=Width;
result.Height:=Height;
result.PixelFormat:=PixelFormat;
end;

funkcja GetDesktopListViewHandle:

function GetDesktopListViewHandle: THandle; stdcall;
var
  S: String;
begin
  Result := FindWindow('ProgMan', nil);
  Result := GetWindow(Result, GW_CHILD);
  Result := GetWindow(Result, GW_CHILD);
  SetLength(S, 40);
  GetClassName(Result, PChar(S), 39);
  if PChar(S) <> 'SysListView32' then
    exit;
end;

i brakujące zmienne:

RGBA,RGBb,A : TBitmap;
png : tpngobject;

Korzystam z komponentu TPNGImage.

Mam nadzieję, że teraz wszystko jest w porządku.

Wodzu: mógłbyś trochę rozwinąć ? Nie do końca rozumiem jak to zrobić.

0

No juz prawie :)

Ale zabraklo Ci jeszcze RegisterClass i WndMessageProc ;)

Chodzi o to ze do pobrania Alphy powinienes uzyc png.AlphaScanline. Samo TPNGObject tez ma metode ScanLine wiec te "posrednie" bitmapy sa zbedne. MulDiv tez nie musisz juz stosowac ani uzywac png.CreateAlpha.

0

kurde, czyli mam zostawić tylko bitmapę RGBA i zamienić kod na taki:

    for Y := RGBA.Height-1 downto 0 do
      begin
        RGBAPixel:=RGBA.ScanLine[y];
        RGBPixel:=RGBb.ScanLine[y];
        APixel:=A.ScanLine[y];
          for X := 0 to RGBA.Width-1 do

?

Czy w UpdateLayeredWindow podać uchwyt do canvasa PNG ?

0

oups, mialem na mysli taki:

    for Y := RGBA.Height-1 downto 0 do
      begin
        RGBAPixel:=PNG.ScanLine[y];
        RGBPixel:=PNG.ScanLine[y];
        APixel:=PNG.ScanLine[y];
          for X := 0 to RGBA.Width-1 do
              ...

przypadkiem nacisnąłem tab i enter ;)

0

no nie do konca, musisz pobrac informacje o Alpha, a wiec tak to wyglada:

    
type
  TRGBArray = Array[Word] of TRGBTriple;
  PRGBArray = ^TRGBArray;

var
    AlphaArray: pByteArray;
    PixelArray: PRGBArray;

for Y := RGBA.Height-1 downto 0 do
      begin
        RGBAPixel:=RGBA.ScanLine[y];
        AlphaArray := png.AlphaScanline[y];
        PixelArray := png.Scanline[y];
        for X := 0 to RGBA.Width-1 do
          begin
            RGBAPixel.rgbReserved := AlphaArray[X];
            RGBAPixel.rgbRed := MulDiv(PixelArray[X].rgbtRed, AlphaArray[X], 255);
            RGBAPixel.rgbGreen := MulDiv(PixelArray[X].rgbtGreen, AlphaArray[X], 255);
            RGBAPixel.rgbBlue :=  MulDiv(PixelArray[X].rgbtBlue, AlphaArray[X], 255);
            inc(RGBAPixel);
          end;
      end;
0

wielkie dzięki, działa jak marzenie :)

0

ciesze sie, a nastepnym razem przyloz sie do pierwszego posta;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1