【開源小軟件 】Bing每日壁紙 讓桌面壁紙保持更新


發布一個開源小軟件,Bing每日壁紙

該小軟件可以自動獲取Bing的精美圖片設置為壁紙,並且支持隨機切換歷史壁紙,查看壁紙故事。

歡迎大家下載使用,點star!有問題請留言或者提issue。

開源地址: https://github.com/jadepeng/bing-wallpaper ,想了解技術原理的請看 技術方案

gecko

如何使用

該程序沒有主窗口,是托盤程序,點擊托盤圖標,操作相關菜單即可。

功能特性

  • 自動獲取Bing最新圖片並設置為壁紙
  • 壁紙故事, 你還可以查看壁紙后面的故事
  • 歷史壁紙,支持查看最近兩年的壁紙
  • 隨機切換,隨機獲取幾年的壁紙,穿梭時光之中
  • 定時切換,開啟后每一小時自動切換壁紙

壁紙故事

你還可以查看壁紙后面的故事,支持上下切換

壁紙故事

隨機切換

點擊后,會隨機從歷史數據中挑選一張並顯示

隨機切換

定時切換

開啟后,每1小時自動切換,相當於自動點擊隨機切換。

開發緣起

后知后覺的發現,搜狗壁紙助手已經關閉服務,不能獲取新的壁紙,回想起Bing每日提供精美的圖片,因此考慮寫一個小工具,可以自動從bing獲取圖片並設置為壁紙。

Usage

自己編譯

  • 下載代碼
git clone https://github.com/jadepeng/bing-wallpaper.git
  • Open .sln file in Visual Studio

  • Build

  • Run

.../BingWallpaper/bin/Release/BingWallpaper.exe

下載二進制

Release下載最新的構建包,筆者是win10 X64。不能運行的自己下載代碼編譯。

兼容性

This only works on Windows systems.

I've tested it on Windows 7 and Windows 10 as an admin user. If you face any problems please open an issue!

技術方案

接口

https://github.com/kompiuter/bing-wallpaper 已經有一個雛形了,因此基於這個修改下就可以滿足需求了。因此直接fork這個工程。

首先是新數據問題,http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US 接口可以獲取json格式的數據。其中idx可以調整,最多獲取10幾天的數據。

{
"images": [
{
"startdate": "20180819",
"fullstartdate": "201808191600",
"enddate": "20180820",
"url": "/az/hprichbg/rb/PineMartenScotland_ZH-CN10077017107_1920x1080.jpg",
"urlbase": "/az/hprichbg/rb/PineMartenScotland_ZH-CN10077017107",
"copyright": "凱恩戈姆山國家公園里的一只松貂,蘇格蘭 (© SCOTLAND: The Big Picture/Minden Pictures)",
"copyrightlink": "http://www.bing.com/search?q=%E6%9D%BE%E8%B2%82&form=hpcapt&mkt=zh-cn",
"quiz": "/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20180819_PineMartenScotland%22&FORM=HPQUIZ",
"wp": true,
"hsh": "997ecf7cb73e47b55617ce44f1097373",
"drk": 1,
"top": 1,
"bot": 1,
"hs": []
}
],
"tooltips": {
"loading": "正在加載...",
"previous": "上一個圖像",
"next": "下一個圖像",
"walle": "此圖片不能下載用作壁紙。",
"walls": "下載今日美圖。僅限用作桌面壁紙。"
}
}

然后可以通過https://cn.bing.com/cnhp/coverstory/獲取壁紙故事:

{
"date": "August 20",
"title": "鼠類終結者",
"attribute": "英國,凱恩戈姆山國家公園",
"para1": "凱恩戈姆山國家公園坐落於蘇格蘭高地中心地區,是英國最大的國家公園。喜歡刺激的人將這里視為天堂,蘇格蘭的五個滑雪勝地中有三座位於這里,此外這里還有兩處水上活動中心、進行飛釣和跟蹤雄鹿的區域。這里也是景觀壯麗的野生區域,內有水獺、獾、紅松鼠、鹿以及鶚等。你瞧,那粗壯的樹干后面還藏着一個可愛的小家伙——松貂,它無憂無慮的在這里生存着!",
"para2": "",
"provider": "© SCOTLAND: The Big Picture/Minden Pictures",
"imageUrl": "http://hpimges.blob.core.chinacloudapi.cn/coverstory/watermark_pinemartenscotland_zh-cn10077017107_1920x1080.jpg",
"primaryImageUrl": "http://hpimges.blob.core.chinacloudapi.cn/coverstory/watermark_pinemartenscotland_zh-cn10077017107_1920x1080.jpg",
"Country": "英國",
"City": "凱恩戈姆山國家公園",
"Longitude": "-3.538737",
"Latitude": "57.037787",
"Continent": "歐洲",
"CityInEnglish": "Cairngorms National Park",
"CountryCode": ""
}

因此,調用這兩個接口就可以獲取到最新的一天的數據。

上面提到了,bing的接口只能獲取10幾天的數據,且只能獲取1天的壁紙故事,因此需要從其他途徑獲取。通過搜索,可以輕松發現https://bing.ioliu.cn/ 有最近兩年多的數據,我們可以爬取下來作為離線數據,這樣數據就全了。

通過自研的爬蟲平台,簡單配置下:

enter description here

下載得到898條數據,應該包含2年多的數據:

enter description here

導出為json,放入工程。

設置壁紙

設置壁紙,需要調用user32.dll中的SystemParametersInfo方法,

 public sealed class 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(Image img, Style style)
        {
            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());
            }

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

壁紙故事

enter description here

一個簡單的winform頁面,背景是圖片,左右兩個圖片作為按鈕,下方一個panel顯示詳情。

隨機切換

程序開始,從json里加載歷史數據,放到一個list里,隨機從里面獲取一個即可。

 static string DataFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "history.json");
        static string BakDataFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "history.json.bak");
      
        static HistoryImageProvider()
        {
            historyImages = LoadHistoryImages();
            historyImages.ForEach(image =>
            {
                date2Image.Add(image.Date, image);
            });
        }

        static List<HistoryImage> historyImages;
        static Dictionary<string, HistoryImage> date2Image = new Dictionary<string, HistoryImage>();

        static List<HistoryImage> LoadHistoryImages()
        {
            try {
                string[] lines = File.ReadAllLines(DataFile);
                List<HistoryImage> images = new List<HistoryImage>();
                var ser = new DataContractJsonSerializer(typeof(HistoryImage));
                foreach(var line in lines)
                {
                    if (line.Trim().Length > 0)
                    {
                        images.Add((HistoryImage)ser.ReadObject(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(line))));
                    }
                }
                return images;
                }
            catch
            {
                if (File.Exists(BakDataFile))
                {
                    File.Copy(BakDataFile, DataFile);
                    return LoadHistoryImages();
                }

                return new List<HistoryImage>();
            }
        }

        /// <summary>
        ///  隨機圖片
        /// </summary>
        /// <returns></returns>
        public static HistoryImage getRandom()
        {
            return historyImages[new Random().Next(0, historyImages.Count - 1)];
        }

新數據保存

從接口獲取到新數據后,加入List,並且持久化到硬盤。

 public static void AddImage(HistoryImage image)
        {         
            if (date2Image.ContainsKey(image.Date))
            {
                historyImages.Add(image);
                date2Image.Add(image.Date, image);
                Save();
            }     
        }

        public static void Save()
        {
            if (File.Exists(DataFile))
            {
                File.Delete(BakDataFile);
                File.Move(DataFile, BakDataFile);
            }
            try
            {
                using (var stream = new FileStream(DataFile, FileMode.Create))
                {
                    var ser = new DataContractJsonSerializer(typeof(HistoryImage));
                    var line = System.Text.Encoding.UTF8.GetBytes("\r\n");
                    historyImages.ForEach(image =>
                    {
                        ser.WriteObject(stream, image);
                        stream.Write(line, 0, line.Length);
                    });
                }
            }
            catch
            {
                if (File.Exists(BakDataFile))
                {
                    File.Copy(BakDataFile, DataFile);
                }
            }
        }

作者:Jadepeng
出處:jqpeng的技術記事本--http://www.cnblogs.com/xiaoqi
您的支持是對博主最大的鼓勵,感謝您的認真閱讀。
本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM