目次
サンプル・プログラム
stationsearchwin.msi | インストーラ |
bin/stationsearchwin.exe | 実行プログラム本体 |
bin/cwebpage.dll bin/libcurl.dll | 実行時に必要になるDLL |
bin/etc/help.chm | ヘルプ・ファイル |
sour/stationsearchwin.cpp | ソース・プログラム |
sour/resource.h | リソース・ヘッダ |
sour/resource.rc | リソース・ファイル |
sour/application.ico | アプリケーション・アイコン |
sour/mystrings.cpp | 汎用文字列処理関数など(ソース) |
sour/mystrings.h | 汎用文字列処理関数など(ヘッダ) |
sour/pahooGeocode.cpp | 住所・緯度・経度に関わるクラス(ソース) |
sour/pahooGeocode.hpp | 住所・緯度・経度に関わるクラス(ヘッダ) |
sour/apikey.cpp | APIキーの管理(ソース) |
sour/apikey.hpp | APIキーの管理(ヘッダ) |
sour/WebView2.h | WebView2に関わるヘッダ |
sour/event.h | WebView2用インターフェース(ヘッダ) |
sour/event.cpp | WebView2用インターフェース(ソース) |
sour/pahooWebView2.cpp | WebView2に関わる関数(ソース) |
sour/pahooWebView2.hpp | WebView2に関わる関数(ヘッダ) |
sour/makefile | ビルド |
バージョン | 更新日 | 内容 |
---|---|---|
2.1.2 | 2024/11/30 | 使用ライブラリ更新 |
2.1.1 | 2024/08/17 | 使用ライブラリ更新 |
2.1.0 | 2024/05/03 | API入力処理を改良 |
2.0.0 | 2024/04/28 | Edgeブラウザ対応,64ビット対応 |
1.1.4 | 2024/03/30 | 使用ライラリ更新 |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.0 | 2024/05/03 | getMyPath()をapikey.appのgetMyPath()関数に変更 |
1.7.0 | 2024/04/27 | Edge対応に伴いデバッグ用コードを廃棄 |
1.6.0 | 2023/07/02 | getPointsGSI()メソッド追加 |
1.5 | 2022/09/03 | デバッグコード埋め込み |
1.4 | 2021/05/01 | makeMapLeaflet() 引数追加 |
バージョン | 更新日 | 内容 |
---|---|---|
1.2.0 | 2024/05/06 | getModulePath() 追加 |
1.12 | 2021/01/31 | readWebContents() 引数post追加 |
1.11 | 2020/10/17 | htmlspecialchars() 追加 |
1.1 | 2020/10/17 | GetVersion2()追加,readWebContents() 引数ua追加 |
1.01 | 2020/10/03 | setClipboardData() bug-fix |
バージョン | 更新日 | 内容 |
---|---|---|
1.0.0 | 2024/04/27 | 初版 |
バージョン | 更新日 | 内容 |
---|---|---|
2.0.0 | 2024/04/29 | createSetAPIkey, processSetAPIkey に統合 |
1.0 | 2020/09/30 | 初版 |
使用ライブラリ
また、地図表示にWebブラウザ・コントロールを利用するため "WebView2Loader.dll" を利用する。jchv / webview2-in-mingw からダウンロードできる。
MSYS2 コマンドラインからビルドするのであれば、"makefile" を利用してほしい。
リソースの準備
Eclipse を起動し、新規プロジェクト stationsearchwin を用意する。
ResEdit を起動し、resource.rc を用意する。
Eclipse に戻り、ソース・プログラム "stationsearchwin.cpp" を追加する。
リンカー・フラグを -Wl,--enable-stdcall-fixup -mwindows -lgdiplus -static -lstdc++ -lgcc -lwinpthread -lcurl -lssl "C:\(libcurl-x64.dllのフォルダ)\libcurl-x64.dll" "C:\(WebView2Loader.dllのフォルダ)\WebView2Loader.dll" に設定する。
また、コマンド行パターンを ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} -lole32 -loleaut32 -luuid にすること。
MSYS2 コマンドラインからビルドするのであれば、"makefile" を利用してほしい。
解説:定数など
stationsearchwin.cpp
44: // 定数など ==================================================================
45: #define MAKER "pahoo.org" //作成者
46: #define APPNAME "stationsearchwin" //アプリケーション名
47: #define APPNAMEJP "最寄駅検索" //アプリケーション名(日本語)
48: #define APPVERSION "2.1.2" //バージョン
49: #define APPYEAR "2020-24" //作成年
50: #define REFERENCE "https://www.pahoo.org/e-soul/webtech/cpp01/cpp01-15-01.shtm" //参考サイト
51:
52: //ListViewItemの最大文字長:変更不可
53: #define MAX_LISTVIEWITEM 259
54:
55: //ヘルプ・ファイル
56: #define HELPFILE ".\\etc\\help.chm"
57:
58: //デフォルト保存ファイル名
59: #define SAVEFILE "stationsearchwin.csv"
60:
61: //マップID
62: #define MAP_ID "map_id"
63: //地図の大きさ
64: #define MAP_WIDTH 530 //地図の幅(ピクセル)
65: #define MAP_HEIGHT 300 //地図の高さ(ピクセル)
66: //経度・緯度(初期値)
67: #define DEF_LONGITUDE 139.766667
68: double Longitude = DEF_LONGITUDE;
69: #define DEF_LATITUDE 35.681111
70: double Latitude = DEF_LATITUDE;
71: //地図拡大率(初期値)
72: #define DEF_ZOOM 13
73: int Zoom = DEF_ZOOM;
74: //地図の種類(初期値)
75: #define DEF_MAPTYPE "GSISTD"
76: string Maptype = DEF_MAPTYPE;
解説:検索の流れ
stationsearchwin.cpp
1076: //検索
1077: case IDM_EXEC:
1078: case IDC_BUTTON_EXEC:
1079: //カーソルを砂時計に
1080: SetCursor(LoadCursor(NULL, IDC_WAIT));
1081: //検索キーがあればジオコードAPI呼び出し
1082: Query = getStrEditBox(hDlg, IDC_EDIT_QUERY);
1083: if (Query.length() > 0) {
1084: if (pGC->searchPoints(_SW(Query), UserAgent, 0) > 0) {
1085: Longitude = pGC->Ppoints[0].longitude;
1086: Latitude = pGC->Ppoints[0].latitude;
1087: }
1088: //ブラウザ表示と一覧表示
1089: selectAction = eAction::GetZoomType;
1090: execScriptAndAction();
1091: } else {
1092: //ブラウザ表示と一覧表示
1093: selectAction = eAction::GetLatLongZoomType;
1094: execScriptAndAction();
1095: }
1096: //エラー・リセット
1097: ErrorMessage = "";
1098: pGC->resetError();
1099: break;
HeartRails Geo API 最寄駅検索
URL |
---|
https://express.heartrails.com/api/xml |
フィールド名 | 要否 | 内 容 |
---|---|---|
method | 必須 | メソッド名:getStation(固定) |
x | 必須 | 最寄駅を取得したい場所の経度(世界測地系)。 |
y | 必須 | 最寄駅を取得したい場所の緯度(世界測地系)。 |
解説:HeartRails Geo APIの呼び出し
stationsearchwin.cpp
376: /**
377: * HeartRails Express API から必要な情報を配列に格納する
378: * @param double latitude 緯度(世界測地系)
379: * @param double longitude 経度(世界測地系)
380: * @return int ヒット数/(-1):エラー発生
381: */
382: int pahooHeartRailsExpress::getResults_Heartrails(double latitude, double longitude) {
383: char lng[SIZE_BUFF + 1], lat[SIZE_BUFF + 1];
384:
385: snprintf(lng, SIZE_BUFF, "%.5f", longitude);
386: snprintf(lat, SIZE_BUFF, "%.5f", latitude);
387: this->webapi = "http://express.heartrails.com/api/xml?method=getStations&x=" + (string)lng + "&y=" + (string)lat;
388: static string contents = "";
389: bool res = readWebContents(this->webapi, UserAgent, &contents);
390: if (res == FALSE) {
391: this->errmsg = _SW("HeartRails Express APIの接続エラーが発生しました");
392: return (-1);
393: }
394:
395: //配列の初期化
396: for (int i = 0; i < __SIZE_PPOINTS; i++) {
397: this->Pstations[i].id = 0;
398: this->Pstations[i].title = this->Pstations[i].line = this->Pstations[i].distance = L"";
399: this->Pstations[i].latitude = this->Pstations[i].longitude = 0.0;
400: }
401:
402: //XML読み込み
403: int cnt = 0;
404: try {
405: std::stringstream ss;
406: ss << contents;
407: ptree pt;
408: xml_parser::read_xml(ss, pt);
409:
410: //応答チェック
411: if (optional<string>str = pt.get_optional<string>("response.station")) {
412: } else {
413: this->errmsg = _SW("HeartRails Geo APIの応答エラーが発生しました");
414: return (-1);
415: }
416:
417: //XML解釈
418: try {
419: for (auto it : pt.get_child("response")) {
420: if (cnt >= __SIZE_PPOINTS) {
421: break;
422: }
423: //読み飛ばし
424: if (it.first != "station") {
425: continue;
426: }
427: //最寄駅名
428: if (optional<string>name = it.second.get_optional<string>("name")) {
429: this->Pstations[cnt].title = _UW(name.value());
430: }
431: //緯度
432: if (optional<string>lat = it.second.get_optional<string>("y")) {
433: this->Pstations[cnt].latitude = stod(lat.value());
434: }
435: //経度
436: if (optional<string>lng = it.second.get_optional<string>("x")) {
437: this->Pstations[cnt].longitude = stod(lng.value());
438: }
439: //路線
440: if (optional<string>line = it.second.get_optional<string>("line")) {
441: this->Pstations[cnt].line = _UW(line.value());
442: }
443: //距離
444: if (optional<string>distance = it.second.get_optional<string>("distance")) {
445: this->Pstations[cnt].distance = _UW(distance.value());
446: }
447: //識別子
448: this->Pstations[cnt].id = {(char)(65 + cnt)};
449: cnt++;
450: }
451: //XML解釈エラー
452: } catch(ptree_bad_path& e) {
453: this->errmsg = _SW("HeartRails Geo APIの検索エラーが発生しました");
454: return (-1);
455: }
456:
457: //読み込みエラー
458: } catch(xml_parser_error& e) {
459: this->errmsg = _SW("HeartRails Geo APIの接続エラーが発生しました");
460: return (-1);
461: }
462: contents.clear();
463:
464: return cnt;
465: }
解説:パラメータの保存と読み込み
stationsearchwin.cpp
158: /**
159: * パラメータの読み込み
160: * @param なし
161: * @return なし
162: */
163: void loadParameter(void) {
164: ptree pt;
165:
166: //初期値設定
167: initParameter();
168:
169: //XMLファイル読み込み
170: try {
171: xml_parser::read_xml(getMyPath(APPNAME) + APPNAME + ".xml", pt);
172:
173: //XML解釈
174: try {
175: //形式チェック
176: if (optional<string>str = pt.get_optional<string>("parameter")) {
177: } else {
178: return;
179: }
180: //パラメータ読み込み
181: for (auto it : pt.get_child("parameter")) {
182: string type= it.second.get_optional<string>("<xmlattr>.type").value();
183: if (type == "latitude") {
184: Latitude = stod(it.second.data());
185: } else if (type == "longitude") {
186: Longitude = stod(it.second.data());
187: } else if (type == "zoom") {
188: Zoom = stoi(it.second.data());
189: } else if (type == "maptype") {
190: Maptype = (string)it.second.data();
191: } else if (type == "wx") {
192: hParent_X = (unsigned)stoi(it.second.data());
193: } else if (type == "wy") {
194: hParent_Y = (unsigned)stoi(it.second.data());
195: } else if (type == "query") {
196: Query = utf8_sjis((string)it.second.data());
197: }
198: }
199: //解釈失敗したら初期値設定
200: } catch (xml_parser_error& e) {
201: initParameter();
202: return;
203: }
204: //読み込み失敗したら初期値設定
205: } catch (xml_parser_error& e) {
206: initParameter();
207: return;
208: }
209:
210: //アプリケーション・ウィンドウの位置(デスクトップ範囲外なら原点移動)
211: HWND hDesktop = GetDesktopWindow();
212: WINDOWINFO windowInfo;
213: windowInfo.cbSize = sizeof(WINDOWINFO);
214: GetWindowInfo(hDesktop, &windowInfo);
215: if (hParent_X >= (unsigned)windowInfo.rcWindow.right) {
216: hParent_X = 0;
217: }
218: if (hParent_Y >= (unsigned)windowInfo.rcWindow.bottom) {
219: hParent_Y = 0;
220: }
221: }
stationsearchwin.cpp
223: /**
224: * パラメータの保存
225: * @param なし
226: * @return なし
227: */
228: void saveParameter(void) {
229: #ifndef CMDAPP
230: //アプリケーション・ウィンドウの位置取得
231: WINDOWINFO windowInfo;
232: windowInfo.cbSize = sizeof(WINDOWINFO);
233: GetWindowInfo(hParent, &windowInfo);
234: hParent_X = (unsigned)windowInfo.rcWindow.left;
235: hParent_Y = (unsigned)windowInfo.rcWindow.top;
236: if (hParent_X >= (unsigned)windowInfo.rcWindow.right) {
237: hParent_X = 0;
238: }
239: if (hParent_Y >= (unsigned)windowInfo.rcWindow.bottom) {
240: hParent_Y = 0;
241: }
242: #endif
243:
244: char lng[SIZE_BUFF + 1], lat[SIZE_BUFF + 1];
245: snprintf(lng, SIZE_BUFF, "%.5f", Longitude);
246: snprintf(lat, SIZE_BUFF, "%.5f", Latitude);
247:
248: //XMLファイルへ書き込む
249: ptree pt;
250: ptree& child1 = pt.add("parameter.param", lat);
251: child1.add("<xmlattr>.type", "latitude");
252: ptree& child2 = pt.add("parameter.param", lng);
253: child2.add("<xmlattr>.type", "longitude");
254: ptree& child3 = pt.add("parameter.param", to_string(Zoom));
255: child3.add("<xmlattr>.type", "zoom");
256: ptree& child4 = pt.add("parameter.param", Maptype);
257: child4.add("<xmlattr>.type", "maptype");
258: ptree& child5 = pt.add("parameter.param", (string)to_string(hParent_X));
259: child5.add("<xmlattr>.type", "wx");
260: ptree& child6 = pt.add("parameter.param", (string)to_string(hParent_Y));
261: child6.add("<xmlattr>.type", "wy");
262: ptree& child7 = pt.add("parameter.param", sjis_utf8(Query));
263: child7.add("<xmlattr>.type", "query");
264:
265: const int indent = 4;
266: write_xml(getMyPath(APPNAME) + APPNAME + ".xml", pt, std::locale(),
267: xml_writer_make_settings<std::string>(' ', indent));
268: }
共通手順、モジュールなど
- C++ 開発環境の準備:ぱふぅ家のホームページ
- C++ 開発環境の準備 -MSYS2編-
- WiX によるWindowsインストーラー作成:ぱふぅ家のホームページ
- C++ でダイアログボックスを使う
- C++ でイベント駆動型アプリを作る
- 解説:ニュース一覧作成|C++ で Googleニュース検索
- 解説:検索結果をCSVファイルに保存|C++ で Googleニュース検索
- 解説:クリップボード|C++ でパスワード生成機を作る
- 解説:APIキーの管理|C++ で直近の地震情報を取得する
- 解説:WebView2|C++ で直近の地震情報を取得する
- 解説:解説:マップ表示用HTML生成|C++ で直近の地震情報を取得する
参考サイト
- PHPで住所・ランドマークから最寄駅を求める:ぱふぅ家のホームページ
「PHPで住所・ランドマークから最寄駅を求める」で作ったPHPプログラムをC++に移植したものである。
(2024年11月30日)使用ライブラリ更新
(2024年8月17日)使用ライブラリ更新
(2024年5月3日)Edgeブラウザ対応,64ビット対応.API入力処理を改良.
(2024年3月30日)使用ライラリ更新