【2019 R3】WebBrowser コントロールを使ってみた
こんにちは、サポート部のまさよしです。
今年も残すところ一ヶ月となり色々と振り返る時期となりましたが、PowerBuilder のトップトピックスとしてはなんといっても PowerBuilder 2019 R3 日本語版 (LTS) のリリースですよね!
新機能のゴン攻めがあったりビッタビタにはめた機能改修があったりと、開発者やユーザーの冒険心をくすぐるような内容となっていますので「PowerBuilder 2019 R3 日本語版 リリース」や「PowerBuilder 2019 R3 日本語版 新機能+機能強化のご紹介」をおさらいしつつ、しっかり振り返って来年の新規開発や既存アプリ改修、マイグレーションに活用してください!
そこで今回ご紹介するのは WebBrowser コントロールです。以前のバージョンでも OLE コントロールとして外部の Web ブラウザーを利用できていましたが、2019 R3 では標準コントロールとして新しく追加されました。標準コントロールとなると使ってみよう感の敷居も下がったと思いませんか?
それでは、さっそくはじめましょう。
その前に
WebBrowser コントロールのご紹介の前にプチ情報を。すでにご存じの方もいるかもしれませんが、2019 R3 ではデモアプリの変更もありました。
詳しくは「Appeon PowerBuilder、InfoMaker 2019 新機能紹介」のリンク先にある「What’s New」の「1.5 デモアプリの変更」で確認できますが、新機能の UI Theme や RibbonBar コントロールなどが実装されているアプリが追加されました。
今回ご紹介する WebBrowser コントロールに関してもコード (Example Graph App) が用意されているので、是非参考にしてもらえればと思います。
シンプルなブラウザーを実装
昔から説明書を読む前にゲームを始めてしまう私としては、マニュアルを読む前に PowerBuilder でシンプルなブラウザーを作ってみたいと思ってしまいますね。その好奇心の赴くまま手を動かしてみましょう。
ブラウザーということでピクチャコントロールを 4 つ (戻る / 進む / 再読み込み / ホーム)、シングルラインエデットコントロールを 1 つ (URL 入力)、ボタンコントロールを 1 つ (GO)、WebBrowser コントロールを 1 つ配置したウィンドウを用意します。
各コントロールの処理は以下のとおりです。
インスタンス変数
Boolean ib_CanBack Boolean ib_CanForward
WebBrowser コントロール : NavigationStateChanged イベント
ib_CanBack = canGoBack ib_CanForward = canGoForward
ピクチャコントロール (戻る) : Clicked イベント
If ib_CanBack Then wb_1.Goback() End If
ピクチャコントロール (進む) : Clicked イベント
If ib_CanForward Then wb_1.GoForward() End If
ピクチャコントロール (再読み込み) : Clicked イベント
wb_1.Refresh()
ピクチャコントロール (ホーム) : Clicked イベント
Integer li_rtn sle_url.text = "https://japan.appeon.com/" li_rtn = wb_1.Navigate(sle_url.text)
ボタンコントロール (GO) : Clicked イベント
Integer li_rtn
li_rtn = wb_1.Navigate(sle_url.text)
コードの簡単な説明です。ピクチャコントロール (戻る / 進む) の活性 / 非活性の制御用にインスタンス変数を用意して、WebBrowser コントロールのナビゲーションの状態が変化したときに発生する NavigationStateChanged イベントで引数の canGoBack と canGoForward をセットします。また、ピクチャコントロール (ホーム) やボタンコントロール (GO) では Navigate 関数で引数に指定された Web ページを参照します。
機能が少ないこともありますがコードはこれだけです。ローコードで簡単に作れますよね!さっそく動作を確認してみましょう。
本当にクイックに実装できました。なお、WebBrowser コントロールの詳細についてはオンラインヘルプ「オブジェクトとコントロール : WebBrowserコントロール (英語)」でご確認ください。
次はブラウザーを実装しているときにちょっとしたアイデアが浮かんだので、少し試してみます。
顧客管理機能のちょっとした改修
来月や再来月は年末 / 年始でお客様への挨拶回りが多くなる季節となります。新型コロナウイルスによる緊急事態宣言も解除されたので、もしかしたらお客様先へ直接伺う機会も増えてくるかもしれません。そのときに改めてお客様の企業情報や訪問先までの経路を確認したいこともあるかと思います。
こういう場合、例えばブラウザーを立ち上げ企業名を入力してコーポレートサイトを検索したり、住所を入力して経路検索したりするかと思いますが、もし顧客管理機能が備わっている PowerBuilder のシステムがあれば WebBrowser コントロールを利用するのも良いかもしれませんね。
簡単な顧客管理画面を以下のように作成してみました。メインには顧客情報を一覧表示するデータウィンドウを配置しましたが特別な作りはしていません。
なお、顧客情報一覧上のボタンが押された際に表示される (WebBrowser コントロールのみ配置した) ウィンドウもあわせて用意しました。各コントロールの処理は以下のとおりです。
顧客情報を一覧表示するウィンドウ
グローバル変数
Integer gi_mode
データウィンドウ : Clicked イベント
Choose Case dwo.name Case "btn_disp_customer_info" // 画面 (企業情報) の表示 gi_mode = 1 OpenWithParm(w_disp_web, dw_supplier_list.GetItemString(row, "customer_site_url")) Case "btn_disp_map" // 画面 (地図) の表示 gi_mode = 2 OpenWithParm(w_disp_web, dw_supplier_list.GetItemString(row, "customer_address")) Case "btn_disp_route" // 画面 (ルート検索) の表示 gi_mode = 3 OpenWithParm(w_disp_web, dw_supplier_list.GetItemString(row, "customer_address")) End Choose
顧客情報一覧上のボタンが押された際に表示されるウィンドウ
インスタンス変数
String is_home_address = "東京都港区西新橋二丁目三番一号 マークライト虎ノ門5階"
ウィンドウ : Open イベント
Integer li_rtn Choose Case gi_mode Case 1 // 画面 (企業情報) の表示 w_disp_web.title = "企業情報" li_rtn = wb_1.Navigate(Message.StringParm) Case 2 // 画面 (地図) の表示 w_disp_web.title = "地図" li_rtn = wb_1.Navigate("https://www.google.com/maps/search/?api=1&query=" + Message.StringParm) Case 3 // 画面 (ルート検索) の表示 w_disp_web.title = "ルート検索" li_rtn = wb_1.Navigate("https://www.google.com/maps/dir/?api=1&origin=" + is_home_address + "&destination=" + Message.StringParm) End Choose
今回は地図の表示やルート検索に Google Maps を利用しました。もちろん Google Maps API を利用することも考えましたが、特定の場所のピン止めやルート検索のみを比較的簡単に実装できるよう、API キーの取得が不要で手間なく扱えるようにあえて URL パラメーターでリクエストを行う方式をとりました。興味がある方は「公式ドキュメント : Maps URLs (英語)」をご確認ください。
どうやら特定の場所にピンを立てるリクエスト (Search) が「https://www.google.com/maps/search/?api=1¶meters」で、指定した場所間の道順を表示するリクエスト (Directions) が「https://www.google.com/maps/dir/?api=1¶meters」という形式のようです。なお仕様上、ズーム指定はできないようです。ボタンが押された際に表示されるウィンドウの Open 時に遷移元によってこのリクエストを切り替えてます。それでは動作を確認してみましょう。
ここもローコードで簡単に作れますね。それでは皆さんも WebBrowser コントロールをご活用ください!
…
あ!?そういえば WebBrowser コントロールの宿題が残っていましたね。今年の宿題は今年のうちに終わらせてしまいましょう。
Google API シリーズのちょっとした改修
実は今回 WebBrowser コントロールをピックアップしたのは、前回のブログ「Google Drive API で Google ドライブへアクセス」を投稿したときに先輩エンジニアから「Authorization Code 生成用に ShellExecuteW 関数使ってるけど、WebBrowser コントロールを使った方が外部関数を省けたり、ユーザーのアクション数を減らしたり、アプリ内で機能完結するから一体感の向上も図れるんじゃない?」というアドバイスをもらったのがはじまりでした (記事内に「次回の記事ではそちらも記載予定です」と書いてありましたね)。
それでは Authorization Code の生成を ShellExecuteW 関数から WebBrowser コントロールに切り替えてみますが、コードはここまで説明した内容とほぼ変わりなく修正量も至って少ないので簡潔にお伝えしますね。
- WebBrowser コントロールを配置したウィンドウを新規作成
- 新規作成したウィンドウの Open イベントで WebBrowser コントロールの Navigate 関数を実行 (引数は Message オブジェクトの StringParm プロパティ)
- Authorization Code 生成ボタンで実行している ShellExecute 関数を OpenWithParm 関数に変更 (引数は新規作成したウィンドウ名と認証リクエスト用 URL)
- Global External Functions に宣言されている ShellExecuteW 関数のコメント化もお忘れなく!
これだけです。それでは動作を確認してみましょう。
いいですねー。前までは処理の途中でデフォルトブラウザーが起動するのでなんとなく流れが中断された気分になったのですが、そういう違和感もなくなった気がします。
画像はありませんが、以降の処理 (Access Token の取得や Google ドライブへのアクセス) まで確認できました。
もちろん「Google Sheets API を使ってスプレッドシートを操作」や「Gmail API を使ってメールを操作(前編)」といった Google API シリーズすべてに対応できるのでお試しください。
まとめ
顧客管理の機能 (コーポレートサイト表示、地図表示、ルート検索) や Google API シリーズの機能 (Authorization Code 生成) は今のままでも別途ブラウザーを立ち上げれば、後は検索などで実現できます。
ですが、今回のようにちょっとした改善を絶え間なく注ぐことで、ユーザーの満足度を高められるかもしれません。皆さんも色々と創意工夫してアプリをより使い勝手よく育ててくださいね。
「アプリケーションも、ちょっとの工夫でこの使いやすさ!」
以上、まさよしでした。