Rahmenloses Fenster mit eigenem Skin ohne Region (WinAPI)

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Kurzer
Beiträge: 1618
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Rahmenloses Fenster mit eigenem Skin ohne Region (WinAPI)

Beitrag von Kurzer »

Hallo zusammen,

bei der Suche nach einer Lösung zu einem geskinnten PB-Fenster habe ich nur Beispiele gefunden, die mit der Region-Funktion der WinAPI Fensterbereiche durchsichtig gemacht haben.

Hier meine Lösung, die dem PB-Fenster ein eigenes Hintergrundbild verpasst und mittels Colorkey bestimmte Bereiche transparent schaltet. Im Beispiel alles, was die RGB-Farbe $FF00FF aufweist. Dort wirkt dann auch die Maus auf den drunterliegenden Bereich. Also so, wie man sich das i.d.R. wünscht.

Hier der code dazu:

Code: Alles auswählen

EnableExplicit

Global iEvent.i, iEventGadget.i
Global iQuit.i, iImage.i, iPatternBrush.i
Global iMainWindow.i, iButton.i

iMainWindow = OpenWindow(#PB_Any, 100, 100, 105, 195, "", #PB_Window_BorderLess)

If iMainWindow
  iButton = ButtonGadget(#PB_Any, 38, 70, 35, 20, "Quit")

	; Den Patternbrush für den Fensterhintergrund aus dem Image erzeugen
	iImage = LoadImage(#PB_Any, "D:\Image.bmp")
	iPatternBrush = CreatePatternBrush_(ImageID(iImage))
	; Den Patternbrush als Fensterhintergrund zuordnen.
	SetClassLongPtr_(WindowID(iMainWindow), #GCL_HBRBACKGROUND, iPatternBrush)
	; Das Image brauchen wir jetzt nicht mehr
	FreeImage(iImage)
	
	; Jetzt das Fenster an allen Stellen mit Farbe $FF00FF durchsichtig machen (#LWA_COLORKEY)
	SetWindowLongPtr_(WindowID(iMainWindow), #GWL_EXSTYLE, #WS_EX_LAYERED)
	SetLayeredWindowAttributes_(WindowID(iMainWindow), $FF00FF, 1, #LWA_COLORKEY)

  Repeat
    iEvent = WaitWindowEvent()
	  iEventGadget = EventGadget()

	  Select iEvent
	  Case #PB_Event_Gadget
	    Select iEventGadget
	      Case iButton : iQuit = 1
	    EndSelect
	
	  Case #WM_LBUTTONDOWN 
	  	Debug "In das Window geklickt!"
	  	SendMessage_(WindowID(iMainWindow), #WM_NCLBUTTONDOWN, #HTCAPTION, 0) 
	  EndSelect

  Until iQuit = 1
  
	If iPatternBrush
		DeleteObject_(iPatternBrush)
	EndIf

	CloseWindow(iMainWindow)

EndIf
Und hier das BIld, welches nachgeladen wird:
Bild


Das ganze sieht dann so aus:
Bild

Viele Spaß damit.

PS: Wie man auch den Button skinnen kann, habe ich leider nicht rausbekommen.
ImageButton hab ich noch nicht getestet.
Verbesserungen sind herzlich willkommen.

PS2: Durch Verarbeiten der #WM_LBUTTONDOWN Message kann das Fenster an beliebiger Stelle angefasst und verschoben werden.
Zuletzt geändert von Kurzer am 30.04.2010 19:09, insgesamt 1-mal geändert.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Re: Rahmenloses Fenster mit eigenem Skin ohne Region (WinAPI

Beitrag von Kaeru Gaman »

für einen geskinten Button verwendet man dann keinen normalen Button, sondern etwas OwnerDrawn oder simpel ein ImageGadget mit einer Click-Auswertung. ;)
du brauchst keinen "echten" Button, um ein anklickbares Fensterelement zu haben.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Kurzer
Beiträge: 1618
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: Rahmenloses Fenster mit eigenem Skin ohne Region (WinAPI

Beitrag von Kurzer »

Jo, aber beim Imagegadget fehlt mir der "Reindrück-Effekt", der bei einem Button exisitert.
Kann man aber sicherlich nachempfinden?

Bei einem echten Button kannst Du es Dir mit dem Drücken ja auch nochmal überlegen, solange Du den Mausknopf noch nicht wieder losgelassen hast.

Ich hab es mit einem Image noch nicht ausgiebig gestestet (war wieder so ein Mittagspausenhack).
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
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: Rahmenloses Fenster mit eigenem Skin ohne Region (WinAPI

Beitrag von ts-soft »

Wundert mich jetzt aber, das hier noch keine Beispiele mit Layered Windows waren. Im engl. Forum gibts
da wohl ein paar.

Die Codes mit Region stammen ja größtenteils aus Zeiten, wo man auf ältere Windows Versionen noch
Rücksicht nahm :wink:

PS: Du solltest Dir angewöhnen SetClassLongPtr_, GetWindowLongPtr_ usw. zu nutzen, dann brauchste beim portieren auf x64 nicht mehr ändern!

Schönes Beispiel :allright:

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Kurzer
Beiträge: 1618
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: Rahmenloses Fenster mit eigenem Skin ohne Region (WinAPI

Beitrag von Kurzer »

Jo, danke für die Hinweise, Thomas.

Ich muß dazu sagen, daß ich nicht permanent mit PB oder Prorammierung zu tun habe. Das hat unterschiedliche Gründe.

Fakt ist aber, daß sich daher auch nur schwer ein kontinuierlicher Lerneffekt durch wiederholtes Anwenden einstellt - ähm, was vielleicht dem ein oder anderen erklärt, warum ich ab und zu im Anfängerforum poste. <)

Wenn mal wieder ein PB-Projekt ansteht und ich nicht weiterkomme, dann kratze ich mir meist die Infos aus Beispielen und dem Forum zusammen. Aber gerade im Bereich WinAPI kann ich deshalb fehlerhaften oder veralteten code nicht immer als solchen erkennen.

Was ich sagen will: Ich bin dankbar, wenn Beispiele mit Verbesserungen kommentiert werden, so wie ts-soft das in senem Beitrag getan hat.
Zu dem Fenster-Layerzeug habe ich sicherlich einen Teil auch aus dem Forum erfahren, aber eben nicht als komplettes Beispiel. Daß man den Patternbrush z.B. später wieder mit DeleteObjekt_() freigeben muß, war in keinem der Beispiele zu sehen - das habe ich aus der MSDN erfahren.

Das Beispiel oben habe ich jetzt angepaßt bzgl. SetWindowLongPtr_

Gruß vom Frosch (bzw. Markus, falls es jemand famliärer mag :wink:)
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Antworten