DrawText auf Desktop einblenden?



  • Hallo,
    ich experimentiere gerade mit einer Art Status-Einblendung für ein Tray-Programm ohne sichtbares Fenster und schreibe dazu bei einem Ereignis direkt auf den Desktop(die Schrift habe ich...

    SetBkMode(desktop_hdc,TRANSPARENT);
    DrawText(desktop_hdc, status_text, -1,&desktop_rect, DT_NOCLIP);
    

    Wenn das Ereignis vorbei ist, entferne ich die Einblendung mit...

    InvalidateRect(NULL, &desktop_rect, true);
    

    Nun sieht das ehrlich gesagt etwas dröge aus bzw. ob man die Schrift sieht, hängt auch von unvorhersehbaren Faktoren wie dem Hintergrund ab. Daher meine Frage: Lässt sich diese WinAPI-Funktion irgendwie aufpeppen? Also z.B. eine kontrastreiche Kontur um die Schrift oder ein Farbverlauf hinzufügen?

    Kann man auf diese Weise geschriebenen Text irgendwie ein- und ausblenden(also nicht An/Aus, sondern langsam einblenden und auch langsam wieder ausblenden)?

    Da ich direkt auf dem Desktop "male", kann der Status-Text jederzeit überschrieben werden. Ist es in so einem Fall OK, wenn ich einen Timer benutze, um z.B. in 10ms-Intervallen den Text erneut mit DrawText zu zeichnen, damit er bis zum Ende des Ereignis sicher im Vordergrund zu sehen ist?

    Viele Grüße,
    GrandSlam



  • eine sauberer Lösung wäre ein Layered Window, das an die entsprechende Position gesetzt wird. Animationen musst selber erstellen. Für die Textdarstellung würde ich GDI+ verwenden, da man hier mehr Optionen hat.



  • Hallo layeredWnd,

    vielen Dank für Deine Tipps, das mit GDI+ klappt sehr gut und ich finde, dass man damit schon sehr schöne Effekte erzielen kann.

    Beim Thema layered window habe ich einige Probleme:

    hWnd = CreateWindow(szWindowClass, szTitle, WS_EX_LAYERED | WS_EX_TRANSPARENT,
          0, 0, 500, 500, NULL, NULL, hInstance, NULL);
       if (hWnd==NULL)
       {
          return FALSE;
       }
    	HDC mein_hdc = GetDC(hWnd);
    	Graphics graphics(mein_hdc); 
    	Pen pen(Color(255, 0, 0, 255));
    	graphics.DrawLine(&pen, 0, 0, 500, 500); 
    	bool test = UpdateLayeredWindow(hWnd,NULL,NULL,NULL,NULL,NULL,RGB(0,0,0),NULL,ULW_COLORKEY);
    

    Wenn ich das Fenster normal erzeuge(WS_VISIBLE), wird das Fenster inklusive der mit DrawLine() gezeichnete Test-Linie angezeigt. Sobald ich jedoch ein layered window erzeugen möchte, wird gar nichts mehr angezeigt! Ich habe die meisten Parameter bei UpdateLayeredWindow() auf NULL gesetzt, weil ich das erst mal mit statischem Inhalt testen wollte und ich die Erklärungen bei MSDN so verstanden hatte, dass man z.B. Position, Größe, hdcSrc, etc. nur benötigt, wenn sich die Parameter und der Inhalt des layered window später noch ändern. Ich habe auch Tests mit hdcSrc(via CreateCompatibleDC() und dann darauf die DrawLine()-Funktion angewendet) sowie einigen anderen Parametern durchgeführt, aber die Test-Linie wurde dennoch nicht angezeigt. Wenn ich nach UpdateLayeredWindow() ein ShowWindow(hWnd, SW_SHOW) hintendran hänge, wird mir ein normales Fenster mit weißem Hintergrund ohne die selbst gezeichnete Linie angezeigt. 😕

    Die bool-Variable test ist bei UpdateLayeredWindow() FALSE, ich weiß nur leider nicht warum. Ich bin mir nicht mal sicher, ob die Reihenfolge so richtig und ausreichend ist(CreateWindow()->GDI-Zeugs auf dem HDC des layered window durchführen->UpdateLayeredWindow())...

    Viele Grüße,
    GrandSlam



  • Ich frage mich gerade eher, warum noch ein LayeredWindow verwendet wird, wenn mit GDI+ bereits mit Transparenz gemalt werden kann.



  • Hallo Youka,

    ich hatte layeredWnd so verstanden, dass ein layered window im Gegensatz zu meinem Vorhaben(Timer, welcher den Status-Text z.B. alle 50ms direkt auf dem Desktop-HDC erneuert) eine "saubere" Lösung sei. Daher habe ich versucht das Umzusetzen. Es geht mir darum, dass nur die Status-Meldung in Form eines transparenten Textes bis zum Ende eines Ereignisses vor allen anderen Fenstern zu sehen ist und nicht durch irgendwelche anderen Fenster unvorhersehbar teilweise oder ganz "übermalt" wird, so wie es jetzt der Fall ist. Die Status-Meldung soll auch nicht andere Anwendungen behindern(also Mausklicks ignorieren).
    Wenn ich das richtig verstanden habe, gibt es auch noch Overlay-Einblendungen, die direkt über die Grafikkarte gehen. Mit denen will ich natürlich nicht konkurrieren, mir reicht es, wenn meine Status-Meldung stets vor ganz normalen Fenster-Anwendungen wie Schreibprogrammen, Browsern oder Email-Programmen zu sehen ist.

    Viele Grüße,
    GrandSlam



  • Zuerst einmal: CreateWidnowEx(+RegisterClassEx) verwenden! Der erste Parameter ist dann (WS_EX_LAYERED|WS_EX_TRANSPARENT). Für dwStyle würde ich WS_POPUP empfehlen, weil dieses Fenster dann über allen anderen liegt und zudem das Client area dem Window area entspricht.
    Bei UpdateLayeredWindow() muss, soweit ich weiß, mindestens einmal die Größe angeben werden. Der einfach halber, würde ich pptDst(<-GetWindowRect), psize und pptSrc (<-POINT={0,0}) immer angeben.





  • Bleibt nur noch die Frage wie man das Fenster hinter allen anderen Top-Level Fenstern hält, und idealerweise auch sichtbar hält wenn jmd. den "show desktop" Shortcut/Button drückt.



  • hustbaer schrieb:

    Bund idealerweise auch sichtbar hält wenn jmd. den "show desktop" Shortcut/Button drückt.

    WS_EX_TOPMOST



  • Scheinbar müssen gewisse Parameter angegeben werden, auch wenn in der Doku was von optional steht.

    http://www.c-plusplus.net/forum/312705-full



  • topmost schrieb:

    hustbaer schrieb:

    Bund idealerweise auch sichtbar hält wenn jmd. den "show desktop" Shortcut/Button drückt.

    WS_EX_TOPMOST

    hustbaer schrieb:

    Bleibt nur noch die Frage wie man das Fenster hinter allen anderen Top-Level Fenstern hält, und idealerweise auch sichtbar hält wenn jmd. den "show desktop" Shortcut/Button drückt.

    Nein, gerade nicht WS_EX_TOPMOST 🙄



  • hustbaer schrieb:

    topmost schrieb:

    hustbaer schrieb:

    Bund idealerweise auch sichtbar hält wenn jmd. den "show desktop" Shortcut/Button drückt.

    WS_EX_TOPMOST

    hustbaer schrieb:

    Bleibt nur noch die Frage wie man das Fenster hinter allen anderen Top-Level Fenstern hält, und idealerweise auch sichtbar hält wenn jmd. den "show desktop" Shortcut/Button drückt.

    Nein, gerade nicht WS_EX_TOPMOST 🙄

    Woher diese Forderung? Wenn er auf den Desktop zeichnet, übermalt er ja auch alle Fenster.



  • Uff.
    Mag sein dass ich das jetzt falsch verstanden habe.
    In dem Fall das 🙄 bitte postwendend an mich zurück.

    Ich hatte angenommen dass er meint dass er auf das Desktop-Fenster zeichnet, also das Ding was halt den Desktophintergrund malt. Das mit den Icons drauf. Und wenn man da draufmalt, dann bleibt das - sofern ich mich richtig erinnere - immer hübsch hinter allen Fenstern.

    Wobei ich mir jetzt nicht mehr so sicher bin. Wenn er wirklich etwas über allem anderen einblenben will, so ala Overlay, dann natürlich WS_EX_TOPMOST.


Anmelden zum Antworten