none
Desktop "screenen" RRS feed

  • Allgemeine Diskussion

  • Hallo,

    mir ist leider nicht wirklich ein Sinnvoller Titel zu dem Thema eingefallen, also hier meine Frage:

    Ich möchte eine Form an den Desktop "kleben", das klappt mit SetParent (DLL Import) auch ganz gut.

    Das Problem: Windows Aero mag wohl Tranzparenz auf dem Desktop nicht so sehr und macht meine Teil-Transparente Form 100% unsichtbar, oder killt gelegentlich auch mal den Explorer. Dann wollte ich den Aero-Glas Effekt nutzen, weil die Form sowieso in dem Style werden sollte. Nur sobald ich den Desktop als Parent festlege verschwindet der Glas Effekt und meine Form wird schwarz (ist logisch, da wird es wohl auch keine Möglichkeit geben).

    Jetzt habe ich mir gedacht: Na Gut, dann nehm ich halt eine art Screenshot vom Desktop, und berechne die Transparenz manuell, so dass meine Form 100% untransparent ist, es aber Transparent wirkt (anders dürfte das ja mit der "echten" Transparenz auch nicht gehandhabt werden).

    Und da liegt mein Problem: Wie komme ich an eine Art Screenshot vom Desktop, auf dem der ohne meine Form dargestellt wird (am besten das auch nur, wenn der Desktop sich im Bereich meiner Form neu zeichnet)?

    MfG

    [Hidden]

    Dienstag, 12. Juli 2011 15:15

Alle Antworten

  • Hallo H.,

    • Wie komme ich an eine Art Screenshot vom Desktop ...

    auch, wenn mir Dein Bildschirm-Kopie-System da etwas merkwürdig vorkommt, ggf. ist folgendes dafür hilfreich:

    [Graphics.CopyFromScreen-Methode (System.Drawing)]
    http://msdn.microsoft.com/de-de/library/system.drawing.graphics.copyfromscreen.aspx

    [C# Tipps und Tricks: Spaßprogramm: Screenshot vom Desktop als Hintergrund und alle Icons löschen]
    http://csharp-tricks.blogspot.com/2010/07/spaprogramm-screenshot-vom-desktop-als.html


    ciao Frank
    Donnerstag, 14. Juli 2011 07:35
  • Hi,

    danke für die Links funktioniert aber leider nicht. Die Form wird leider mit kopiert.

    Ich hab auch versucht die Form irgendwie auszublenden, den Desktop zu kopieren und wieder einzublenden. Hat leider je nachdem was ich versucht habe auch nur dafür gesorgt, dass ich nichtmehr auf den Desktop kam, die Form wie irre geflimmert hat (hatte ich leider schon erwartet) oder es hat garnicht funktioniert.

    Wenn dir mein System merkwürdig vorkommt: Wie würdest du es denn machen? Bin gerne bereit andere Ansätze zu probieren.

    MfG

    Hidden



    Samstag, 16. Juli 2011 17:42
  • Hi,

    Du könntest eventuell mit UpdateLayeredWindow herumexperimentieren... je nachdem, was konkret Du möchtest, bekommst Du das gewünschte AlphaBlending

    http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=1822

    Viele Grüße,

      Thorsten

    Samstag, 16. Juli 2011 18:34
  • Hat leider auch nicht funktioniert. Die Form wird wieder 100% unsichtbar.

    MfG

    Hidden

    Sonntag, 17. Juli 2011 12:10
  • Hallo,

    mit Kopieren wird das nicht funktionieren, denn der Desktop ist keine statische Oberfläche.
    Aero wird erst durch den Desktop Window Manager möglich, der sich dazwischen klemmt.
    Je nachdem was Du alles anstellen willst, solltest Du Dir das API dort anschauen.

    Tim Sneath beschreibt das in Windows Vista Aero Pt. 1 - Adding Glass to a Windows Forms Application
    das Beispiel existiert dort nicht mehr, ähnlich dürfte aber sein:
    Windows Vista Aero Glass in .NET Managed Win32 Applications
    Ein API Beispiel findet sich unter: Custom Window Frame Using DWM

    Und wenn ich es mit einem teil-transparenten Formular und aktiven VisualStyles kombiniere,
    verschwindet es (unter Windows 7 SP1) nicht.

    Als Hinweis noch:
    Das Einhängen in den Windows Desktop kann zu unangenehmen Seiteneffekten führen
    was Raymond Chen in What's so special about the desktop window? beschreibt.

    Klappt das alles nicht, solltest Du evtl. mal ein reduziertes Beispiel zeigen, was Du bisher konstruiert hast.

    Gruß Elmar

    Sonntag, 17. Juli 2011 16:43
    Beantworter
  • Hallo H.,

    • Wenn dir mein System merkwürdig vorkommt: Wie würdest du es denn machen? Bin gerne bereit andere Ansätze zu probieren.

    ja, also zunächst ist es sehr gefährlich, an den Desktop als Parent zu binden, da dieser auch neu erstellt werden kann (Du hast es selber schon bemerkt), nebst anderen Problemen. Ich interpretiere mal Dein "an den Desktop 'kleben'" als "im Fenster des Desktop's bleiben". Dann würde ich da nur über die Bildschirm-Positionen arbeiten, sodass man unabhängig vom Window-Handle ist.
    Beispielsweise im groben Ansatz:

     

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Drawing.Imaging;
    
    namespace WinDesktopDemo
    {
     public partial class Form1 : Form
     {
     Rectangle arbeitsBereich;
     Button btnKopieren = new Button();
     PictureBox pictureBox = new PictureBox();
    
     public Form1()
     {
      InitializeComponent();
      arbeitsBereich = Screen.GetWorkingArea(this);
      btnKopieren.Text = "Kopieren";
      btnKopieren.Click += new EventHandler(btnKopieren_Click);
      Controls.Add(btnKopieren);
      pictureBox.Dock = DockStyle.Fill;
      pictureBox.BackColor = Color.Transparent;
      Controls.Add(pictureBox);
      this.Move += Form1_Move;
     }
    
     void btnKopieren_Click(object sender, EventArgs e)
     {
      BildschirmKopie.Kopiere(this, pictureBox);
     }
    
     public void Form1_Move(object sender, EventArgs e)
     {
      if (Width > arbeitsBereich.Width) Width = arbeitsBereich.Width;
      if (Height > arbeitsBereich.Height) Width = arbeitsBereich.Height;
      if (!arbeitsBereich.Contains(Bounds))
      FormPositionKorrigieren();
     }
    
     private void FormPositionKorrigieren()
     {
      if (Bounds.Left < arbeitsBereich.Left) Left = arbeitsBereich.Left;
      if (Bounds.Top < arbeitsBereich.Top) Top = arbeitsBereich.Top;
      if (Bounds.Right > arbeitsBereich.Right) Left -= (Bounds.Right - arbeitsBereich.Right);
      if (Bounds.Bottom > arbeitsBereich.Bottom) Top -= (Bounds.Bottom - arbeitsBereich.Bottom);
     }
     }
    
     public class BildschirmKopie
     {
     private static Bitmap bmpBildschirmKopie;
     private static Graphics graphicsBildschirmKopie;
     private const int außerhalb = 300000;
    
     public static void Kopiere(Form1 form, PictureBox pBox)
     {
      Rectangle originalBounds = form.Bounds;
      Rectangle clientRectangleBounds = form.RectangleToScreen(form.ClientRectangle);
      form.Move -= form.Form1_Move;
      form.Location = new Point(außerhalb, außerhalb);
    
      bmpBildschirmKopie = new Bitmap(clientRectangleBounds.Width,
      clientRectangleBounds.Height, PixelFormat.Format32bppArgb);
      graphicsBildschirmKopie = Graphics.FromImage(bmpBildschirmKopie);
      graphicsBildschirmKopie.CopyFromScreen(clientRectangleBounds.X,
      clientRectangleBounds.Y, 0, 0, clientRectangleBounds.Size,
      CopyPixelOperation.SourceCopy);
      pBox.Image = bmpBildschirmKopie;
      graphicsBildschirmKopie.Dispose();
    
      form.Bounds = originalBounds;
      form.Move += form.Form1_Move;
     }
     }
    }
    
    

     


    ciao Frank


    Montag, 18. Juli 2011 09:20
  • Hi,

    @Frank:

    Danke für die Ausführliche Antwort, nur auch hier leider das Problem: Die Form flimmert beim Kopieren, was nun nicht so toll ist.

     

    @Elmar:

    Danke, ich sehs mir am Wochenende mal an.

    BTW: warum markiert nen Moderator irgendwelche Antworten als "Antwort"? Woher weiß denn der Moderator ob mir die Antwort geholfen hat ...?
    Dienstag, 19. Juli 2011 17:57
  • Hallo,

    schau es Dir in Ruhe an. Und frage weiter, wenn was unklar bleibt.

    Gruß Elmar

    P. S.: Ich nehme den Antwort-Status für alle zurück...

    Die Moderation hakt schon mal länger liegen gebliebene Threads ab,
    weil viele Fragende dies vergessen - und Ordnung muss in Deutschland nun mal sein ;-)

    Dienstag, 19. Juli 2011 19:59
    Beantworter
  • Hallo H.,

    • ... Die Form flimmert beim Kopieren,

    aha, also meinst Du mit Flimmern, das kurze Weggehen und Wiederkehren der Sichtbarkeit der Form.
    Das kann man aber auch wegbekommen. Ich habe Dir mal ein anderes Beispiel über TransparencyKey ohne Form-Verschiebung gemacht (das flimmert beim Kopieren dadurch nicht mehr) :

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Drawing.Imaging;
    
    namespace WinDesktopDemo
    {
      public partial class Form1 : Form
      {
        Rectangle arbeitsBereich;
        Button btnKopieren = new Button();
        PictureBox pictureBox = new PictureBox();
    
        public Form1()
        {
          Hide(); ShowInTaskbar = false; TransparencyKey = Color.White;
          BackColor = Color.White; Application.DoEvents();
          InitializeComponent();
          arbeitsBereich = Screen.GetWorkingArea(this);
          btnKopieren.Text = "Kopieren";
          Text = "Bildschirm-Ausschnitt-Kopie";
          btnKopieren.Click += new EventHandler(btnKopieren_Click);
          Controls.Add(btnKopieren);
          pictureBox.Dock = DockStyle.Fill;
          pictureBox.BackColor = Color.White;
          Controls.Add(pictureBox);
          this.Move += Form1_Move;
          Show(); ShowInTaskbar = true;
        }
    
        void btnKopieren_Click(object sender, EventArgs e)
        {
          BildschirmKopie.Kopiere(this, pictureBox);
        }
    
        public void Form1_Move(object sender, EventArgs e)
        {
          if (Width > arbeitsBereich.Width) Width = arbeitsBereich.Width;
          if (Height > arbeitsBereich.Height) Width = arbeitsBereich.Height;
          if (!arbeitsBereich.Contains(Bounds))
            FormPositionKorrigieren();
        }
    
        private void FormPositionKorrigieren()
        {
          if (Bounds.Left < arbeitsBereich.Left) Left = arbeitsBereich.Left;
          if (Bounds.Top < arbeitsBereich.Top) Top = arbeitsBereich.Top;
          if (Bounds.Right > arbeitsBereich.Right) Left -= (Bounds.Right - arbeitsBereich.Right);
          if (Bounds.Bottom > arbeitsBereich.Bottom) Top -= (Bounds.Bottom - arbeitsBereich.Bottom);
        }
      }
    
      public class BildschirmKopie
      {
        private static Bitmap bmpBildschirmKopie;
        private static Graphics graphicsBildschirmKopie;
    
        public static void Kopiere(Form1 form, PictureBox pBox)
        {
          Rectangle originalBounds = form.Bounds;
          Rectangle clientRectangleBounds = form.RectangleToScreen(form.ClientRectangle);
          bmpBildschirmKopie = new Bitmap(clientRectangleBounds.Width,
          clientRectangleBounds.Height, PixelFormat.Format32bppArgb);
          graphicsBildschirmKopie = Graphics.FromImage(bmpBildschirmKopie);
          graphicsBildschirmKopie.CopyFromScreen(clientRectangleBounds.X,
          clientRectangleBounds.Y, 0, 0, clientRectangleBounds.Size,
          CopyPixelOperation.SourceCopy);
          pBox.Image = bmpBildschirmKopie;
          graphicsBildschirmKopie.Dispose();
        }
      }
    }
    


    ciao Frank

    Mittwoch, 20. Juli 2011 05:04
  • Hallo [Hidden],

    Ich würde nicht direkt das Dektop-Fenster als Parent setzen, sondern das Progman-Fenster.

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace TransparentDesktopWindow {
      public partial class DesktopWindow : Form {
        public DesktopWindow() {
          InitializeComponent(); // Opacity ist auf 50% gesetzt
        }
    
        private void DesktopWindow_Load(object sender, EventArgs e) {
          NativeMethods.GlueToTheDesktop(this.Handle);
        }
      }
    
      internal sealed class NativeMethods {
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    
        public static void GlueToTheDesktop(IntPtr formHandle) {
          IntPtr progmanHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Progman", "Program Manager");
          SetParent(formHandle, progmanHandle);
        }
      }
    }
    
    

    Auf meinem System (Windows 7 Ultimate mit Aero-Desktop) funktionierte dieser Code auf Anhieb. Und ich konnte auch kein Flimmern etc. feststellen. Solltest Du dennoch Probleme damit haben, probier' den Code bitte auch auf einem anderen System aus. Vielleicht hängen deine Probleme auch mit der Hardware (z.B. Grafikkarte) zusammen.

    Gruß
    Marcel

    Mittwoch, 20. Juli 2011 09:27
    Moderator
  • @Marcel:

    Progman meinte ich mit Desktop (gibts da noch was anderes?)

    Also dein Code wird bei mir leider auch 100% unsichtbar (ich habe unter InitializeComponent(); this.Opacity = 0.5; eingefügt. Oder meintest du das mit den 50% opacity anders?)

    Ich werds auf nem anderen System ausprobieren, sobald ich die Möglichkeit habe.

    @Frank:

    Eine sehr intressante Lösung, löst nur leider mein Problem nicht. Du machst ja einfach nur die Form unsichtbar, und machst dann ein Bild auf dem die Form natürlich nicht erscheint, weil sie ja unsichtbar ist. Nur wenn man das mehr als einmal macht, dann wird die Form wieder mitkopiert. Und wenn ich die vorher unsichtbar mache, flimmert es logischerweise wieder.

    Mittwoch, 20. Juli 2011 18:10
  • @Hidden:

    > Progman meinte ich mit Desktop (gibts da noch was anderes?)
    Genaugenommen ist Desktop der Parent von Progman.

    > Also dein Code wird bei mir leider auch 100% unsichtbar [...]
    Das kann ich leider nicht nachvollziehen. 
    Mir fehlen z.Z. jegliche Anhaltspunkte für eine qualifizierte Diagnose.
    Aber vielleicht gibt es unter den Lesern dieses Threads jemanden, der das bestätigen kann?

    Poste bitte einen reproduzierbaren Minimalcode hier.

    Gruß
    Marcel



    Mittwoch, 20. Juli 2011 18:33
    Moderator
  • Hallo,

    ich bezog mich in meinem ersten Beitrag und dem Warnhinweis dort auf GetDesktopWindow.

    Wie dort auch schon gesagt, klappt die Transparenz einwandfrei - ich hatte ebenfalls Opacity 50%
    und Fuchsia als Transparente Farbe - um den von Tim Sneath angesprochenen Blur-Effekt zu bewundern ;-)

    Verwende ich hier (unter Windows 7 SP1 32-Bit) Marcels Zeile so ist das Fenster ebenfalls verschwunden.

    Ansonsten ging es mir da so wie Marcel: Ohne belastbaren Code kann man wenig sagen.

    [Edit]
    Das Fenster entfleucht nicht, wenn man das Windows-7-Basis oder Klassisch Theme verwendet -
    allerdings ruckelt es beim Verschieben zum Abgewöhnen ;-)
    Lt. Spy++ scheint der Progman dann auch funktiontüchtiger zu werden.

    Da es bei Marcel auch bei Aero zu funktionieren scheint, könnten die Möglichkeiten des Grafiktreibers eine Rolle spielen.
    [/Edit]

    Gruß Elmar


    Mittwoch, 20. Juli 2011 18:59
    Beantworter
  • Hallo H.,

    • .. Du machst ja einfach nur die Form unsichtbar...

    nein, sie ist sichtbar, sie wird durch Show() zur Laufzeit sichtbar und ist nur aus einem Schönheitseffekt im Konstruktor/Anfang kurz unsichtbar gemacht. Sie ist sichtbar. Der Clientbereich der Form ist transparent. [s. mein Quellcode] Natürlich auch ohne Flimmern oder sonstiges.

     

    • ... und machst dann ein Bild auf dem die Form natürlich nicht erscheint, ...

    doch, das Bild erscheint auf der Form, ... schieb doch mal die Form ein wenig hin und her, nachdem Du auf [Kopieren] gedrückt hast :-)

     

    • ... mein Problem ...

    ich denke immer mehr, dass Du die eigentliche Anforderung noch nicht gut und vollständig genug beschrieben hast.
    Zum Beispiel das "An den Desktop kleben" ... es könnte beispielsweise [Dieses () - ist aber ebenso unsauber, weil bei SetParent eh viel viel mehr gemacht werden müsste, als das, was dort steht] gemeint sein. Nur man müsste dann wissen, was alles für Anforderungen erfüllt sein sollen. Über DesktopWindow oder Progman ist aber beides eher instabil (genannte Gründe) und deswegen würde ich das hier eher mittels C# (.NET) direkt implementieren, wie in meinem Beispiel. Zumal man ein "Progman" Fenster eh auf anderen Betriebssystemen als Windows ggf. vergeblich sucht und so inkompatible Software erstellen würde.


    ciao Frank






    Mittwoch, 20. Juli 2011 19:01
  • Hallo Elmar,

    Es könnte tatsächlich mit der Hardwareunterstützung zusammenhängen.
    Hier ein kurzes Video das (hoffentlich) zeigt, was ich hier sehe:

    https://skydrive.live.com/#!/?cid=344bc0d5b88800d3&sc=documents&uc=1&id=344BC0D5B88800D3%21104!cid=344BC0D5B88800D3&id=344BC0D5B88800D3%21227&sc=documents

    Gruß
    Marcel

    Donnerstag, 21. Juli 2011 08:31
    Moderator
  • Hallo Marcel,

    nach (zu kurzen) Schlaf, vermute ich, dass Progman unter Aero das Gnadenbrot entzogen wurde ;-)

    Wechselt man auf das angesprochene Basis-Theme, so taucht nicht nur das vorher verschwundene Fenster auf,
    er hostet als weiteres Subfenster SHELLDLL_DefView.
    Wechselt man zurück auf Aero (mit oder ohne Cartoons), verschwindet das Fenster
    und wird einem WorkW zugeordnet zusammen mit SHELLDLL_DefView (und Progman ist kinderlos).

    Wie man Google entnehmen kann fällt da der eine oder andere ältere Code auf die Nase.
    Für einen Verwendungszweck: http://www.midiox.com/html/dtcoding.htm (dürfte heute schief gehen)

    Gruß Elmar

    Donnerstag, 21. Juli 2011 09:31
    Beantworter
  • Hi,

    ich wollte mich nochmal melden, nachdem ich in letzter Zeit recht wenig von selbiger zur Verfügung hatte.

    Hat noch irgendwer ne Idee?

    MfG
    Hidden

    Sonntag, 31. Juli 2011 15:08
  • Hallo Hidden

    weiterkommen wir nur - nach Marcels und meiner Meinung -,
    wenn Du etwas mehr von dem offenbarst, was Du mit Deinem Projekt vorhast.

    Gruß Elmar

    Sonntag, 31. Juli 2011 15:42
    Beantworter