Fenster immer im Vordergrund



  • Weiß jemand wie man:
    SetWindowPos((???), HWND_TOP, 0, 0, 800, 600, SWP_SHOWWINDOW | SWP_NOMOVE);
    in mein SFML Programm einbinden kann?

    #include "pch.h"
    #include <SFML/Graphics.hpp>
    
    #if defined (SFML_SYSTEM_WINDOWS)
    #include <windows.h>
    
    bool setShape(HWND hWnd, const sf::Image& image)
    {
    	const sf::Uint8* pixelData = image.getPixelsPtr();
    	HRGN hRegion = CreateRectRgn(0, 0, image.getSize().x, image.getSize().y);
    
    	// Determine the visible region
    	for (unsigned int y = 0; y < image.getSize().y; y++)
    	{
    		for (unsigned int x = 0; x < image.getSize().x; x++)
    		{
    			if (pixelData[y * image.getSize().x * 4 + x * 4 + 3] == 0)
    			{
    				HRGN hRegionPixel = CreateRectRgn(x, y, x + 1, y + 1);
    				CombineRgn(hRegion, hRegion, hRegionPixel, RGN_XOR);
    				DeleteObject(hRegionPixel);
    			}
    		}
    	}
    
    	SetWindowRgn(hWnd, hRegion, true);
    	DeleteObject(hRegion);
    	return true;
    }
    
    bool setTransparency(HWND hWnd, unsigned char alpha)
    {
    	SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    	SetLayeredWindowAttributes(hWnd, 0, alpha, LWA_ALPHA);
    	return true;
    }
    
    #elif defined (SFML_SYSTEM_LINUX)
    #include <X11/Xatom.h>
    #include <X11/extensions/shape.h>
    
    bool setShape(Window wnd, const sf::Image& image)
    {
    	const sf::Uint8* pixelData = image.getPixelsPtr();
    	Display* display = XOpenDisplay(NULL);
    
    	// Try to set the window shape
    	int event_base;
    	int error_base;
    	if (XShapeQueryExtension(display, &event_base, &error_base))
    	{
    		Pixmap pixmap = XCreatePixmap(display, wnd, image.getSize().x, image.getSize().y, 1);
    		GC gc = XCreateGC(display, pixmap, 0, NULL);
    
    		XSetForeground(display, gc, 1);
    		XFillRectangle(display, pixmap, gc, 0, 0, image.getSize().x, image.getSize().y);
    		XSetForeground(display, gc, 0);
    
    		for (unsigned int y = 0; y < image.getSize().y; y++)
    		{
    			for (unsigned int x = 0; x < image.getSize().x; x++)
    			{
    				if (pixelData[y * image.getSize().x * 4 + x * 4 + 3] == 0)
    					XFillRectangle(display, pixmap, gc, x, y, 1, 1);
    			}
    		}
    
    		XShapeCombineMask(display, wnd, ShapeBounding, 0, 0, pixmap, ShapeSet);
    		XFreeGC(display, gc);
    		XFreePixmap(display, pixmap);
    		XFlush(display);
    		XCloseDisplay(display);
    		return true;
    	}
    
    	XCloseDisplay(display);
    }
    
    bool setTransparency(Window wnd, unsigned char alpha)
    {
    	Display* display = XOpenDisplay(NULL);
    	unsigned long opacity = (0xffffffff / 0xff) * alpha;
    	Atom property = XInternAtom(display, "_NET_WM_WINDOW_OPACITY", false);
    	if (property != None)
    	{
    		XChangeProperty(display, wnd, property, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&opacity, 1);
    		XFlush(display);
    		XCloseDisplay(display);
    		return true;
    	}
    	else
    	{
    		XCloseDisplay(display);
    		return false;
    	}
    }
    
    
    
    
    
    #undef None // None conflicts with SFML
    #elif defined (SFML_SYSTEM_MACOS)
    bool setShape(sf::WindowHandle handle, const sf::Image& image);
    bool setTransparency(sf::WindowHandle handle, unsigned char alpha);
    #else
    bool setShape(sf::WindowHandle handle, const sf::Image& image)
    {
    	return false;
    }
    
    bool setTransparency(sf::WindowHandle handle, unsigned char alpha)
    {
    	return false;
    }
    #endif
    
    int main()
    {
    	
    	
    	// Change this to the wanted transparency
    	const unsigned char opacity = 220;
    
    	// Load an image with transparent parts that will define the shape of the window
    	sf::Image backgroundImage;
    	backgroundImage.loadFromFile("1.png");
    
    	// Create the window and center it on the screen
    	sf::RenderWindow window(sf::VideoMode(backgroundImage.getSize().x, backgroundImage.getSize().y, 32), "Transparent Window", sf::Style::None);
    	window.setPosition(sf::Vector2i((sf::VideoMode::getDesktopMode().width - backgroundImage.getSize().x) / 2,
    		(sf::VideoMode::getDesktopMode().height - backgroundImage.getSize().y) / 2));
    
    	// These functions return false on an unsupported OS or when it is not supported on linux (e.g. display doesn't support shape extention)
    	setShape(window.getSystemHandle(), backgroundImage);
    	setTransparency(window.getSystemHandle(), opacity);
    	
    	// We will also draw the image on the window instead of just showing an empty window with the wanted shape
    //	SetWindowPos((???), HWND_TOP, 0, 0, 800, 600, SWP_SHOWWINDOW | SWP_NOMOVE);
    
    
    	sf::Texture backgroundTexture;
    	sf::Sprite backgroundSprite;
    	backgroundTexture.loadFromImage(backgroundImage);
    	backgroundSprite.setTexture(backgroundTexture);
    
    	// Main loop to display the image while the window is open (pressing the escape key to close the window)
    	while (window.isOpen())
    	{
    		sf::Event event;
    		while (window.pollEvent(event))
    		{
    			if (event.type == sf::Event::Closed || (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape))
    				window.close();
    		}
    
    		window.clear(sf::Color::Transparent);
    		window.draw(backgroundSprite);
    		window.display();
    	}
    
    	return 0;
    }
    
    
    
    
    
    
    
    


  • ich habe mir die Basics von C++ angeeignet und habe nun mit
    SFML und C++ ein transparentes Fenster erstellt. Nun möchte
    ich dieses als Overlay nutzen. Ich verstehe nur nicht wie ich
    SetWindowPos((???), HWND_TOP, 0, 0, 800, 600, SWP_SHOWWINDOW | SWP_NOMOVE);
    richtig einbauen kann. Habt ihr eine Idee wie man das lösen kann
    und wisst ihr ob die Grafik der Maus folgen kann?
    lg Doim



  • Du kommst doch mit window.getSystemHandle() an das Handle des Fensters, oder? Anschließend kannst du dieses Handle an SetWindowPos übergeben. Es sollte mMn allerdings HWND_TOPMOST sein, HWND_TOP macht es wieder rückgängig.
    Für die Regionen gibt es auch die Funktion ExtCreateRegion, die sich bei dem Vorhaben wohl besser eignet.

    Edit: In deinem Code steht das ja mehrere Male. Entweder ist der Code einfach nur zusammenkopiert oder ich verstehe die Frage nicht...



  • @yahendrik das ist ein Beispiel Code, den ich ein bisschen verändert habe. Ich bin neu in C++ und verstehe den Unterschied zwischen einem Sfml und einem normalen Fenster mit Windows.h nicht.



  • Okay, wenn die Bibliothek die Funktionalität nicht anbietet, musst du das eben an ihr vorbei machen. Letzendlich kapseln Bibliotheken auch nur die Systemaufrufe, sei es, um den Zugang einfacher zu gestalten oder aber Plattformunabhängigkeit zu erreichen. Letzteres hast du allerdings durch den Code ohnehin schon aufgegeben.
    Ein HWND ein ein Handle auf ein WiNDow. SetWindowPos und andere Funktionen der WinApi erwarten dies und können mit der SFML-Klasse natürlich nichts anfangen. Daher gibt es eben getSystemHandle(), auch wenn es in anderen Fällen vermutlich keine gute Idee ist, an der Bibliothek vorbei zu programmieren. SetWindowPos sollte allerdings keine Probleme machen.



  • @yahendrik Danke ich's Versuch das Mal. Ich melde mich.
    LG Doim



  • ich habes es gerade mit

    SetActiveWindow(hWnd);
    SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
    
    SetForegroundWindow(hWnd);
    RedrawWindow(hWnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
    

    probiert aber ich habe keine Ahnung an welcher Stelle im Programm das eingebaut werden muss



  • Den Button zur Anzeige des gesamten Codes habe ich erst kürzlich entdeckt (kam wohl erst mit dem Update des Forums). Vorher hatte ich nicht gesehen, dass Code für Linux ebenfalls vorhanden ist.
    SetWindowPos kannst du natürlich nur unter Windows einsetzen und da würde ich es mal direkt vor der Nachrichtenschleife probieren:

    ...
    #if defined (SFML_SYSTEM_WINDOWS)
        // wie schon geschrieben, sollte es HWND_TOPMOST sein
        SetWindowPos(window.getSystemHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    #endif
        while (window.isOpen())
        {
        ....
    

Anmelden zum Antworten