Bing Maps コントロールを利用すると Wndows ストアアプリでも簡単に地図を表示することができます
表示される地図をキャプチャして画像ファイルにする場合、下記のようにすれば保存できます
private async void Button_Click(object sender, RoutedEventArgs e) { var bitmap = new RenderTargetBitmap(); await bitmap.RenderAsync(this.mapView, (int)this.mapView.ActualWidth, (int)this.mapView.ActualHeight); var data = await bitmap.GetPixelsAsync(); var file = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("tmp.png", CreationCollisionOption.GenerateUniqueName); using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) { var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream); encoder.SetPixelData( BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, DisplayInformation.GetForCurrentView().LogicalDpi, DisplayInformation.GetForCurrentView().LogicalDpi, data.ToArray()); await encoder.FlushAsync(); } }
・・・ただし、表示位置を移動した直後や航空写真に変えた直後ににキャプチャするとレンダリングが追い付かなくて歯抜け地図画像になってしまうことが;
ウェイトをおくにしても PC のスペックや場所、地図情報のキャッシュ状態によって必要な待ち時間がまちまちでどの程度待ち時間を設定すればよいのかわかりません;
いろいろ試行錯誤した結果、完璧ではないですが Bing Maps コントロールが内部で利用しているキャッシュファイルの更新日時を参照する以下のような方法に行きつきました
/// <summary> /// index.ext ファイルの最終更新日時 /// </summary> private DateTimeOffset mapExtFileModified = DateTimeOffset.MinValue; /// <summary> /// マップコントロールのレンダリングを待機する /// </summary> /// <returns>Task</returns> private async Task WaitMapRender() { this.mapExtFileModified = DateTimeOffset.Now; // 最大約10秒まで Bing Maps のキャッシュ更新を監視する for (int i = 0; i < 50; i++) { await Task.Delay(50); if (this.mapExtFileModified.CompareTo(await this.GetMapExtFileModified()) < 0) { break; } await Task.Delay(150); } } /// <summary> /// Bing Maps のキャッシュファイル(index.ext)更新日時を取得する /// </summary> /// <returns>index.ext の更新日時</returns> private async Task<DateTimeOffset> GetMapExtFileModified() { try { var extFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(@"ms-appdata:///temp/Bing.Maps/Cache/QuadKey/index.ext", UriKind.Absolute)); var property = await extFile.GetBasicPropertiesAsync(); return property.DateModified; } catch (Exception) { return DateTimeOffset.MinValue; } }
この方法でやったら少しは改善されたような気がします