Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Anfängerfragen zum Programmieren mit PureBasic.
ads2010
Beiträge: 6
Registriert: 18.03.2010 15:34

Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ads2010 »

Guten Tag,
und "Hallo" ersteinmal. Ich bin neu hier und seit kurzem mit PB beschäftigt.

Ich habe folgendes Problem. Ich benutze eine Prozedur zum Einblenden eines Windows Fensters, welches vorher ein Bild durch ein Imagegadget bekommen hat. Dazu verwende ich die dshowmedia.pbi von Inc. um ein Video in einem weiteren Imagegadget abzuspielen. Die Moviebefehle von PB funktionieren nicht immer einwandfrei mit .wmv (insbesondere Movieseek).

Wenn ich das Bild eingeblendet habe, ist das Video nicht zu sehen. Mir war klar, dass ich das SetWindowLong und dort das #GWL_Exstyle Flag wieder zurücksetzen muss. Das habe ich probiert und dann wird auch das Video einwandfrei in meinem Gadget abgespielt. Offensichtlich mache ich aber etwas falsch, denn will ich nun das Fenster mit Bild wieder ausblenden, wird nicht das Bild ausgeblendet sonder das Fenster wird schwarz und das schwarze Fenster ausgeblendet.

Dieser Fehler tritt "nur" unter Windows XP auf. Unter Windows 7 läuft es einwandfrei. Ich gehe davon aus, dass ich einen falschen Wert in das SetWindowLong schreibe und es deswegen nicht funktioniert.

PB V. 4.40

Anbei eine sehr abgespeckte Version ohne dshowmedia. Das Problem bleibt erhalten. Hat jemand eine Idee?

Code: Alles auswählen

Procedure SetWinTransparency(win,level) 
  If level>=0 And level<101 
    hLib = LoadLibrary_("user32.dll") 
    If hLib 
      adr = GetProcAddress_(hLib,"SetLayeredWindowAttributes") 
      If adr 
        ergebnis=SetWindowLongPtr_(WindowID(win),#GWL_EXSTYLE,GetWindowLong_(WindowID(win),#GWL_EXSTYLE)|$00080000) ; #WS_EX_LAYERED = $00080000 
        Debug ergebnis
        CallFunctionFast(adr,WindowID(win),0,255*level/100,2) 
      EndIf 
      FreeLibrary_(hLib) 
    EndIf 
  EndIf 
EndProcedure 


UseJPEGImageDecoder()

LoadImage (0, "gfx/bild.jpg")

OpenWindow(0,0,0,0,0,"Waldhaus",   #PB_Window_ScreenCentered|#PB_Window_BorderLess)
setwintransparency (0,0)
x=WindowX(0)
y=WindowY(0)

x=x-1024/2:y=y-768/2

ResizeWindow ( 0, x, y,1024,768)
ImageGadget(0,  0, 0, 1024, 768, ImageID(0))
DisableGadget (0,1)
ButtonGadget(6,950,700,48,48,"")
SetGadgetText(6,"EXIT!")

;einblenden von 0 auf 100%
 x=0
 Repeat 
 x=x+1
 Delay (5)
 SetWinTransparency(0,x)
 Until x = 100
 
;zurücksetzen des GWL_Exstyle Wertes
 
 SetWindowLongPtr_(WindowID(win),#GWL_EXSTYLE,GetWindowLong_(WindowID(win),#GWL_EXSTYLE)& ~#WS_EX_LAYERED)

;auf exit warten     
 quit=0   
 Repeat
     
 ev = WindowEvent() 
    
 Select ev
   Case #PB_Event_Gadget
    Select EventGadget()
     Case 6:quit=1
    EndSelect
 EndSelect
        
 Until quit=1

 ;Bild ausblenden von 100% auf 0 
  x=100
  Repeat 
   x=x-1
   Delay (5)
   SetWinTransparency(0,x)
  Until x = 0
  
End
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ts-soft »

Keine Probleme unter XP Sp3

Hab aber trotzdem noch kleinere Fehler beseitigt, das EventLoop korrigiert, GetWindowLongPtr_(),
sowie unnötige API entfernt und auf Prototypes umgestellt!
(funktioniert natürlich auch ohne diese Änderungen unter Win 32-Bit)

Code: Alles auswählen

Prototype SetLayeredWindowAttributes(hWnd, crKey, bAlpha, dwFlags)

Procedure SetWinTransparency(win, level)
  Protected hLib, ergebnis
  Protected SetLayeredWindowAttributes.SetLayeredWindowAttributes
  
  If level >= 0 And level < 101
    hLib = OpenLibrary(#PB_Any, "user32.dll")
    If hLib
      SetLayeredWindowAttributes = GetFunction(hLib, "SetLayeredWindowAttributes")
      If SetLayeredWindowAttributes
        ergebnis = SetWindowLongPtr_(WindowID(win), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(win), #GWL_EXSTYLE) | $00080000) ; #WS_EX_LAYERED = $00080000
        Debug ergebnis
        SetLayeredWindowAttributes(WindowID(win), 0, 255*level / 100, 2)
      EndIf
      CloseLibrary(hLib)
    EndIf
  EndIf
EndProcedure


UseJPEGImageDecoder()

LoadImage (0, "gfx/bild.jpg")

OpenWindow(0, 0, 0, 0, 0, "Waldhaus",   #PB_Window_ScreenCentered | #PB_Window_BorderLess)
setwintransparency (0, 0)
x = WindowX(0)
y = WindowY(0)

x = x - 1024 / 2:y = y - 768 / 2

ResizeWindow ( 0, x, y, 1024, 768)
ImageGadget(0,  0, 0, 1024, 768, ImageID(0))
DisableGadget (0, 1)
ButtonGadget(6, 950, 700, 48, 48, "")
SetGadgetText(6, "EXIT!")

;einblenden von 0 auf 100%
x = 0
Repeat
  x = x + 1
  Delay (5)
  SetWinTransparency(0, x)
Until x = 100

;zurücksetzen des GWL_Exstyle Wertes

SetWindowLongPtr_(WindowID(win), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(win), #GWL_EXSTYLE) & #WS_EX_LAYERED)

;auf exit warten
quit = 0
Repeat

  ev = WaitWindowEvent()

  Select ev
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 6:quit = 1
      EndSelect
  EndSelect

Until quit = 1

;Bild ausblenden von 100% auf 0
x = 100
Repeat
  x = x - 1
  Delay (5)
  SetWinTransparency(0, x)
Until x = 0

End
Gruß
Thomas
ads2010
Beiträge: 6
Registriert: 18.03.2010 15:34

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ads2010 »

Hi Thomas,

habe Besten Dank! Ich habe es unter WIN XP SP2 probiert und da ging es nicht. Durch das Weglassen der API Befehle und Nutzung der PB Befehle (Deine Version) geht es jetzt auch bei mir. Meine Version oben aber nicht. Ich habe zwar keine Ahnung wieso, aber letztenendes zählt das Ergebnis.

Nochmals vielen Dank. Ich habe daran schon drei Tage rumgewerkelt.

Grüße Frank

EDIT:

Nein, es funktioniert doch nicht. Du hast:
SetWindowLongPtr_(WindowID(win),#GWL_EXSTYLE,GetWindowLong_(WindowID(win),#GWL_EXSTYLE)& ~#WS_EX_LAYERED)

geändert und zwar den Wert "~#WS_EX_LAYERED". Bei die fehlt "~"

Dadurch setzt Du das Windows Fenster nicht zurück. Dann funktioniert das Ein- und Ausblenden, aber das Video wird nicht in meinem anderen ImageGadget angezeigt.

:-(
Zuletzt geändert von ads2010 am 18.03.2010 17:20, insgesamt 1-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ts-soft »

Die einzige Erklärung wäre, das Du SetWindowLongPtr_() verwendest hast, aber als
Gegenstück GetWindowLong_() (statt GetWindowLongPtr_()), das sollte dann aber nur
unter WinXP 64-Bit einen Unterschied machen.

Egal, Hauptsache es hilft :wink:
ads2010
Beiträge: 6
Registriert: 18.03.2010 15:34

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ads2010 »

Ich habe auch probiert,

Code: Alles auswählen

SetWindowLongPtr_(WindowID(win), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(win), #GWL_EXSTYLE) & #WS_EX_LAYERED)
Vor das Ausblenden zu schreiben. Bleibt aber beim gleichen Fehler.

Die Frage ist, ob ich das Fenster 100% richtig wieder so herstelle, wie es vor der SetWinTransparency Prozedur war. Ich glaube, der Wert "~#GWL_EX_Layered" ist falsch. Ohne "~" ist es nichts anderes, nach der Transparenz Funktion.

:cry:
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ts-soft »

Du setzt den Style in der Procedure auch Mehrfach! Einmal sollte genügen.
Desweiteren kannste das Ergebnis von GetWindowLongPtr_() auch zwischenspeichern,
und einfach wieder herstellen.
ads2010
Beiträge: 6
Registriert: 18.03.2010 15:34

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ads2010 »

Stimmt einmal sollte reichen, ich habe es jetzt rausgenommen und rufe vorher nur einmal auf.

Der Wert ist 0 den ich zurückbekomme (sowohl mir setwindowlongPtr als auch mit getwindowlongptr erhalte ich jeweils 0)

nach dem Einblenden erhalte ich 524288

Wenn ich dann

Code: Alles auswählen

SetWindowLongPtr_(WindowID(win), #GWL_EXSTYLE, 0)
setze, habe ich leider das gleiche problem. :cry:

Kann es sein, dass ich nicht den richtigen Wert ausgelesen bekomme?
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ts-soft »

0 ist korrekt für den ExStyle. 524288 sollte er mit Layered Flag sein.
Dein Problem ist also ein anderes, was ich aber hier nicht sehen noch
testen kann, da der Teil, wo der Fehler auftritt ja fehlt.
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von mk-soft »

Wenn es bei ts-soft mit winxp sp3 funktioniert, liegt es vielleicht an dein sp2.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
ads2010
Beiträge: 6
Registriert: 18.03.2010 15:34

Re: Problem Ein/Ausblenden (SetWindowLong Wert stimmt nicht)

Beitrag von ads2010 »

Nee, nee, mein Programm oben ist die abgespeckte Version die nicht richtig funktioniert, d.h. der Bildschirm wird schwarz und dann ausgeblendet. Hast Du dieses exakt so bei dir getestet oder auch ohne "~". ohne ist klar, dass es funktioniert. Du kannst auch stattdessen

Code: Alles auswählen

SetWindowLongPtr_(WindowID(win),#GWL_EXSTYLE,0)
einfügen. Das macht das gleiche Problem. Wenn nicht, wurde der Fehler im SP3 beseitigt. Wie gesagt unter Win7 ist alles Problemlos.

:) Ich habe jetzt aber eine andere Lösung für das Ausblenden, welche funktioniert.

Ich nehme am Ende einfach

AnimateWindow_(WindowID(0),3000,#AW_BLEND|#AW_HIDE)

und gut ist!

Im Übrigen muss ich da auch wieder auf "0" oder "~#WS_EX_LAYERED" setzen, damit es geht. Dann funktioniert es aber einwandfrei. Ich glaube, hier ist ein Bug in der user32.dll. Ich habe es auf zwei weiteren XP SP2 Rechnern getestet und da ist der gleiche Fehler aufgetreten.

Mir ist es ein Rätsel...
Antworten