Tranparentes Fenster und Alphablending

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Morty
Beiträge: 268
Registriert: 22.10.2004 07:20
Wohnort: Erfurt
Kontaktdaten:

Beitrag von Morty »

Hi.

Hat einer eine Ahnung wie man das ganze in Echtzeit skalieren kann? So wie bei dieser Dock auf'n Mac.

Mit einem einfach Resize des Bildes und dann das Fenster via UpdateLayeredWindow und den richtigen Daten 'erneuern' klappt es leider nicht.

Morty
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Beitrag von Hoto »

Deluxe0321 hat geschrieben:

Code: Alles auswählen

;http://www.purebasic.fr/english/viewtopic.php?p=211814#211814
;netmaestro [Sat Sep 29, 2007]
Procedure StringToBStr (string$) ; By Zapman Inspired by Fr34k
  Protected Unicode$ = Space(Len(String$)* 2 + 2)
  Protected bstr_string.l
  PokeS(@Unicode$, String$, -1, #PB_Unicode)
  bstr_string = SysAllocString_(@Unicode$)
  ProcedureReturn bstr_string
EndProcedure

ProcedureDLL LoadDecodedImage(Filename$)

  CompilerIf Defined(GdiplusStartupInput, #PB_Structure) = 0
    Structure GdiplusStartupInput
      GdiPlusVersion.l
      *DebugEventCallback.Debug_Event
      SuppressBackgroundThread.l
      SuppressExternalCodecs.l
    EndStructure
  CompilerEndIf 
 
  OpenLibrary(0, "gdiplus.dll")
   
  input.GdiplusStartupInput
  input\GdiPlusVersion = 1
 
  CallFunction(0, "GdiplusStartup", @*token, @input, #Null)

  CallFunction(0, "GdipCreateBitmapFromFile", StringToBStr(Filename$), @*image)
 
  CallFunction(0, "GdipGetImageWidth", *image, @Width.l)
  CallFunction(0, "GdipGetImageHeight", *image, @Height.l)
  CallFunction(0, "GdipCreateHBITMAPFromBitmap", *image, @imageid.l, -1)
  CallFunction(0, "GdipDisposeImage", *image)
  CallFunction(0, "GdiplusShutdown", *token)
  CloseLibrary(0)
 
  return_imagenumber = CreateImage(#PB_Any, width, height, 32)
  StartDrawing(ImageOutput(return_imagenumber))
    DrawAlphaImage(imageid,0,0)
  StopDrawing()
 
  ProcedureReturn return_imagenumber
EndProcedure

img = LoadDecodedImage("Documents.png")

OpenWindow(0,0,0,300,300,"",#PB_Window_ScreenCentered|#PB_Window_BorderLess|#PB_Window_Invisible)
SetWindowLong_(WindowID(0),#GWL_EXSTYLE,GetWindowLong_(WindowID(0),#GWL_EXSTYLE)|#WS_EX_LAYERED)
CreateGadgetList(WindowID(0))

  hDC = StartDrawing(ImageOutput(img))
    sz.SIZE
    sz\cx = ImageWidth(img)
    sz\cy = ImageHeight(img)
    ContextOffset.POINT
    BlendMode.BLENDFUNCTION
    BlendMode\SourceConstantAlpha = 255
    BlendMode\AlphaFormat = 1
    UpdateLayeredWindow_(WindowID(0), 0, 0, @sz, hDC, @ContextOffset, 0, @BlendMode, 2)
  StopDrawing()

ImageGadget(0,0,0,0,0,ImageID(img))
HideWindow(0,0)

Repeat:E=WaitWindowEvent():Delay(5):Until(E=#PB_Event_CloseWindow):End 
Diese LoadDecodedImage Funktion soll doch dazu sein, um einen Bug im PNG Decoder zu umgehen, weswegen die Alpha Transparenz sonst nicht funktionieren soll. Ich habs aber nun normal mit dem LoadImage Befehl von PB probiert und das PNG wird einwandfrei dargestellt. Kann es sein, dass dieser Code für eine ältere PB Version erstellt wurde und dieser Bug inzwischen gefixt ist? Verwende 4.10 und da funktioniert es wie gesagt auch mit LoadImage.

Das fiel mir nur gerade auf, weil ein zweites PNG Bild unerklärlicher weise zu dunkel dargestellt wurde. Da dachte ich mir ich probiers mal mit LoadImage. Zu meiner Verwunderung war nicht nur die Helligkeit richtig, sondern auch die Transparenz. Kann ich mir diese LoadDecodedImage Funktion ja sparen.


Kann es sein, dass man kein Image mit Alpha Transparenz per ResizeImage im Mode #PB_Image_Smooth verkleinern kann? Krieg da nichts angezeigt, während der RAW Modus funktioniert.
Zuletzt geändert von Hoto am 03.07.2008 12:26, insgesamt 1-mal geändert.
Benutzeravatar
Morty
Beiträge: 268
Registriert: 22.10.2004 07:20
Wohnort: Erfurt
Kontaktdaten:

Beitrag von Morty »

Hi.

Jo, ist mir auch gerade aufgefallen. Das Beispiel was ich habe nutzt auch das normal LoadImage was vollkommen ausreicht.

Wichtig für's transparente Skining ist denke ich nur:

Code: Alles auswählen

SetWindowLong_(WindowID(0),#GWL_EXSTYLE,GetWindowLong_(WindowID(0),#GWL_EXSTYLE)|#WS_EX_LAYERED) 

hDC = StartDrawing(ImageOutput(img)) 
  sz.SIZE 
  sz\cx = ImageWidth(img) 
  sz\cy = ImageHeight(img) 
  ContextOffset.POINT 
  BlendMode.BLENDFUNCTION 
  BlendMode\SourceConstantAlpha = 255 
  BlendMode\AlphaFormat = 1 
  UpdateLayeredWindow_(WindowID(0), 0, 0, @sz, hDC, @ContextOffset, 0, @BlendMode, 2) 
StopDrawing() 
Ein PNG mit Alpha in der Größe zu ändern geht nur mit #PB_Image_Raw , das hattest Du ja auch schon rausbekommen. Ansonsten geht der Alpha Kanal verloren.

Ich hab jetzt schon viel probiert. Also, das Bild via Tastendruck kleiner gemacht und den ganzen Codezweig nochmal ausgeführt. Nur leider ändert sich das Bild dabei nicht. Man merkt zwar beim Verkleinern das sich der Rahmen verändert, aber da wird das Bild nur abgeschnitten. Größe bleibt wie beim Initialisieren erhalten. Komisch?!?

Aber irgendwie muss das doch gehen?

Morty
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Beitrag von Hoto »

Jo, eventuell hab ich aber ne Lösung, wenn ich für folgendes Problem eine Lösung finde. ;)

Wenn ich mit LoadImage(img,"test.png) ein Image reingeladen habe, wie kann ich das dann an GDI+ übergeben?

GdipDrawImageRectI(*gfx, *image, 0, 0, 160 , 160)

Was muss da statt *image dann rein? Habs schon mit img, ImageID(img) und *img probiert, nix.
Benutzeravatar
Morty
Beiträge: 268
Registriert: 22.10.2004 07:20
Wohnort: Erfurt
Kontaktdaten:

Beitrag von Morty »

Warum?

Das GDI+ Zeugs im oberen Teil des Quellcodes war doch nur ein alter Workaround für das Laden eine PNG mit Alpha. Für das eigentliche Skining braucht man das doch garnicht. Das findet in den von mir erwähnten Zeilen statt.

Aber wenn Du es unbedingt so brauchst, warum lädst Du es dann nicht via GDI+ ? Damit hast Du auf jeden Fall ein gültiges Handle.
Die entsprechenden Funktionen stehen ja auch schon da.

Morty
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Beitrag von Hoto »

Morty hat geschrieben:Warum?

Das GDI+ Zeugs im oberen Teil des Quellcodes war doch nur ein alter Workaround für das Laden eine PNG mit Alpha. Für das eigentliche Skining braucht man das doch garnicht. Das findet in den von mir erwähnten Zeilen statt.
Weil ich GDI+ vielleicht auch noch für andere Dinge in meinem Programm brauche wofür der normale PB Kram teilweise viel zu langsam ist (z.B. ImageResize)?
Aber wenn Du es unbedingt so brauchst, warum lädst Du es dann nicht via GDI+ ? Damit hast Du auf jeden Fall ein gültiges Handle.
Die entsprechenden Funktionen stehen ja auch schon da.
Weil damit irgendwas nicht stimmt, eines meiner PNG Bilder kommt viel zu dunkel raus, hat weder was mit gAMA zu tun noch mit dem Bild an sich, alle anderen Programme stellen es richtig dar. Aber vielleicht weiß ja Jemand hierfür eine Lösung, dann bräuchte ich für das andere jetzt auch keine Lösung.

Code: Alles auswählen

Procedure LoadDecodedImage(Filename$)
  GdipCreateBitmapFromFile(Filename$, @*image)
  GdipGetImageWidth(*image, @width.l)
  GdipGetImageHeight(*image, @height.l)
  GdipCreateHBITMAPFromBitmap(*image, @hBitmap.l, 0)
  
  image2.l = CreateImage(#PB_Any,width,height,32)
  StartDrawing(ImageOutput(image2))
  DrawAlphaImage(hBitmap,0,0)
  StopDrawing()
  ProcedureReturn image2
EndProcedure
Mit dieser Prozedur lade ich das PNG rein, dann siehts aber so aus (links wie es sein soll mit LoadImage und rechts mit GDI+):
Bild

Jemand eine Idee an was das liegen könnte? Bei einem anderen PNG funktioniert das einwandfrei.
Benutzeravatar
Morty
Beiträge: 268
Registriert: 22.10.2004 07:20
Wohnort: Erfurt
Kontaktdaten:

Beitrag von Morty »

Okay, kannst Du das entsprechende PNG mal irgendwie als Download zur Verfügung stellen? Da würde ich auchmal probieren.

Morty
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Beitrag von Hoto »

Jo, kein Problem.

Bild

Im übrigen hab ich inzwischen raus gefunden wie man PB Images an GDI übergeben kann, mit GdipCreateBitmapFromHBITMAP(ImageID(img), 0, @*image). Leider ist dann aber komplett die Transparenz weg, wenn ich das auch noch hinkriegen würde, wäre das Problem auch so beseitigt. /:->

Edit: scheint irgendwas mit der Transparenz zu tun zu haben, beim ursprünglichen Bild ist das FF Symbol nicht durchsichtig, das hab ich erst durchsichtig gemacht und erst dadurch kommt es per GDI+ zu dunkel raus...
Benutzeravatar
Hoto
Beiträge: 294
Registriert: 01.09.2004 22:51

Beitrag von Hoto »

Niemand sonst ne Idee wieso GDI+ hier Murks macht?
Benutzeravatar
TomS
Beiträge: 1508
Registriert: 23.12.2005 12:41
Wohnort: München

Beitrag von TomS »

Hoto hat geschrieben:Niemand sonst ne Idee wieso GDI+ hier Murks macht?
Leider nein. Kann mir vielleicht jemand sagen, wie ich an das Image komme, wenn ich es per IncludeBinary einbinde? CatchImage() is schon klar, aber wo muss ich das Handle an das GDI-Gedöns (dass ich btw gar nich raff) übergeben?
Antworten