2009-06-30 6 views

답변

87

여기에 내가 년이 전에 쓴 응용 프로그램에서 빠지게 클래스입니다 :

public sealed class Wallpaper 
{ 
    Wallpaper() { } 

    const int SPI_SETDESKWALLPAPER = 20; 
    const int SPIF_UPDATEINIFILE = 0x01; 
    const int SPIF_SENDWININICHANGE = 0x02; 

    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); 

    public enum Style : int 
    { 
     Tiled, 
     Centered, 
     Stretched 
    } 

    public static void Set(Uri uri, Style style) 
    { 
     System.IO.Stream s = new System.Net.WebClient().OpenRead(uri.ToString()); 

     System.Drawing.Image img = System.Drawing.Image.FromStream(s); 
     string tempPath = Path.Combine(Path.GetTempPath(), "wallpaper.bmp"); 
     img.Save(tempPath, System.Drawing.Imaging.ImageFormat.Bmp); 

     RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true); 
     if (style == Style.Stretched) 
     { 
      key.SetValue(@"WallpaperStyle", 2.ToString()); 
      key.SetValue(@"TileWallpaper", 0.ToString()); 
     } 

     if (style == Style.Centered) 
     { 
      key.SetValue(@"WallpaperStyle", 1.ToString()); 
      key.SetValue(@"TileWallpaper", 0.ToString()); 
     } 

     if (style == Style.Tiled) 
     { 
      key.SetValue(@"WallpaperStyle", 1.ToString()); 
      key.SetValue(@"TileWallpaper", 1.ToString()); 
     } 

     SystemParametersInfo(SPI_SETDESKWALLPAPER, 
      0, 
      tempPath, 
      SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); 
    } 
} 

내가 광범위하게 그것을 테스트하지 않은, 그래서 당신의 자신의 위험에 사용합니다.

+0

이것은 BMP 파일 만 설정합니다. JPEG를 설정하려면 어떻게해야합니까? – Sauron

+1

윈도우가 jpeg를 벽지로 지원하는지 확실하지 않은 경우 ... 벽지로 설정하기 전에 bmp로 다른 이미지를 변환합니다 (올바른 경우 나 잘못 입력 했음). 코드 변환을 수행해야하는 경우 –

+5

사용하고 있습니다. 이 jpegs에 대 한 그냥 괜 찮 아 요. 위의 코드에서 bmp가 호출 되었기 때문에이를 제한하지 않기 때문입니다. * 아마도 * 다른 사람들뿐만 아니라 png와 gif에서도 작동 할 것입니다. 그러나 나는 그것을 확인하지 않았습니다. –

-2

GIF를위한 변경 (tweaking) 닐 N의 대답 :

마지막으로
using Microsoft.Win32; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Drawing; 
using System.IO; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 

프로젝트를 마우스 오른쪽 클릭, 어셈블리 및 프레임 워크 (참조를 추가하고 :

private const int SPI_SETDESKWALLPAPER = 20; 
private const int SPIF_UPDATEINIFILE = 0x01; 
private const int SPIF_SENDWININICHANGE = 0x02; 

[DllImport("user32.dll", CharSet = CharSet.Auto)] 
private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); 

public enum Style : int 
{ 
    Tiled, 
    Centered, 
    Stretched 
} 

/// <summary> 
/// Loops numFrames times, animating the desktop background as the given gif. 
/// Remember this will sorta bog down your computer, and probably isn't best to be running 24/7. 
/// If numFrames is negative this will loop forever 
/// </summary> 
/// <param name="gifPath">The gif to be animated</param> 
/// <param name="transparencyReplace">If the gif has transparency, it will be "replaced" with this color.</param> 
/// <param name="framesPerSecond">How many frames to play per second. This is a max: most likely it will be a little slower than this especially at first.</param> 
/// <param name="style">Whether to tile, center, or stretch each gif frame as it's played.</param> 
/// <param name="numFrames">The number of frames to play. If negative, this method will loop forever.</param> 
public static void SetDesktopBackgroundAsGifAsync(string gifPath, System.Drawing.Color transparencyReplace, int framesPerSecond, Style style, int numFrames) 
{ 
    Thread workerThread = new Thread(() => SetDesktopBackgroundAsGif(gifPath, transparencyReplace, framesPerSecond, style, numFrames)); 
    workerThread.Start(); 
} 

/// <summary> 
/// Loops numFrames times, animating the desktop background as the given gif. 
/// Remember this will sorta bog down your computer, and probably isn't best to be running 24/7. 
/// If num frames is negative this will loop forever. 
//// <summary> 
/// <param name="gifPath">The gif to be animated</param> 
/// <param name="backgroundImage">Image to render the gif on top of (because of transparency)</param> 
/// <param name="framesPerSecond">How many frames to play per second. This is a max: most likely it will be a little slower than this.</param> 
/// <param name="style">Whether to tile, center, or stretch each gif frame as it's played.</param> 
/// <param name="numFrames">The number of frames to play. If negative, this method will loop forever.</param> 
public static void SetDesktopBackgroundAsGifAsync(string gifPath, System.Drawing.Image backgroundImage, int framesPerSecond, Style style, int numFrames) 
{ 
    Thread workerThread = new Thread(() => SetDesktopBackgroundAsGif(gifPath, backgroundImage, framesPerSecond, style, numFrames)); 
    workerThread.Start(); 
} 

/// <summary> 
/// Loops numFrames times, animating the desktop background as the given gif. 
/// Remember this will sorta bog down your computer, and probably isn't best to be running 24/7. 
/// if numFrames is negative this will loop forever 
/// </summary> 
/// <param name="gifPath">The gif to be animated</param> 
/// <param name="transparencyReplace">If the gif has transparency, it will be "replaced" with this color.</param> 
/// <param name="framesPerSecond">How many frames to play per second. This is a max: most likely it will be a little slower than this.</param> 
/// <param name="style">Whether to tile, center, or stretch each gif frame as it's played.</param> 
/// <param name="numFrames">The number of frames to play. If negative, this method will loop forever.</param> 
public static void SetDesktopBackgroundAsGif(string gifPath, System.Drawing.Color transparencyReplace, int framesPerSecond, Style style, int numFrames) 
{ 
    if (!File.Exists(gifPath)) 
     throw new Exception("Given gif: '" + gifPath + "' not found"); 

    FileStream gifFile = new FileStream(gifPath, FileMode.Open); 

    GifBitmapDecoder gifDecoder = new GifBitmapDecoder(gifFile, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); 

    if (gifDecoder.Frames.Count == 0) 
     throw new Exception("No frames in given gif"); 

    Bitmap backgroundImage = new Bitmap(gifDecoder.Frames[0].PixelWidth, gifDecoder.Frames[0].PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 

    using(Graphics g = Graphics.FromImage(backgroundImage)) 
    { 
     g.FillRectangle(new System.Drawing.SolidBrush(transparencyReplace), 0, 0, gifDecoder.Frames[0].PixelWidth, gifDecoder.Frames[0].PixelHeight); 
    } 

    gifFile.Close(); 

    SetDesktopBackgroundAsGif(gifPath, backgroundImage, framesPerSecond, style, numFrames); 
} 

/// <summary> 
/// Loops infinitely, animating the desktop background as the given gif. 
/// Remember this will sorta bog down your computer, and probably isn't best to be running 24/7. 
/// </summary> 
/// <param name="gifPath">The gif to be animated</param> 
/// <param name="backgroundImage">Image to render the gif on top of (because of transparency)</param> 
/// <param name="framesPerSecond">How many frames to play per second. This is a max: most likely it will be a little slower than this.</param> 
/// <param name="style">Whether to tile, center, or stretch each gif frame as it's played.</param> 
/// <param name="numFrames">The number of frames to play. If negative, this method will loop forever.</param> 
private static void SetDesktopBackgroundAsGif(string gifPath, System.Drawing.Image backgroundImage, int framesPerSecond, Style style, int numFrames) 
{ 
    if (!File.Exists(gifPath)) 
     throw new Exception("Given gif: '" + gifPath + "' not found"); 

    FileStream gifFile = new FileStream(gifPath, FileMode.Open); 

    GifBitmapDecoder gifDecoder = new GifBitmapDecoder(gifFile, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); 

    if (gifDecoder.Frames.Count == 0) 
     throw new Exception("No frames in given gif"); 

    Console.WriteLine("Saving frames to temporary files:"); 

    int numFramesSoFar = 0; 

    for (int i = 0; i < gifDecoder.Frames.Count; i++) 
    { 
     BitmapFrame gifFrame = gifDecoder.Frames[i]; 
     PngBitmapEncoder pngEncoder = new PngBitmapEncoder(); 
     pngEncoder.Frames.Add(gifFrame); 
     MemoryStream pngStream = new MemoryStream(); 
     pngEncoder.Save(pngStream); 
     Image frameImage = Image.FromStream(pngStream); 
     Bitmap bmp = new Bitmap(frameImage.Width, frameImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 
     using (Graphics g = Graphics.FromImage(bmp)) 
     { 
      g.DrawImage(backgroundImage, 0, 0); 
      g.DrawImageUnscaled(frameImage, 0, 0); 
     } 
     string tempPath = Path.Combine(Path.GetTempPath(), gifPath + i + ".bmp"); 
     bmp.Save(tempPath, System.Drawing.Imaging.ImageFormat.Bmp); 

     Console.WriteLine("Saved frame " + i); 

     numFramesSoFar++; 

     if (numFrames >= 0 && numFramesSoFar >= numFrames) break; 
    } 

    Console.WriteLine("Setting frames to desktop background at about " + framesPerSecond + " FPS"); 

    // 1.0/... to convert to seconds per frame (instead of frames per second) 
    // * 1000 to convert to milliseconds per frame 
    // * 1000 to convert to microseconds per frame 
    // * 10 to convert to 0.1s of microseconds per frame = 100s of nanoseconds per frame 
    long ticksBetweenFrames = (long)Math.Round(1.0/framesPerSecond) * 1000*1000*10; 

    Stopwatch timer = new Stopwatch(); 
    timer.Start(); 

    numFramesSoFar = 0; 

    while(numFrames < 0 || numFramesSoFar < numFrames) 
    { 
     for (int i = 0; i < gifDecoder.Frames.Count; i++) 
     { 
      // Sleep until we're at the desired frame rate, if needed. 
      if(ticksBetweenFrames > timer.ElapsedTicks) 
       Thread.Sleep(new TimeSpan(Math.Max(0, ticksBetweenFrames - timer.ElapsedTicks))); 

      timer.Restart(); 

      // From http://stackoverflow.com/a/1061682/2924421 

      string filePath = Path.Combine(Path.GetTempPath(), "wallpaper" + i + ".bmp"); 

      RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true); 

      if (style == Style.Stretched) 
      { 
       key.SetValue(@"WallpaperStyle", 2.ToString()); 
       key.SetValue(@"TileWallpaper", 0.ToString()); 
      } 

      if (style == Style.Centered) 
      { 
       key.SetValue(@"WallpaperStyle", 1.ToString()); 
       key.SetValue(@"TileWallpaper", 0.ToString()); 
      } 

      if (style == Style.Tiled) 
      { 
       key.SetValue(@"WallpaperStyle", 1.ToString()); 
       key.SetValue(@"TileWallpaper", 1.ToString()); 
      } 

      SystemParametersInfo(SPI_SETDESKWALLPAPER, 
       0, 
       filePath, 
       SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); 

      numFramesSoFar++; 

      if (numFrames >= 0 && numFramesSoFar >= numFrames) break; 
     } 
    } 

    gifFile.Close(); 
} 

은 또한 당신이 사용할 필요가 있습니다) Presentation Core, System.Xaml 및 WindowsBase를 추가합니다.

프로젝트를 마우스 오른쪽 단추로 클릭하고 속성으로 이동하여 대상 프레임 워크가 .Net Framework 4.5인지 확인하십시오. 이를 변경하면 Visual Studio를 다시 시작해야 할 수 있습니다.

+2

물론 그것은 기계를 습격합니다. 무의식적으로 던져진'Thread.Sleep'에 대한 호출로 블로킹 무한 루프가 있습니다. 시간이 지날 때까지 기다릴 수있는 더 좋은 방법이 있습니다. –

+0

아니요, SystemParametersInfo (예 : 초당 10 회) 호출과 관련이 있다고 생각합니다. 바탕 화면은 그런 식으로 새로 고쳐지기위한 것이 아닙니다. 이것은이 방법을 호출하는 프로그램을 실행하여 0 %에서 6 % -12 %의 CPU 사용으로가는 "탐색기"에 의해 증명됩니다. 내 대답을 비틀어, 비동기 메서드를 추가하고 Thread.Sleep 스팸 덜 호출 (필요한 경우에만 발생). 눈부신 우려가 있습니까? – Phylliida

+0

나는 다른 방법으로 스레드를 멈추기 위해이 스레드를 조정하는 방법을 고려해 보았지만, 처음에는 그 좋은 방법이 아닐 수도있는 방법에 대해 배 넘어갈 것처럼 보인다. – Phylliida

7

this useful answer의 자료를 바탕으로 my own app에 일치하는 화면 해상도를 설정했습니다.

그러나 레지스트리 설정이 잘못되었습니다. 올바른 값은 다음과 같습니다 (Win 7, Win 8.1, Win 10에서 테스트 됨).

if (style == Style.Fill) 
{ 
    key.SetValue(@"WallpaperStyle", 10.ToString()); 
    key.SetValue(@"TileWallpaper", 0.ToString()); 
} 
if (style == Style.Fit) 
{ 
    key.SetValue(@"WallpaperStyle", 6.ToString()); 
    key.SetValue(@"TileWallpaper", 0.ToString()); 
} 
if (style == Style.Span) // Windows 8 or newer only! 
{ 
    key.SetValue(@"WallpaperStyle", 22.ToString()); 
    key.SetValue(@"TileWallpaper", 0.ToString()); 
} 
if (style == Style.Stretch) 
{ 
    key.SetValue(@"WallpaperStyle", 2.ToString()); 
    key.SetValue(@"TileWallpaper", 0.ToString()); 
} 
if (style == Style.Tile) 
{ 
    key.SetValue(@"WallpaperStyle", 0.ToString()); 
    key.SetValue(@"TileWallpaper", 1.ToString()); 
} 
if (style == Style.Center) 
{ 
    key.SetValue(@"WallpaperStyle", 0.ToString()); 
    key.SetValue(@"TileWallpaper", 0.ToString()); 
} 
+0

왜 (숫자) .ToString()을 사용합니까? 왜 "(숫자)"가 아닌가? – HighTechProgramming15

+0

물론 할 수 있습니다. 그것은 개념의 문제입니다. 누군가 다른 사람이했기 때문에 이런 방식으로 썼습니다. – badsamaritan

관련 문제