Clientarea eines Fensters transparent, aktualisiert nicht beim bewegen
-
Ich weiß, das Thema war schon ein paar Mal. Und ich habe es mir auch angesehen, und probiert, aber irgendwas mache ich wohl falsch.
Ich habe jetzt folgendes:
... wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); wc.hbrBackground = (HBRUSH)GetStockObject(HOLLOW_BRUSH); wc.lpszClassName = szAppName; wc.lpszMenuName = NULL; RegisterClass(&wc); hWnd = CreateWindowEx(0, szAppName, "Titelleiste", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, 0, 0); ... LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: { PAINTSTRUCT ps; ::BeginPaint(hWnd, &ps); ::SetBkMode(ps.hdc, TRANSPARENT); ::EndPaint(hWnd, &ps); break; } case WM_ERASEBKGND: { HDC hdc = ::GetDC(hWnd); ::SetBkMode(hdc, TRANSPARENT); ::ReleaseDC(hWnd, hdc); return (LRESULT)::GetStockObject(HOLLOW_BRUSH); break; } case WM_MOVE: { HDC hdc = ::GetDC(hWnd); ::SetBkMode(hdc, TRANSPARENT); ::ReleaseDC(hWnd, hdc); InvalidateRect(hWnd, NULL, false); UpdateWindow(hWnd); break; } case WM_DESTROY: { PostQuitMessage(0); return 0; } } return DefWindowProc(hWnd, message, wParam, lParam); }
Nach dem Start ist das Fenster erstmal transparent, aber, wenn ich das Fenster verschiebe, oder in der Größe ändere, dann aktualisiert sich der "transparente" Hintergrund nicht. Nur, wenn ich das Fenster minimiere und anschließend wieder maximiere, dann wird der Hintergrund aktualisiert. Ich dachte eigentlich, dass ich alles eingebaut hätte, womit es laufen sollte.
Sorry, falls es irgendwo beschrieben steht, dann habe ich es nicht gefunden.
-
Ruf mal InvalidateRect() für das hinter dem transparenten Fenster liegendem Parent-Fenster auf - letzten parameter auf true
-
nur geraten
case WM_MOVE: { // zeichnen brauchst du hier nichst // und den hintergrund löschen mit true InvalidateRect(hWnd, NULL, true); UpdateWindow(hWnd); break; }
ps:
das break in WM_ERASEBKGND hat keine funktion, kannst du dir schenken[edit]
drei sekunden zu langsam und anscheinend richtig geraten
-
Du kannst für WM_ERASEBKGND auch schreiben:
case WM_ERASEBKGND:
return 0;
das hat quasi denselben Effekt. WM_ERASEBKGND soll 0 zurückliefern, wenn der Hintergrund nicht gelöscht wurde und non-zero wenn er gelöscht wurde. Im wParam steht der HDC den man beim Hintergrund zeichnen benutzen soll.Wenn der Hintergrund nicht neugezeichnet wird und das Fenster verschoben wird, zeichnet man quasi über sich selber drüber. Deswegen muss das dahinterliegende Fenster sich neuzeichnen.
-
Ich hab' ja nur das eine Fenster. Hab' jetzt
HWND Parent = ::GetParent(hWnd); RECT r; ::GetWindowRect(hWnd, &r); InvalidateRect(Parent, &r, false);
in WM_MOVE drin, funzt trotzdem nicht. Wenn ich WS_EX_TRANSPARENT bei WindowCreateEx angebe, dann funzt es, aber da ist so ziemlich alles am flackern und krückenlahm. Außerdem ist dann nicht nur die Clientarea transparent, zu 80-90% verschwindet dann auch die Titelleiste und der Rahmen des Fensters.
Ich dachte, wenn ich die Koordinaten des Fensters an InvalidateRect übergebe, dann hört zumindest das flackern auf, aber Pustekuchen.
-
bei InvalidateRect TRUE nehmen
-
Hab' ich auch probiert, läuft auch nicht. Sonst noch eine Idee?
-
case WM_SIZE: InvalidateRect(hWnd, NULL, TRUE); break;
das würde ich in die wndproc vom parent reinschreiben
-
window schrieb:
case WM_SIZE: InvalidateRect(hWnd, NULL, TRUE); break;
das würde ich in die wndproc vom parent reinschreiben
quatsch!! ich nehms zurück.
-
Aso, es handelt sich gar nich um nen child-window ?
Dann fusch doch ne Region zurecht und setze die mit SetWindowRgn()
oder WS_EX_LAYERED und mit SetLayeredWindowAttributes() die Transparenz einstellen.
-
Nein, jetzt in meinem Test handelt es sich um ein Standard-Hello-World Fenster, wo ich einfach den Clientbereich transparent haben möchte, was halt normal weiß ist. Hintergrund ist der, dass ich für ein Tabcontrol für jedes Tab ein Fenster erstelle, wo dann der Hintergrund transparent sein soll. Da hab' ich mir gedacht, dass ich erst einmal versuche einfach nur den Clientbereich von einem normalen Fenster transparent zu machen. Dann müsste man das ja auf die Child-Windows ebenso anwenden können. Jetzt geht es mir aber nicht mehr nur um die Child-Windows, sondern nun interessiert es mich auch, wie ich das bei einem Hauptfenster anstelle. Irgendwie muss es ja gehen, denn, wenn ich das Fenster minimiere und anschließend maximiere, dann wird es ja aktualisiert, dann muss es ja auch irgendwie beim bewegen und resizen gehen, denke ich. Nur leider finde ich da keine Möglichkeit.
-
Wenns nen Hauptfenster ist geht das mit WS_EX_LAYERED ziemlich einfach.
z.B. Einfach alles was transparent sein soll weiss zeichnen und dann mittels SetLayeredWindowAttributes() den ColorKey auf weiss setzen.Naja, irgendwie scheint mir Transparenz bei Windows nicht gescheit gelöst vor.
Die DC scheinen teilweise irgendwie den Inhalt des drunter-liegenden DCs zu übernehmen, wenn sich das drunter-liegende Fenster neugezeichnet hat. Wie das genau zusammenhängt hab ich bisher nirgendswo gefunden...Ideal wäre, wenn die DC wirklich genau an ein Fenster gebunden wären und ne Bitmap mit Alpha-Kanal drin wäre. Die WM_ERASEBKGND könnte man völlig weglassen.
Schön wäre außerdem wenn die komplette Windows-Oberfläche Double-Buffered wäre
Aber egal
-
Naja, bei SetLayeredWindowAttributes hab' ich das Problem, dass es erst ab Win2000 unterstützt wird, und ich das nicht unbedingt als Grenze haben möchte. Ich werd' dann wohl einfach noch ein wenig testen, schauen wir mal.
Vielen Dank auf jeden schonmal für die Antworten.
-
Dann wäre noch die SetWindowRgn()-Variante möglich.
Btw, evtl. interessant:
http://support.microsoft.com/gp/lifewin
-
Ja, Regions wären eine Möglichkeit, aber etwas aufwendig die Region genau auf die Childs anzupassen.
Mir geht es hier bei dem Hauptfenster jetzt nur in erster Linie darum, dass ich der Meinung, dass es irgendwie gehen muss, einen besonderen Einsatzzweck hab' ich da gar nicht, also nicht bei Hauptfenstern. Ich denke einfach nur, dass wenn ich schon die Möglichkeit habe einen Hollow-Brush zu verwenden, dass ich Windows ja dann auch irgendwie sagen können muss, dass bzw. wann der Hintergrund, der ja eigentlich nicht da sein dürfte neu gezeichnet werden muss, damit wieder der Transparenz-Effekt entsteht.
Naja, schauen wir mal.
Danke auf jeden.