LoginSignup
5
10

More than 3 years have passed since last update.

C#でFormにBingマップを表示する

Last updated at Posted at 2020-05-25

はじめに

Windows Formsに触れたことがある人なら、きっと誰もがマップをFormに埋め込みたいと思うでしょう。
しかしWindows Formsには、残念ながらマップを表示するコントロールはありません。
しかし、CefSharpとBing Maps APIを組み合わせればそのような機能を実現できます。
今回はそのやり方を紹介します。

HTMLファイルを作る

仕組みとしては、Bing Mapsを埋め込んだHTMLファイルをCefSharpで表示する形となります。
本当はGoogle Maps APIを使いたかったのですが、クレジットカード情報を登録する必要があるみたいで面倒だったので、今回はあきらめました。

Bing Maps APIを使うにはMicrosoftのアカウントが必要です。持っていない方は登録しましょう。
持っている方はBing Maps APIのページにアクセスし、「Sign in」ボタンを押してサインインします。
サインインできたら、上のメニューの「My account」から「My keys」をクリックします。
「Create key」という画面が表示されたら、必要事項を記入し「Create」をクリックします。
するとキーの一覧が表示されるので、「Show key」を押せばキーが表示されます。
このキーは後で使うのでコピーしておいてください。

それではHTMLを記述していきます。


<!DOCTYPE html>
<html>
  <head>
    <title>Bing Maps API</title>
    <meta charset="utf-8" />
    <script type='text/javascript'
      src='http://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=[キーを指定]&setLang=ja' 
      async defer></script>

   <script type='text/javascript'>
    var map;
    function GetMap() {
      map = mapStart(35, 140, 10);
    }

    // Mapを初期化
    // 緯度, 経度, 拡大率(1~20)
    function mapStart(lat, lon, num) {
      return new Microsoft.Maps.Map('#myMap', {
        center: new Microsoft.Maps.Location(lat, lon),
        // 表示モード(road:普通, aerial:航空写真)
        mapTypeId: Microsoft.Maps.MapTypeId.aerial,
        zoom: num
      });
    }

    // ピンを立てる(緯度, 経度)
    function mapPushpin(lat, lon) {
      const location = new Microsoft.Maps.Location(lat, lon);
      const pin = new Microsoft.Maps.Pushpin(location, {
        color: "red",     // ピンの色
        draggable: true,  // ドラッグできるか
      });
      map.entities.push(pin);
    }
    </script>
</head>
<body style="margin:0;">
    <div id="myMap" style="position:relative;width:100%;height:100%;"></div>
</body>
</html>

[キーを指定]のところに先ほど取得したキーを指定してください。
これをC:\Maps.htmlとして保存します。

CefSharpの導入

次に、Bingマップを表示するアプリのプロジェクトを作成しておきましょう。
作成したら、このプロジェクトに「CefSharp」というパッケージを導入します。
CefSharpはChromiumのC#向け実装です。

「HTMLファイルを表示したいならWebBrowserコントロールを使えばいいのでは?」
と思うかもしれませんが、WebBrowserコントロールは内部に古いIEのエンジンを使っているので、エラーが頻発してまともに使えません。

今回は、NuGetでCefSharp.WinFormsをインストールします。
スクリーンショット (52).png

インストールが完了したら、プロジェクトのフォルダにある設定ファイル(csprojファイル)をテキストエディタで開きます。
以下のように、<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>をPropertyGroupタグの中に追加して保存します。
スクリーンショット (55).png

次に、App.configファイルを開き、configurationタグの中に


<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <probing privatePath="x86"/>
    </assemblyBinding>
</runtime>

を追加して保存します。
スクリーンショット (53).png

これでCefSharpの導入は完了です。

Bingマップを表示するプログラム

それでは、プログラムを作っていきます。
以下のようにPanelやステータスバーなどを置きます。
CefSharpはツールボックスに表示できないので、Panelの内部に合わせて表示するようにします。
スクリーンショット (54).png

以下が今回のプログラムです。


using System;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;

namespace BingMapsSample
{
    public partial class Form1 : Form
    {
        string maphtml = @"C:\Maps.html";  // さっきのHTMLファイル
        ChromiumWebBrowser cefBrowser;
        CefSettings settings;
        public Form1()
        {
            InitializeComponent();
            button1.Enabled = false;
            toolStripStatusLabel1.Text = "読み込み中...";

            settings = new CefSettings();
            // レンダリングを最適化(これをやらないとバグる)
            settings.SetOffScreenRenderingBestPerformanceArgs();
            Cef.Initialize(settings);
            cefBrowser = new ChromiumWebBrowser(maphtml);
            cefBrowser.LoadingStateChanged += CefBrowser_LoadingStateChanged;
            // Panelに合わせて表示
            panel1.Controls.Add(cefBrowser);
            cefBrowser.Dock = DockStyle.Fill;
        }

        private void CefBrowser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e)
        {
            if(!e.IsLoading)
            {
                // 読み込み完了時
                Invoke((MethodInvoker)delegate {
                    toolStripStatusLabel1.Text = "読み込み完了";
                    button1.Enabled = true;
                });
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Javascriptの実行
            cefBrowser.ExecuteScriptAsync("map = mapStart(" + textBox1.Text +
                "," + textBox2.Text + "," + "10);");
            cefBrowser.ExecuteScriptAsync("mapPushpin(" + textBox1.Text +
                "," + textBox2.Text + ");");
        }
    }
}

button1_Click内ではExecuteScriptAsyncメソッドを使って、HTMLファイルで定義した関数を呼び出しています。
実行するとこのようにマップが表示されます。
スクリーンショット (56).png
緯度と経度を入力して「移動」を押せば
スクリーンショット (57).png
このようにマークが付きます。

おわりに

以上、C#でFormにBingマップを表示する方法でした。
回りくどい方法でしたが、意外とちゃんと動くので是非試してみてください。

参考文献

5
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
10