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 mitelse 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 soLRESULT 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...)