はじめに
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をインストールします。
インストールが完了したら、プロジェクトのフォルダにある設定ファイル(csprojファイル)をテキストエディタで開きます。
以下のように、<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>をPropertyGroupタグの中に追加して保存します。
次に、App.configファイルを開き、configurationタグの中に
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="x86"/>
</assemblyBinding>
</runtime>
これでCefSharpの導入は完了です。
Bingマップを表示するプログラム
それでは、プログラムを作っていきます。
以下のようにPanelやステータスバーなどを置きます。
CefSharpはツールボックスに表示できないので、Panelの内部に合わせて表示するようにします。
以下が今回のプログラムです。
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ファイルで定義した関数を呼び出しています。
実行するとこのようにマップが表示されます。
緯度と経度を入力して「移動」を押せば
このようにマークが付きます。
おわりに
以上、C#でFormにBingマップを表示する方法でした。
回りくどい方法でしたが、意外とちゃんと動くので是非試してみてください。