Seite 1 von 1

Fenster überlappend einsetzen

Verfasst: 21.07.2012 20:36
von Lambda
Habe diesen Effekt professorisch schon erreicht. Ein rahmenloses+leicht transparentes Fenster wird in ein normales Fenster mit Rand eingesetzt.

Mit SetParent_() geht es nur leider nicht da das Fenster sich dann unterhalb aller Steuerelmente befindet. Meine professorische Lösung bewegt/dimensioniert das Fenster nach seinem Parent. Wenn jetzt aber ein (z.B) Explorer(Ordner) Fenster überlapt und ich das transparente Fenster aktiviert, befindet sich das Explorer Fenster natürlich zwischen Parent und dem transparentem Fenster.

Wie setze ich nun das transparente Fenster in das andere ein, sodass es innerhalb dieses Fensters immer im Vordergrund bleibt? Sehr geschickt wäre noch, wenn das transparente Fenster dann auch nicht dem Parent den Fokus klauen würde.

Re: Fenster überlappend einsetzen

Verfasst: 21.07.2012 21:50
von HeX0R
Du meinst nicht zufällig "provisorisch"?

Nicht, dass ich jetzt den Oberlehrer spielen will (Gott bewahre), aber ich hab echt ne Weile gebraucht, um dahinter zu kommen, was du mit professorisch meinen könntest.

...um aber auf dein eigentliches Problem zu kommen:
Das ist alles recht verwirrend erklärt, einfacher wäre es, du zeigst mal ein Codebeispiel.

Re: Fenster überlappend einsetzen

Verfasst: 21.07.2012 22:42
von Lambda
Äh, ja klar, provisorisch meinte ich. ^^

Der selbe Effekt tritt z.B auf wenn ein Fenster (Vista/7) einfriert.. dann wird das innere zum Teil weiß ausgeblendet. Genau das will ich erreichen und auf dieser halb-druchsichtigen Fläche Steuerelemente setzen.

Re: Fenster überlappend einsetzen

Verfasst: 22.07.2012 03:51
von Regenduft
Meinst Du sowas? Hab' ich mal aus einem Projekt gezogen und "runterreduziert", könnte evtl. buggy sein. Außerdem "hinkt" das Fenster hinterher, da ich keinen Callback verwendet habe.

Code: Alles auswählen

; Regenduft 22.07.2012 - http://forums.purebasic.com/german/viewtopic.php?p=303827#p303827

EnableExplicit

;xFF = GetSystemMetrics_(#SM_CXFIXEDFRAME)       ; Rahmenbreite bei Fenster OHNE Sizegadget
;yFF = GetSystemMetrics_(#SM_CYFIXEDFRAME)       ; Rahmenhöhe bei Fenster OHNE Sizegadget
Global xSF = GetSystemMetrics_(#SM_CXSIZEFRAME) ; Rahmenbreite bei Fenster MIT Sizegadget
Global ySF = GetSystemMetrics_(#SM_CYSIZEFRAME) ; Rahmenhöhe bei Fenster MIT Sizegadget
Global yC  = GetSystemMetrics_(#SM_CYCAPTION)   ; Höhe der Titelzeile (OHNE Rahmenhöhe)

#WIN_Parent = 0 : #WIN_Child  = 1

Procedure.i AntagonistResize(EvntWin)
  Select EvntWin
  Case #WIN_Parent, #WIN_Child
    
    Protected WxP = WindowX     (#WIN_Parent)
    Protected WyP = WindowY     (#WIN_Parent)
    Protected WwP = WindowWidth (#WIN_Parent)
    Protected WhP = WindowHeight(#WIN_Parent)
    Protected WxC = WindowX(     #WIN_Child)
    Protected WyC = WindowY(     #WIN_Child)
    Protected WwC = WindowWidth( #WIN_Child)
    Protected WhC = WindowHeight(#WIN_Child)
    
    ; << WICHTIG >> Nur Fenstergröße ändern, wenn tatsächlich
    ; nötig, da sonst eine "Endlos-Resize-Schleife" entsteht!
    
    Select EvntWin
    
    Case #WIN_Parent
      If WxC<>WxP+xSF    : WxC=WxP+xSF    : Else : WxC=#PB_Ignore : EndIf
      If WyC<>WyP+ySF+yC : WyC=WyP+ySF+yC : Else : WyC=#PB_Ignore : EndIf
      If WwC<>WwP        : WwC=WwP        : Else : WwC=#PB_Ignore : EndIf
      If WhC<>WhP        : WhC=WhP        : Else : WhC=#PB_Ignore : EndIf
      ResizeWindow(#WIN_Child,WxC,WyC,WwC,WhC)
      ProcedureReturn #WIN_Child
      
    Case #WIN_Child
      If WxP<>WxC-xSF       : WxP=WxC-xSF       : Else : WxP=#PB_Ignore : EndIf
      If WyP<>WyC-ySF-yC    : WyP=WyC-ySF-yC    : Else : WyP=#PB_Ignore : EndIf
      If WwP<>WwC           : WwP=WwC           : Else : WwP=#PB_Ignore : EndIf
      If WhP<>WhC           : WhP=WhC           : Else : WhP=#PB_Ignore : EndIf
      ResizeWindow(#WIN_Parent,WxP,WyP,WwP,WhP)
      ProcedureReturn #WIN_Parent
      
    EndSelect
    
  EndSelect

  ProcedureReturn -1
EndProcedure

Procedure.i Antagonist(Win)
  Select Win
    Case #WIN_Parent : ProcedureReturn #WIN_Child
    Case #WIN_Child  : ProcedureReturn #WIN_Parent
    Default          : ProcedureReturn -1
  EndSelect
EndProcedure

Procedure.i SetWindowTransparency(WindowID, AlphaValue.l, TransparentColor.l, Flags=#LWA_ALPHA|#LWA_COLORKEY)
  Static Init
  If Init=0 And GetWindowLongPtr_(WindowID,#GWL_EXSTYLE)<>#WS_EX_LAYERED
    Init=-1 : SetLastError_(0)
    If SetWindowLongPtr_(WindowID,#GWL_EXSTYLE,#WS_EX_LAYERED)=0 And GetLastError_()
      Init=0 : ProcedureReturn #False
    EndIf
  EndIf
  ProcedureReturn SetLayeredWindowAttributes_(WindowID, TransparentColor, AlphaValue, Flags)
EndProcedure

Macro SetWindowState2(Window, State)
  If GetWindowState(Window) <> State : SetWindowState(Window, State) : EndIf
EndMacro

OpenWindow(#WIN_Parent,0,0,300,200,"Parent",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget|#PB_Window_MinimizeGadget)
OpenWindow(#WIN_Child,WindowX(#WIN_Parent)+xSF,WindowY(#WIN_Parent)+yC+ySF,WindowWidth(#WIN_Parent),WindowHeight(#WIN_Parent),"Child",#PB_Window_BorderLess,WindowID(#WIN_Parent))
SetWindowColor(#WIN_Parent,$0000FF) ; Rot
SetWindowColor(#WIN_Child ,$FF0000) ; Blau
SetWindowTransparency(WindowID(#WIN_Child),128,0,#LWA_ALPHA) ; Rot + Blau = Lila
DisableWindow(#WIN_Child,1)
Define EvntWin

Repeat
  Select WaitWindowEvent()
  
  Case #PB_Event_MaximizeWindow
    Debug "#PB_Event_MaximizeWindow"
    Select EventWindow()
    Case #WIN_Parent
      AntagonistResize(#WIN_Parent)
    Case #WIN_Child
      If GetWindowState(#WIN_Parent) <> #PB_Window_Maximize
        SetWindowState(#WIN_Parent, #PB_Window_Maximize)
      EndIf
    EndSelect
    
  Case #PB_Event_MinimizeWindow
    Debug "#PB_Event_MinimizeWindow"
    EvntWin = Antagonist(EventWindow())
    If EvntWin >= 0 And GetWindowState(EvntWin) <> #PB_Window_Minimize
      SetWindowState(EvntWin, #PB_Window_Minimize)
    EndIf
    
  Case #PB_Event_RestoreWindow
    Debug "#PB_Event_RestoreWindow"
    EvntWin = Antagonist(EventWindow())
    If EvntWin >= 0
      SetWindowState2(EvntWin,#PB_Window_Normal)
      AntagonistResize(EvntWin)
    EndIf
    
  Case #PB_Event_MoveWindow, #PB_Event_SizeWindow
    Debug "#PB_Event_MoveWindow, #PB_Event_SizeWindow"
    AntagonistResize(EventWindow())
    
  Case #PB_Event_CloseWindow
    End
    
  EndSelect
  
ForEver

Re: Fenster überlappend einsetzen

Verfasst: 22.07.2012 12:43
von Lambda
Das trifft es sehr genau :allright: wobei das verschieben hier fehlt, aber da sieht man wie das ganze gelöst ist.

Und es löst gleichzeitig das Problmem mit der anderen Fenstern die zwischen den beiden rutschen konnten. :allright:
Wäre nur noch die Frage ob man es nicht noch einen kleinen tick schöner lösen kann, indem das Fenster echt eingsetzt wird.

GELÖSCHT

Verfasst: 22.07.2012 13:45
von mirca
GELÖSCHT

Re: Fenster überlappend einsetzen

Verfasst: 22.07.2012 21:45
von Regenduft
mirca hat geschrieben:cOoki3druqs: Was ist das Ziel deiner halb-druchsichtigen Fläche ? Was willst du damit ereichen oder anders gesagt wofür brauchst du so was?
Also ich kann zwar nicht für cOoki3druqs sprechen, aber ich hatte damit vor ein "alternatives" DisableWindow() zu erstellen, da ich es extrem nervig finde, dass man nach einem "echten" DisableWindow() das Fenster nichtmehr verschieben, bzw. minimieren und maximieren oder "wiederherstellen" kann. Es ist immer im Weg und bei einem Klick macht es nur "Biiing!". >_<

Außerdem kann man (z.B.) ein ProgressBarGadget() draufsetzen, damit der Benutzer weiß, wie lange er noch warten muss, bis die Eingabe wieder freigegeben ist. Die "rot+blau=lila" Farbgebung in meinem Code ist nur für Debuggingzwecke.
cOoki3druqs hat geschrieben:(1.) wobei das verschieben hier fehlt
(2.) Wäre nur noch die Frage ob man es nicht noch einen kleinen tick schöner lösen kann, indem das Fenster echt eingsetzt wird.
zu 1.: Bei mir funktioniert das Verschieben, nur dass das Child erst bei loslassen der Maustaste sozusagen "hinterherspringt". Mit einem Windowcallback sollte man das aber lösen können. Ich glaube Kiffi hatte da mal irgendwo einen schönen Code gepostet. (Generell wurden Callbacks schon öfters "durchgekaut".)

zu 2.: Das ging glaube ich irgendwie per API (evtl. mit SetParent_()?), so dass das Child wie in einem MDIGadget() direkt im Fenster sitzt (also nicht über den Rand geschoben werden kann).

Wäre schön, wenn Du später Deine Lösung posten könntest! Da wäre ich sehr daran interessiert, auch wenn das Projekt in dem ich es benötige z.Zt. auf dem virtuellen Abstellgleis geparkt ist.

Re: Fenster überlappend einsetzen

Verfasst: 23.07.2012 03:08
von Lambda
zu 1. Das hab ich bereits gelöst ^^
zu 2. SetParent_ alleine tuts natürlich nicht, da muss scheinbar noch eine Statusänderung etc stattfinden.. schreibe dir dann die Lösung

Warum soetwas? Na weil ich dadurch 1. eine erzwungene Oberfläche habe (z.B Passwort Eingage für Zugriff) und 2. weil es schick aussieht :D

Bild wieder entfernt