Screenshot des Desktophintergrundes

  • VB.NET

Es gibt 47 Antworten in diesem Thema. Der letzte Beitrag () ist von BjöNi.

    Screenshot des Desktophintergrundes

    Hallo Leute,

    ich brauche bitte Hilfe.
    Ziel ist es, einen Screenshot zu machen, der ausschließlich den Desktop zeigt - also ohne bereits geöffnete Fenster etc. - sozusagen das "Windows-Hintergrundbild".
    Ein Projekt habe ich mal drangehängt (kompilierte EXE ist auch dabei im Release-Ordner).

    Erster Ansatz war, über Shell32 den Desktop zu togglen, dann den Screenshot zu machen und wieder zu togglen.
    Das geht auch, aber ich hätte sehr gern eine Variante ohne togglen.

    Wie komme ich bitte direkt an den Desktop heran (ohne togglen), wenn Programmfenster darüber liegen?
    Ein weiterer Versuch über die API mit "GetDesktopWindow" brachte mir auch nicht das Desktopfenster ;( ..
    Hilfe...

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Function CaptureDesktopImage() As Image
    2. ' Verweis auf Shell32 muss bestehen
    3. Dim ShellReference As Shell32.Shell = Nothing
    4. Dim WorkingImage As Bitmap = Nothing
    5. Dim WorkingGraphics As Graphics = Nothing
    6. Dim TargetArea As Rectangle = Screen.PrimaryScreen.WorkingArea
    7. ShellReference = New Shell32.Shell()
    8. ShellReference.ToggleDesktop()
    9. System.Threading.Thread.Sleep(200)
    10. WorkingImage = New Bitmap(TargetArea.Width, TargetArea.Height)
    11. WorkingGraphics = Graphics.FromImage(WorkingImage)
    12. WorkingGraphics.CopyFromScreen(TargetArea.X, TargetArea.X, 0, 0, TargetArea.Size)
    13. ShellReference.ToggleDesktop()
    14. Return DirectCast(WorkingImage.Clone(), Image)
    15. End Function



    LG,
    Bruno
    Dateien
    • DeskShot.zip

      (100,39 kB, 86 mal heruntergeladen, zuletzt: )
    Ich denke mal, das geht nicht, und wenn, dann nur mit massivem API-Aufwand.
    Was Du könntest:
    Du könntest Dir das Bildschirm-Hintergrundbild holen.
    Du könntest Dir die TaskBar holen,
    Du könntest Dir die Icons der Desktop-Symbole holen (deren Position ggf. auch)
    und daraus Dein Bild zusammensetzen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Du könntest Dir das Bildschirm-Hintergrundbild holen.

    Danke erstmal!

    Weitere Informationen, die vielleicht wichtig sind:
    Ich habe eine Methode, die den Mittelwert aller Farben (als RGB-Kanäle) einer Bitmap bildet (funktioniert schon).
    Als Vorlage für die Mittelwertbildung brauche ich entweder den Bildschirmhintergrund oder eben die Farbe - falls der Anwender kein Hintergrundbild verwendet und nur einfarbig darstellt.

    LG,
    Bruno

    diylab schrieb:

    die vielleicht wichtig sind:
    Was hat das eine mit dem anderen zu tun?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    diylab schrieb:

    die vielleicht wichtig sind:
    Was hat das eine mit dem anderen zu tun?

    Na ich brauche eben den Windows-Hintergrund zum ermitteln der Durchschnittsfarben :) .
    Darum die Idee mit dem Screenshot.

    Aber nun probiere ich die API 'SystemParametersInfo // SPI_GETDESKWALLPAPER'.
    Geht. Zumindest unter Win7 gibt er mir den Pfad zum Hintergrundbild.
    Ob es unter XP auch geht? Habe ich leider nicht.

    Nun brauche ich nur noch die Hintergrundfarbe, falls der User kein Hintergrundbild verwendet und alle Probleme wären gelöst.
    Mal gucken, ob 'SystemParametersInfo' das auch hergibt...

    LG,
    Bruno

    diylab schrieb:

    Pfad zum Hintergrundbild
    Vielleicht suchst Du mal gezielt in der Registry.
    Setze ein Bild, das Du kennst, und suche dessen Name / Pfad (getrennt(!!!)) in der Registry.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    diylab schrieb:

    Pfad zum Hintergrundbild
    Vielleicht suchst Du mal gezielt in der Registry.
    Setze ein Bild, das Du kennst, und suche dessen Name / Pfad (getrennt(!!!)) in der Registry.

    Joooo :P !

    Ok - bei Win7 habe ich nun alle Infos, die ich brauche:

    VB.NET-Quellcode

    1. Private Function GetCurrentWallpaper() As String
    2. Dim rkWallPaper As RegistryKey = Registry.CurrentUser.OpenSubKey("Control Panel\Desktop", False)
    3. Dim WallpaperPath As String = rkWallPaper.GetValue("WallPaper").ToString()
    4. rkWallPaper.Close()
    5. Return WallpaperPath
    6. End Function
    7. Private Function GetCurrentBackColor() As String
    8. Dim rkBackColor As RegistryKey = Registry.CurrentUser.OpenSubKey("Control Panel\Colors", False)
    9. Dim BackColorPath As String = rkBackColor.GetValue("Background").ToString()
    10. rkBackColor.Close()
    11. Return BackColorPath
    12. End Function


    Ob das auch bei XP, Vista & Win8 so ist - keine Ahnung - muss man probieren..
    Also alles chic - Problem gelöst - danke für den Denkanstoß Rod!

    Der im Eingangspost beschriebene Desktop-Screenshot funktioniert gut, vielleicht kann der Thread so bestehen bleiben, irgend jemand kanns vielleicht gebrauchen?

    LG,
    Bruno
    Bei Win8 ist es so, habs gerade ausprobiert.

    Wenn man allerdings mehrere Bilder als Diashow auswählt, dann ist dort ein Pfad zu einem Theme (bei mir unter "C:\Users\Niklas\AppData\Roaming\Microsoft\Windows\Themes" eine Datei namens "TranscodedWallpaper" ohne Dateiendung). Weiß aber nicht, wie die aufgebaut ist.

    BjöNi schrieb:

    Wenn man allerdings mehrere Bilder als Diashow auswählt, dann ist dort ein Pfad zu einem Theme (bei mir unter "C:\Users\Niklas\AppData\Roaming\Microsoft\Windows\Themes" eine Datei namens "TranscodedWallpaper" ohne Dateiendung). Weiß aber nicht, wie die aufgebaut ist.

    Ooops :S ..
    Jemand eine Idee?

    LG,
    Bruno

    PS: Danke für Ausprobieren unter Win8!

    Done :D .

    Macht was es soll - zumindest unter Win7.
    Screenshot vom Testprogramm anbei. Die .EXE auch.
    Wenn Jemand netter weise mal unter XP, Vista und Win8 probieren würde?



    LG,
    Bruno


    Edit by Manschula: Programmdownloads außerhalb des Showrooms sind nicht zulässig --> Anhang entfernt

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Manschula“ ()

    nafets3646 schrieb:

    Poste doch einfach deinen Code, dann können wir es testen ;).


    Klaro - warum nicht!

    Hier mein Original:
    Spoiler anzeigen

    Quellcode

    1. using Microsoft.Win32;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Drawing;
    5. using System.Drawing.Drawing2D;
    6. using System.Linq;
    7. using System.Windows.Forms;
    8. namespace AverageColor
    9. {
    10. public partial class Form1 : Form
    11. {
    12. public Form1()
    13. {
    14. InitializeComponent();
    15. label1.Text = GetCurrentWallpaperPath();
    16. panel1.BackColor = GetCurrentBackColor();
    17. // Gibt es ein Hintergrundbild?
    18. if (GetCurrentWallpaper() != null)
    19. {
    20. panel2.BackColor = AVGColor(GetCurrentWallpaper());
    21. }
    22. else
    23. {
    24. panel2.BackColor = GetCurrentBackColor();
    25. }
    26. pictureBox1.BackgroundImage = GetCurrentWallpaper();
    27. }
    28. /// <summary>
    29. /// Wallpaper Pfad
    30. /// </summary>
    31. /// <returns></returns>
    32. private String GetCurrentWallpaperPath()
    33. {
    34. RegistryKey rkWallPaper = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", false);
    35. string WallpaperPath = rkWallPaper.GetValue("WallPaper").ToString();
    36. rkWallPaper.Close();
    37. return WallpaperPath;
    38. }
    39. /// <summary>
    40. /// Wallpaper
    41. /// </summary>
    42. /// <returns></returns>
    43. private Image GetCurrentWallpaper()
    44. {
    45. RegistryKey rkWallPaper = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", false);
    46. string WallpaperPath = rkWallPaper.GetValue("WallPaper").ToString();
    47. rkWallPaper.Close();
    48. try
    49. {
    50. Image img = Image.FromFile(WallpaperPath);
    51. return img;
    52. }
    53. catch
    54. {
    55. return null;
    56. }
    57. }
    58. /// <summary>
    59. /// Desktop Hintergrundfarbe
    60. /// </summary>
    61. /// <returns></returns>
    62. private Color GetCurrentBackColor()
    63. {
    64. RegistryKey rkBackColor = Registry.CurrentUser.OpenSubKey("Control Panel\\Colors", false);
    65. string BackColorString = rkBackColor.GetValue("Background").ToString();
    66. rkBackColor.Close();
    67. List<int> RGB = BackColorString.Split(' ').ToList().ConvertAll<int>(s => Convert.ToInt32(s));
    68. return Color.FromArgb(RGB[0], RGB[1], RGB[2]);
    69. }
    70. /// <summary>
    71. /// Durchschnittsfarbe einer Bitmap
    72. /// </summary>
    73. /// <param name="Wallpaper"></param>
    74. /// <returns></returns>
    75. private Color AVGColor(Image Wallpaper)
    76. {
    77. using (Bitmap bm = new Bitmap(Wallpaper))
    78. {
    79. Bitmap bmp = new Bitmap(1, 1);
    80. using (Graphics g = Graphics.FromImage(bmp))
    81. {
    82. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    83. g.DrawImage(bm, new Rectangle(0, 0, 1, 1));
    84. }
    85. Color pixel = bmp.GetPixel(0, 0);
    86. return Color.FromArgb(pixel.R, pixel.G, pixel.B);
    87. }
    88. }
    89. }
    90. }



    Und da die Übersetzung in VB.NET (über developerfusion.com):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports Microsoft.Win32
    2. Imports System.Collections.Generic
    3. Imports System.Drawing
    4. Imports System.Drawing.Drawing2D
    5. Imports System.Linq
    6. Imports System.Windows.Forms
    7. Namespace AverageColor
    8. Public Partial Class Form1
    9. Inherits Form
    10. Public Sub New()
    11. InitializeComponent()
    12. label1.Text = GetCurrentWallpaperPath()
    13. panel1.BackColor = GetCurrentBackColor()
    14. ' Gibt es ein Hintergrundbild?
    15. If GetCurrentWallpaper() IsNot Nothing Then
    16. panel2.BackColor = AVGColor(GetCurrentWallpaper())
    17. Else
    18. panel2.BackColor = GetCurrentBackColor()
    19. End If
    20. pictureBox1.BackgroundImage = GetCurrentWallpaper()
    21. End Sub
    22. ''' <summary>
    23. ''' Wallpaper Pfad
    24. ''' </summary>
    25. ''' <returns></returns>
    26. Private Function GetCurrentWallpaperPath() As [String]
    27. Dim rkWallPaper As RegistryKey = Registry.CurrentUser.OpenSubKey("Control Panel\Desktop", False)
    28. Dim WallpaperPath As String = rkWallPaper.GetValue("WallPaper").ToString()
    29. rkWallPaper.Close()
    30. Return WallpaperPath
    31. End Function
    32. ''' <summary>
    33. ''' Wallpaper
    34. ''' </summary>
    35. ''' <returns></returns>
    36. Private Function GetCurrentWallpaper() As Image
    37. Dim rkWallPaper As RegistryKey = Registry.CurrentUser.OpenSubKey("Control Panel\Desktop", False)
    38. Dim WallpaperPath As String = rkWallPaper.GetValue("WallPaper").ToString()
    39. rkWallPaper.Close()
    40. Try
    41. Dim img As Image = Image.FromFile(WallpaperPath)
    42. Return img
    43. Catch
    44. Return Nothing
    45. End Try
    46. End Function
    47. ''' <summary>
    48. ''' Desktop Hintergrundfarbe
    49. ''' </summary>
    50. ''' <returns></returns>
    51. Private Function GetCurrentBackColor() As Color
    52. Dim rkBackColor As RegistryKey = Registry.CurrentUser.OpenSubKey("Control Panel\Colors", False)
    53. Dim BackColorString As String = rkBackColor.GetValue("Background").ToString()
    54. rkBackColor.Close()
    55. Dim RGB As List(Of Integer) = BackColorString.Split(" "C).ToList().ConvertAll(Of Integer)(Function(s) Convert.ToInt32(s))
    56. Return Color.FromArgb(RGB(0), RGB(1), RGB(2))
    57. End Function
    58. ''' <summary>
    59. ''' Durchschnittsfarbe einer Bitmap
    60. ''' </summary>
    61. ''' <param name="Wallpaper"></param>
    62. ''' <returns></returns>
    63. Private Function AVGColor(Wallpaper As Image) As Color
    64. Using bm As New Bitmap(Wallpaper)
    65. Dim bmp As New Bitmap(1, 1)
    66. Using g As Graphics = Graphics.FromImage(bmp)
    67. g.InterpolationMode = InterpolationMode.HighQualityBicubic
    68. g.DrawImage(bm, New Rectangle(0, 0, 1, 1))
    69. End Using
    70. Dim pixel As Color = bmp.GetPixel(0, 0)
    71. Return Color.FromArgb(pixel.R, pixel.G, pixel.B)
    72. End Using
    73. End Function
    74. End Class
    75. End Namespace



    Im Form braucht ihr ein Label, 2 Panele und eine PictureBox.


    LG,
    Bruno
    Ich habe gerade mal versucht, das alles möglichst übersichtlich in eine Methode zu gießen, jedoch kann man dann das Wallpaper solange nicht ändern, bis ich das Programm geschlossen habe. Weiß vielleicht jemand, woran das liegen könnte?
    Code:

    C-Quellcode

    1. public class WallpaperHelper
    2. {
    3. public static Boolean TryGetWallpaper(ref Image Wallpaper)
    4. {
    5. using (RegistryKey WallpaperKey = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", false))
    6. {
    7. FileInfo WallpaperFile = new FileInfo(WallpaperKey.GetValue("Wallpaper").ToString());
    8. WallpaperKey.Close();
    9. if (WallpaperFile.Exists)
    10. {
    11. Wallpaper = Image.FromFile(WallpaperFile.FullName);
    12. return true;
    13. }
    14. return false;
    15. }
    16. }
    17. }
    Hab hier mal was gefunden, was mit der WinAPI funktioniert. Gibt bei einem einfachen Wallpaper den Pfad der Quelldatei zurück, bei einer Diashow den Pfad zur TranscodedWallpaper.
    „Was daraus gefolgert werden kann ist, dass jeder intelligentere User sein Geld lieber für Bier ausgibt, um einen schönen Rausch zu haben, und nicht dieses Ranzprodukt.“

    -Auszug aus einer Unterhaltung über das iPhone und dessen Vermarktung.

    nafets3646 schrieb:

    ..jedoch kann man dann das Wallpaper solange nicht ändern, bis ich das Programm geschlossen habe.

    Du müsstest m.M. nach das Bild per Stream lesen, dann kann es auch verändert werden.
    In meinem Fall geht es so:

    c#

    C-Quellcode

    1. /// <summary>
    2. /// Get Wallpaper Image
    3. /// </summary>
    4. /// <returns></returns>
    5. private Image GetCurrentWallpaper()
    6. {
    7. RegistryKey rkWallPaper = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", false);
    8. string WallpaperPath = rkWallPaper.GetValue("WallPaper").ToString();
    9. rkWallPaper.Close();
    10. Image ReturnImage = null;
    11. if (File.Exists(WallpaperPath))
    12. {
    13. StreamReader reader = new StreamReader(WallpaperPath);
    14. ReturnImage = Image.FromStream(reader.BaseStream);
    15. reader.Close();
    16. }
    17. return ReturnImage;
    18. }


    VB

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Get Wallpaper Image
    3. ''' </summary>
    4. ''' <returns></returns>
    5. Private Function GetCurrentWallpaper() As Image
    6. Dim rkWallPaper As RegistryKey = Registry.CurrentUser.OpenSubKey("Control Panel\Desktop", False)
    7. Dim WallpaperPath As String = rkWallPaper.GetValue("WallPaper").ToString()
    8. rkWallPaper.Close()
    9. Dim ReturnImage As Image = Nothing
    10. If File.Exists(WallpaperPath) Then
    11. Dim reader As New StreamReader(WallpaperPath)
    12. ReturnImage = Image.FromStream(reader.BaseStream)
    13. reader.Close()
    14. End If
    15. Return ReturnImage
    16. End Function


    LG,
    Bruno

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „diylab“ ()

    Ok, danke für den Tipp, das wusste ich noch gar nicht :D.
    Meine Methode sieht jetzt jedenfalls so aus, falls es noch jemanden interessiert:
    VB

    VB.NET-Quellcode

    1. Imports Microsoft.Win32
    2. Imports System.IO
    3. Public Class WallpaperHelper
    4. ''' <summary>
    5. ''' Gibt das aktuelle Wallpaper des Systems aus.
    6. ''' Der Rückgabewert gibt an, ob ein Wallpaper gefunden wurde.
    7. ''' </summary>
    8. ''' <param name="Wallpaper">Dieser Wert gibt bei erfolgreicher Suche das Wallpaper aus.</param>
    9. Public Shared Function TryGetWallpaper(ByRef Wallpaper As Image) As Boolean
    10. Using WallpaperKey As RegistryKey = Registry.CurrentUser.OpenSubKey("Control Panel\Desktop", False)
    11. Dim WallpaperFile As New FileInfo(WallpaperKey.GetValue("Wallpaper").ToString())
    12. WallpaperKey.Close()
    13. If WallpaperFile.Exists Then
    14. Using WallpaperStreamReader As New StreamReader(WallpaperFile.OpenRead())
    15. Wallpaper = Image.FromStream(WallpaperStreamReader.BaseStream)
    16. Return True
    17. End Using
    18. End If
    19. Wallpaper = Nothing
    20. Return False
    21. End Using
    22. End Function
    23. End Class
    C#

    C-Quellcode

    1. using Microsoft.Win32;
    2. using System.IO;
    3. public class WallpaperHelper
    4. {
    5. /// <summary>
    6. /// Gibt das aktuelle Wallpaper des Systems aus.
    7. /// Der Rückgabewert gibt an, ob ein Wallpaper gefunden wurde.
    8. /// </summary>
    9. /// <param name="Wallpaper">Dieser Wert gibt bei erfolgreicher Suche das Wallpaper aus.</param>
    10. public static Boolean TryGetWallpaper(out Image Wallpaper)
    11. {
    12. using (RegistryKey WallpaperKey = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", false))
    13. {
    14. FileInfo WallpaperFile = new FileInfo(WallpaperKey.GetValue("Wallpaper").ToString());
    15. WallpaperKey.Close();
    16. if (WallpaperFile.Exists)
    17. {
    18. using (StreamReader WallpaperStreamReader = new StreamReader(WallpaperFile.OpenRead()))
    19. {
    20. Wallpaper = Image.FromStream(WallpaperStreamReader.BaseStream);
    21. return true;
    22. }
    23. }
    24. Wallpaper = null;
    25. return false;
    26. }
    27. }
    28. }

    nafets3646 schrieb:

    Meine Methode sieht jetzt jedenfalls so aus, falls es noch jemanden interessiert

    Dieser Thread ist sicher für einige Leute interessant, die über Google kommen.
    Auf den ersten Blick sind einige Themen vorhanden, trotzdem hängt alles miteinander zusammen.
    Auch die Methode zum ermitteln der Durchschnittsfarbe ist recht ungewöhnlich und schnell ;).

    Jetzt brauche ich nur noch etwas gescheites zum ermitteln einer Komplementärfarbe (oder noch besser ausgedrückt, einer Kontrastfarbe zur einer vorhandenen Farbe).
    Solche Sachen wie "Xor &HFFFFFF" scheiden aus, das versagt bei grau.

    LG,
    Bruno