Transparenter Dialog mit 256 Transparenz-Stufen



  • Also,

    nach langer überlegung hab ich entschieden das ich meinen aktuellen Skin nicht mehr schön genug finde.

    Bisher habe ich eine Lösung verwendet die per Regions arbeitet und dabei eine Farbe als Transparenz verwendet. Als Skin nahm ich hierfür ein BMP file.
    Problem bzw Schönheitsfehler dieser Lösung ist das man an den Rändern wo der Skin an den Hintergrund stößt immer einen sehr pixligen Rand bekommt wenn die Umrisse relativ unregelmäßig werden bzw es sich bei dem Rand um einen Farbverlauf handelt.

    Ich hab mit einem Freund gesprochen und der meinte ich sollte doch ein PNG-File verwenden das ich dort 256 verschieden Transparenz-Ebenen hätte was die Ränder meines Fensters wesentlich besser aussehen lassen würde.

    Mein erstes Ziel ist es also mein Dialog Fenster transparent zu machen.

    else if(Message==WM_CTLCOLORDLG){
    		SetBkMode((HDC)wParam, TRANSPARENT); 
    		return (long)GetStockObject(HOLLOW_BRUSH);
    	}
    

    damit wird der Background meines Dialogs schon transparent. Wenn man den Dialog nun also verschiebt wird das Fenster aber nicht mehr entsprechend aktualisiert.

    Mein Idee war bei der WM_MOUSEMOVE anzusetzen. Das Fenster wird meistens dann verschoben wenn sich auch die Mouse bewegt.
    Ich habs dann mit

    else if (Message==WM_MOUSEMOVE){
    		SendMessage(hwnd,WM_CTLCOLORDLG,(WPARAM)GetDC(GetDlgItem(hwnd,IDD_ABOUT)),(LPARAM)hwnd);		
    	}
    

    versucht aber leider ohne Erfolg. Aktualiesieren tut er aber im Moment nur wenn ich erst eine andere Anwendung anklicke/aktiviere und dann wieder meine anklicke. Dann is der Hintergrund wieder "richtig" transparent.

    Kann mir jemand nen Tipp geben wie ich meinem Fenster sagen es soll sich wenn nötig im transparenten Modus neu zeichen ?

    Danke,

    OHPen



  • if(Message==WM_INITDIALOG) {
    		SetBkMode(GetDC(GetDlgItem(hwnd,IDC_BACK)),TRANSPARENT);
    		return TRUE;
    	}//WM_INITDIALOG
    
    	else if(Message==WM_CTLCOLORDLG){			
    		SetBkMode((HDC)wParam, TRANSPARENT); 
    		return (long)GetStockObject(HOLLOW_BRUSH);
    	}
    
    	else if (Message==WM_LBUTTONDOWN){
    		ReleaseCapture(); 
    		SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
    		SendMessage(hwnd, WM_CTLCOLORDLG,(WPARAM)hwnd ,(LPARAM)hwnd);			
    		UpdateWindow(hwnd);		
    	}	
    	else if (Message==WM_PAINT){
    		SetBkMode(GetDC(GetDlgItem(hwnd,IDC_BACK)),TRANSPARENT);
    	}
    

    Ich verwende nun folgenden code und das Fenster wird nun schonmal während es verschoben wird neu gezeichnet.
    Allerdings funktioniert das noch nicht so wie ich das haben will.
    Kann mir niemand einen Tipp geben ?



  • erstmal mal ein schönheitsfehler. switche deine messages
    ungefähr so

    LRESULT CALLBACK DlgProcXYZ(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
    		case WM_COMMAND:
    			break;
    		case WM_INITDIALOG:
    			break;
    		case WM_DESTROY:
    			break;
            default:
                break;
        }
        return 0;
    }
    

    sieht besser aus, macht so zeimlich jeder so und switch soll (angeblich, quelle weis ich nicht mehr) schneller sein.

    mit mousemove sollte es doch gehen, rufe einfach UpdateWindow(..) auf. allerdings ist dies zeimlich performencefressend.
    schau die doch mal das http://www.flipcode.com/articles/article_win32skins.shtml dazu an



  • OHPen schrieb:

    Also,

    nach langer überlegung hab ich entschieden das ich meinen aktuellen Skin nicht mehr schön genug finde.

    Bisher habe ich eine Lösung verwendet die per Regions arbeitet und dabei eine Farbe als Transparenz verwendet. Als Skin nahm ich hierfür ein BMP file.
    Problem bzw Schönheitsfehler dieser Lösung ist das man an den Rändern wo der Skin an den Hintergrund stößt immer einen sehr pixligen Rand bekommt wenn die Umrisse relativ unregelmäßig werden bzw es sich bei dem Rand um einen Farbverlauf handelt.

    Ich hab mit einem Freund gesprochen und der meinte ich sollte doch ein PNG-File verwenden das ich dort 256 verschieden Transparenz-Ebenen hätte was die Ränder meines Fensters wesentlich besser aussehen lassen würde.

    Mein erstes Ziel ist es also mein Dialog Fenster transparent zu machen.

    else if(Message==WM_CTLCOLORDLG){
    		SetBkMode((HDC)wParam, TRANSPARENT); 
    		return (long)GetStockObject(HOLLOW_BRUSH);
    	}
    

    damit wird der Background meines Dialogs schon transparent. Wenn man den Dialog nun also verschiebt wird das Fenster aber nicht mehr entsprechend aktualisiert.

    Mein Idee war bei der WM_MOUSEMOVE anzusetzen. Das Fenster wird meistens dann [gg]site:msdn.microsoft.com verschoben wenn sich auch die Mouse bewegt.
    Ich habs dann mit

    [cpp]else if (Message==WM_MOUSEMOVE){
    SendMessage(hwnd,WM_CTLCOLORDLG,(WPARAM)GetDC(GetDlgItem(hwnd,IDD_ABOUT)),(LPARAM)hwnd);
    }[/cpp]

    versucht aber leider ohne Erfolg. Aktualiesieren tut er aber im Moment nur wenn ich erst eine andere Anwendung anklicke/aktiviere und dann wieder meine anklicke. Dann is der Hintergrund wieder "richtig" transparent.

    Kann mir jemand nen Tipp geben wie ich meinem Fenster sagen es soll sich wenn nötig im transparenten Modus neu zeichen ?

    Danke,

    OHPen

    [/gg]Google: site:msdn.microsoft.com [gg]site:msdn.microsoft.com [url] [/url][/url][url][/url][url] 🤡 🕶 🕶 [h][t]



  • lol 🤡



  • Unter welchen Windows-Versionen soll es denn laufen ?

    Edit: Ignorier diesen Post einfach 😉



  • Danke!



  • Servus.
    Man kann jedes beliebige Fenster in einen "Layered Modus" umschalten.
    Du kannst den unten stehenden Code einfach in dein Project einfügen.
    Rufe dann bei Message==WM_INITDIALOG die Funktion auf. iAlpha ist dabei der sogenannte "Blendfaktor". Er kann Werte von 0-255 annehmen. Jeh größer dieser Faktor, umso undurchsichtiger wird dein Fenster.
    Nun zu "COLOR_TRANSPARENT":
    Erstens: Die Farbe ist beliebig.
    Zweitens: Wenn deine Hintergrundfarbe des Fensters identisch ist mit "COLOR_TRANSPARENT" oder du irgendetwas in deinem Fenster in dieser Farbe zeichnest, wird dein Fenster an der Stelle 100% transparent.
    Ich glaube, das ist was du suchst 😉

    #ifndef WS_EX_LAYERED
    #define WS_EX_LAYERED 0x00080000
    #endif
    
    #ifndef LWA_COLORKEY
    #define LWA_COLORKEY 1
    #endif
    #ifndef LWA_ALPHA
    #define LWA_ALPHA 2
    #endif
    
    #define COLOR_TRANSPARENT	RGB(0,0,1)
    
    int SetWindowTransparent_l(HWND hwnd, int iAlpha)
    {
      typedef DWORD (WINAPI *PSLWA)(HWND, DWORD, BYTE, DWORD);
      PSLWA			pSetLayeredWindowAttributes;
      HMODULE		hDLL;
      SetWindowLong (hwnd , GWL_EXSTYLE , GetWindowLong (hwnd , GWL_EXSTYLE ) | WS_EX_LAYERED ) ;
      hDLL = LoadLibrary ("user32.dll");
      if(!hDLL)
        MessageBox(NULL,TEXT("No Handle"),TEXT("ERROR"),MB_OK);
      pSetLayeredWindowAttributes = (PSLWA) GetProcAddress(hDLL,"SetLayeredWindowAttributes");
      if (pSetLayeredWindowAttributes != NULL)
      {
            /*
            * Second parameter RGB(255,255,255) sets the colorkey
            * to white LWA_COLORKEY flag indicates that color key
            * is valid LWA_ALPHA indicates that ALphablend parameter
            * (factor) is valid
            */
        pSetLayeredWindowAttributes (hwnd,COLOR_TRANSPARENT, iAlpha, LWA_COLORKEY|LWA_ALPHA);
      }
      return (0);
    }
    

    PS: An den 100% transparenten Stellen reagiert dein Fenster nicht mehr auf deine Eingaben, sondern das darunter liegende.



  • Man kann jedes beliebige Fenster in einen "Layered Modus" umschalten.

    Fenster mit dem WS_CHILD Flag nicht.

    Der Thread ist aber von 2004. Ich glaube nicht das er noch wirklich Hilfe braucht. 😉

    Aber trotzdem gut mal ein Beispiel dafür hier im Forum zu haben. 🙂



  • bei mir funktioniert das irgendwie nicht...
    kann jemand helfen???

    code:

    #define WIN32_LEAN_AND_MEAN //tells the compiler not to include MFC overhead
    #include <windows.h>
    #include <windowsx.h>
    #include <stdio.h>
    #include <math.h>
    
    #ifndef WS_EX_LAYERED
    #define WS_EX_LAYERED 0x00080000
    #endif
    
    #ifndef LWA_COLORKEY
    #define LWA_COLORKEY 1
    #endif
    #ifndef LWA_ALPHA
    #define LWA_ALPHA 2
    #endif
    
    #define COLOR_TRANSPARENT    RGB(255,255,255)
    
    int SetWindowTransparent_l(HWND hwnd, int iAlpha)
    {
      typedef DWORD (WINAPI *PSLWA)(HWND, DWORD, BYTE, DWORD);//BYTEv
      PSLWA            pSetLayeredWindowAttributes;
      HMODULE        hDLL;
      SetWindowLong (hwnd , GWL_EXSTYLE , GetWindowLong (hwnd , GWL_EXSTYLE ) | WS_EX_LAYERED ) ;
      hDLL = LoadLibrary ("user32.dll");
      if(!hDLL)
        MessageBox(NULL,TEXT("No Handle"),TEXT("ERROR"),MB_OK);
      pSetLayeredWindowAttributes = (PSLWA) GetProcAddress(hDLL,"SetLayeredWindowAttributes");
      if (pSetLayeredWindowAttributes != NULL)
      {
            /*
            * Second parameter RGB(255,255,255) sets the colorkey
            * to white LWA_COLORKEY flag indicates that color key
            * is valid LWA_ALPHA indicates that ALphablend parameter
            * (factor) is valid
            */
        pSetLayeredWindowAttributes (hwnd,COLOR_TRANSPARENT, iAlpha, LWA_COLORKEY|LWA_ALPHA);
      }
      return (0);
    }
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
    {
    	PAINTSTRUCT ps; //used when we get the WM_PAINT event
    	HDC hdc;
    	char buffer[80]; //used to print string
    	static int paintMessage = 0; //counter used to hold the number of times WM_PAINT has been called
    
    	//switch and see what message we are getting
    
    	if(msg==WM_INITDIALOG)
    		{
                    SetWindowTransparent_l(hwnd,100);
    		}
    
    	if(msg==WM_DESTROY)
    		{
    			PostQuitMessage(0);
    			return 0;
    		}
    
    	//take care of messages we didnt
    	return(DefWindowProc(hwnd, msg, wparam, lparam));
    
    }//end WindowProc
    
    //WinMain Entry
    int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow)
    {
    
    	WNDCLASSEX window; //blank window, we're using the extended windows class (WNDCLASSEX)
    	HWND hwnd; //window handle
    	MSG msg; //message
    
    	//now to fill in the window class
    	window.cbClsExtra = 0; //extra class stuff, set to 0 for now
    	window.cbSize = sizeof(WNDCLASSEX); //set to the size of the WINDOWCLASSEX structure
    	window.cbWndExtra = 0; //extra class stuff, set to 0 for now
    	window.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//BLACK_BRUSH); //sets the color of the brush to paint in, notice the type cast to HBRUSH, this is because GetStockObject() can be used for more tehn just getting the brushcolor
    	window.hCursor = LoadCursor(NULL, IDC_ARROW); //cursor for your app, sets it to the standard arrow
    	window.hIcon = LoadIcon(NULL, IDI_APPLICATION); //icon of your program
    	window.hIconSm = LoadIcon(NULL, IDI_APPLICATION); //icon that appears on the titlebar and when minimized
    	window.hInstance = hinstance; //the application instance
    	window.lpfnWndProc = WindowProc; //name of the function that takes care of the messages
    	window.lpszClassName = "WINCLASS1"; //name of the class
    	window.lpszMenuName = NULL; //menu, dont worry about this now (maybe in a later example, just set it to NULL
    	window.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; //finally the style of the window, these are 
    																	//the most used and should suffice
    
    	//register the window class, notice we're using RegisterWindowEx() because we are using the extended window class
    	if(!RegisterClassEx(&window))
    		return 0;
    
    	//create the window
    	if(!(hwnd = CreateWindowEx(
    		NULL,//WS_EX_TRANSPARENT, //extended style
    		"WINCLASS1", //name of the class
    		"... by K4!53R", //title of the window
    		WS_OVERLAPPEDWINDOW | WS_VISIBLE, //common flags, you DO want to see your window, right?
    		0, 0, //initial x and y postion
    		300, 100, //initial height and width
    		NULL, //handle to parent, set to NULL so the desktop is the parent
    		NULL, //handle to menu, we didnt use a menu now so dont worry about it
    		hinstance, //instance of application
    		NULL ))) //extra param
    	return 0;
    
    	//main event loop
    	while(true)
    	{
    
    		//test if we have a message waiting for us in queue, if there is, take care of it
    		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    		{
    
    			//check if message is a WM_QUIT message
    			if(msg.message == WM_QUIT)
    				break;
    
    			//translate any accelerator keys
    			TranslateMessage(&msg);
    
    			//send message to the window proc 
    			DispatchMessage(&msg);
    
    		}
    
    	}//end while
    
    	//use this to return to windows
    	return(msg.wParam);
    
    }//end WinMain
    


  • Fehlerbeschreibung?



  • Das fenster wird ganz normal angezeigt und ist kein bisschen durchsichtig...!



  • Hättest du dir auch nur ein bisschen Mühe gegeben hättest du gemerkt das du WM_INITDIALOG gar nicht bekommst. WM_CREATE ist der richtige Platz.

    Außerdem:

    WS_EX_LAYERED
    Windows 2000/XP: Creates a layered window. Note that this cannot be used for child windows. Also, this cannot be used if the window has a class style of either CS_OWNDC or CS_CLASSDC.

    Bei meinem Test hat es aber trotz CS_OWNDC geklappt. 😕



  • COOL 😃 😮
    danke!!!
    vielen dank!
    es funzt!



  • transparente fenster sind scheisse 😃



  • wenn du nicht weist, worum es geht, kannst du dazu eigentlich nicht viel sagen, aber wenn du meinst...
    (du bist doch nur neidisch, dass ich das hinbekommen habe... 😉 😃 )


Log in to reply