专业云南做网站,网站屏蔽中国ip,wordpress cms模板,设计师找灵感的网站前言一天#xff0c;我朋友指着某某付费软件对我说#xff0c;这个东西不错#xff0c;每天生成一张桌面背景#xff0c;还能学英语#xff08;放置名人名言和翻译#xff09;#xff01;我说#xff0c;这东西搞不好我也能做#xff0c;然后朋友说#xff0c;“如果… 前言一天我朋友指着某某付费软件对我说这个东西不错每天生成一张桌面背景还能学英语放置名人名言和翻译我说这东西搞不好我也能做然后朋友说“如果你搞出来了我愿意给你付费$$$$元”然后就有了今天的故事?。该桌面背景效果如下该桌面背景有4个特点背景为一张从 必应下载的壁纸英文为随机的名人名言从 API获取注意文件下文有阴影使用 Direct2D英文被翻译成了中文使用了 AzureCognitiveService当然还有重要的需要将这张图片设为桌面背景这通过 WindowsAPI完成。下面我将对里面的功能点一一讲解。第一步 下载必应壁纸bing.com每天提供了一张壁纸下载 bing壁纸是最简单的方式。根据用户协议必应每日图片允许也只允许用户将其设置为桌面背景因此可以放心使用。bing壁纸的 API如下https://www.bing.com/HPImageArchive.aspx?formatjsidx0n5mktzh-cn使用浏览器访问格式如下由图可见 API返回了一个 JSON里面一个 images的数组里面元素中的 url属性即是 bing壁纸。可以通过拼接 https://www.bing.com来下载今天的 bing壁纸因此本段也分为三小步用 C#代码可以这样写1. 下载 bing.com壁纸查询 API下载使用 HttpClient注意 HttpClient在单个应用中应该定义为静态的。代码如下var http new HttpClient();
string url https://www.bing.com/HPImageArchive.aspx?formatjsidx0n5mktzh-cn;
string content await http.GetStringAsync(url);注意其中的 n5中的 5指的是最新的 5张照片如果想获取 10张可以将 5改成 10。2. 解析返回的壁纸 JSON信息解析 JSON有很多方式本文使用传统的 Json.NET/ Newtonsoft.Json来做string json JToken.Parse(content);
string images json[images] .Select(x x[url].ToString()) .Select(x https://cn.bing.com x);
string pictureUrl images.First();注意第二行代码其实可以直接获取所有的bing3. 下载完成的壁纸图片这一步也通过 HttpClient完成var fileName Path.GetTempFileName();
File.WriteAllBytes(fileName, await http.GetByteArrayAsync(url));
return fileName;然后下载的图片就保存在 fileName这个变量所表达的路径中了。注意不一定非要下载到文件中下载到内存中亦可但下文中的代码需要少许调整这里就不深入了。第二步 获取名人名言我在网上找了一下有不少网站都提供了英语名人名言服务其中还不乏免费服务。本文使用的是 favqs.com提供的 API随便找的该 API每次调用都会返回不同的“名人名言”我试了一下可堪一用免费 API调用地址如下https://favqs.com/api/qotd返回的 json格式如下{ qotd_date: 2019-09-30T00:00:00.00000:00, quote: { id: 61060, dialogue: false, private: false, tags: [ work ], url: https://favqs.com/quotes/voltaire/61060-let-us-work-w-, favorites_count: 0, upvotes_count: 1, downvotes_count: 0, author: Voltaire, author_permalink: voltaire, body: Let us work without theorizing, tis the only way to make life endurable. }
}可以看到作者和文本可以使用 author和 body两个字段来表示。这部分使用 C#代码下载和解析过程如下async Taskstring GetQuote()
{ var url https://favqs.com/api/qotd; var content await http.GetStringAsync(url); var json JToken.Parse(content); return json[quote][body] \r\n\t\t\t\t—— json[quote][author];
}如代码所示我将 body和 author两个字段拼接成了一个字符串可以直接使用像这样Let us work without theorizing, tis the only way to make life endurable. ——Voltaire第三步 生成图片加阴影这步使用 Direct2D比较复杂要注意的点很多各位可以选择跳过这一步直接拿代码?或者稍微看看。string GenerateWallpaper(string pictureFileName, string english, string chinese)
{ var wic new WIC.ImagingFactory2(); var d2d new D2D.Factory(); float dpi d2d.DesktopDpi.Width; Size2 size new Size2(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); WIC.FormatConverter image CreateWicImage(wic, pictureFileName); using (var wicBitmap new WIC.Bitmap(wic, size.Width, size.Height, WIC.PixelFormat.Format32bppPBGRA, WIC.BitmapCreateCacheOption.CacheOnDemand)) using (var target new D2D.WicRenderTarget(d2d, wicBitmap, new D2D.RenderTargetProperties())) using (var dc target.QueryInterfaceD2D.DeviceContext()) using (var bmpPicture D2D.Bitmap.FromWicBitmap(target, image)) using (var dwriteFactory new SharpDX.DirectWrite.Factory()) using (var brush new SolidColorBrush(target, SharpDX.Color.LightGoldenrodYellow)) using (var bmpLayer new D2D.Bitmap1(dc, target.PixelSize, new D2D.BitmapProperties1(new D2D.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied), dpi, dpi, D2D.BitmapOptions.Target))) { var oldTarget dc.Target; dc.Target bmpLayer; target.BeginDraw(); { var textFormat new DWrite.TextFormat(dwriteFactory, Tahoma, size.Height / 27); // draw English { var textLayout new DWrite.TextLayout(dwriteFactory, english, textFormat, target.Size.Width * 0.75f, float.MaxValue); var center new Vector2((target.Size.Width - textLayout.Metrics.Width) / 2, (target.Size.Height - textLayout.Metrics.Height) / 2); target.DrawTextLayout(new Vector2(center.X, center.Y), textLayout, brush); } { // draw Chinese var textLayout new DWrite.TextLayout(dwriteFactory, chinese, textFormat, target.Size.Width * 0.75f, float.MaxValue); var center new Vector2((target.Size.Width - textLayout.Metrics.Width) / 2, target.Size.Height - textLayout.Metrics.Height - size.Height / 18); target.DrawTextLayout(new Vector2(center.X, center.Y), textLayout, brush); } } target.EndDraw(); // shadow var shadow new D2D.Effects.Shadow(dc); shadow.SetInput(0, bmpLayer, new RawBool(false)); dc.Target oldTarget; target.BeginDraw(); { target.DrawBitmap(bmpPicture, new RectangleF(0, 0, target.Size.Width, target.Size.Height), 1.0f, BitmapInterpolationMode.Linear); dc.DrawImage(shadow, new Vector2(size.Height / 150.0f, size.Height / 150.0f)); dc.UnitMode UnitMode.Pixels; target.DrawBitmap(bmpLayer, 1.0f, BitmapInterpolationMode.Linear); } target.EndDraw(); string wallpaperFileName Path.GetTempPath() wallpaper.png; using (var wallpaperStream File.OpenWrite(wallpaperFileName)) { SaveD2DBitmap(wic, wicBitmap, wallpaperStream); wallpaperStream.Close(); return wallpaperFileName; } }
}
WIC.FormatConverter CreateWicImage(WIC.ImagingFactory wicFactory, string filename)
{ using (var decoder new WIC.JpegBitmapDecoder(wicFactory)) using (var decodeStream new WIC.WICStream(wicFactory, filename, NativeFileAccess.Read)) { decoder.Initialize(decodeStream, WIC.DecodeOptions.CacheOnLoad); using (var decodeFrame decoder.GetFrame(0)) { var converter new WIC.FormatConverter(wicFactory); converter.Initialize(decodeFrame, WIC.PixelFormat.Format32bppPBGRA); return converter; } }
}
void SaveD2DBitmap(WIC.ImagingFactory wicFactory, WIC.Bitmap wicBitmap, Stream outputStream)
{ using (var encoder new WIC.BitmapEncoder(wicFactory, WIC.ContainerFormatGuids.Png)) { encoder.Initialize(outputStream); using (var frame new WIC.BitmapFrameEncode(encoder)) { frame.Initialize(); frame.SetSize(wicBitmap.Size.Width, wicBitmap.Size.Height); var pixelFormat wicBitmap.PixelFormat; frame.SetPixelFormat(ref pixelFormat); frame.WriteSource(wicBitmap); frame.Commit(); encoder.Commit(); } }
}要看的话要点如下图片大小是由主显示器分辨率决定的可以使用 Screen.PrimaryScreen.Bounds.Width/ Screen.PrimaryScreen.Bounds.Height获取一定要注意不同电脑的 DPI设置这样可以保证高 DPI和低 DPI的显示器都能有完美的效果这部分是使用 d2d.DesktopDpi.Width获取的请注意里面的使用方式最重要的是用不同客户的电脑亲自运行看看)字体大小是根据图片的高度决定的如代码所示字体大小为 size.Height/27虽然代码前后顺序是先画文字、再画阴影但实际生成代码部分是先画阴影、再画文字这样确保文字在阴影之上可以使用 textLayout.Metrics获取生成文字的宽度和高度这样可以确保文件显示在中心位置注意下文中 dc.UnitModeUnitMode.Pixels这是确保 DPI显示正常。说来复杂长话短说就是这其实很合理前面设置了 DPI该 DPI不仅影响文字也会影响图片但实际上图片不应该被 DPI影响。以后有机会我会多聊聊 Direct2D这简直是一个宝库。第四步 将文字翻译成中文翻译服务 API提供商就更多了选择很多。我用的是 AzureCognitiveService它也是免费的也有付费版本。创建这个服务后它会提供两个单独的 key使用这个 key即可调用翻译服务了不像是阿里云、AWS那种 Azure会为不同的服务提供不同的 AccessKey这样做可能更容易控制信息安全一些。Azure提供了 SDK因此调用起来非常简单async Taskstring EnglishToChinese(string english)
{ var client new TranslateClient(new CognitiveServicesConfig { SubscriptionKey Util.GetPassword(Translate_Free) }); var response await client.TranslateAsync(new RequestContent { Text english }, new RequestParameter { To new string[] { zh-Hans } }); return response[0].Translations[0].Text;
}其实它的功能非常强大甚至还能多国语言同步翻译等等。最后一步 设置桌面背景这一步调用 WindowsAPI直接使用“祖传代码”即可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(string pictureFileName, Style style) { 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, pictureFileName, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); }
}使用时直接这样调用Wallpaper.Set(wallpaperFileName, Wallpaper.Style.Centered);注意由于第三步中确保了分辨率一样因此也不用关心第二个参数。总结最后看一下执行效果然而最后我那个朋友说你这东西要是支持 Linux就好咯。我不用 Linux所以我也不打算支持我看他其实也根本不用 Linux因此最后说好的 $$$$我一分钱也没拿到?。所以这部分代码我托盘而出向各位免费相送分为带翻译版本和不带翻译版本不带翻译版本可直接使用带翻译版本需要注册一个免费 Azure帐号其实也能运行只是翻译中文会显示翻译错误。愿博君一笑无翻译https://github.com/sdcb/blog-data/blob/master/2019/20190930-wallpaper-by-dotnet/PictureAndQuote-Wallpaper.linq
带翻译https://github.com/sdcb/blog-data/blob/master/2019/20190930-wallpaper-by-dotnet/PictureAndQuote-Wallpaper-T.linq