fubのプラグインの作り方(最初の一歩+ツールバー編)
必要なもの
Visual Studio .NET 2005もしくは同等の機能を有するもの (言語は問わないと思いますが例はC#です)
持っていない人は無料のExpress Editionというお手軽なものがあります。こちらでも可能です。(但し容量は最大1.7GB必要だそうです(システム要件))
また、その言語を使える。もしくは習得する気合が必要となります。
オリジナルのコードを書く前の下準備
- Visual Studioを起動します。
- メニューの ファイル/新規作成/プロジェクト を選択してください。
- ダイアログが出ますので、プロジェクトの種類を指定します。左のツリーから Visual C#/Windows を選択し、テンプレートから Windows コントロール ライブラリを選択。下のプロジェクト名や場所等を決定してください。プロジェクト名や.csファイル名は作成するプラグインの名前が妥当です。(今回はNavigationBarとします)
- メニューの プロジェクト/参照の追加 の参照タブからfubのインストール済みフォルダにある、fubPlugin.dllを設定してください。
- 初期状態ではただのグレーで四角いヘンなコントロールが作成されます。F7を押すか、もしくはソリューションエクスプローラーと書いてあるツリーから.csファイルの右クリックメニューから コードの表示 でコードが表示されます。初期状態のコードは以下の通り。*1
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace NavigationBar { public partial class NavigationBar : UserControl { public NavigationBar() { InitializeComponent(); } } }
- 追加と書き換え(コメントは分かりやすくしただけのことで、汚いので直接書き換えて結構です)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; // using追加(こちらはコードを書きやすくするためのもので必須ではありません) using fubPlugin; // namespace変更 //namespace NavigationBar namespace fubPlugin { // インタフェースの変更(PluginBaseは必須、IToolbarはツールバータイプの場合) //public partial class NavigationBar : UserControl public partial class NavigationBar : PluginBase, IToolbar { public NavigationBar() { InitializeComponent(); // プラグイン名設定 this.PluginName = "NavigationBar"; } } }
オリジナルのコードを書く(例:簡易リンクナビゲーション)
いわゆるlinkタグで指定されたリンク先から「次の文書」「前の文書」へ遷移します。例なのでこれだけ。
リソースの作成
- 前の文書、次の文書に該当するボタン画像を作成するなり探してくるなりしてください。
- Express Editionでもあるかどうかは分かりませんが、以下のファイルにかなり揃っています。Program Files\Microsoft Visual Studio 8\Common7\VS2005ImageLibrary\VS2005ImageLibrary.zip
- プロジェクトメニューの一番下のプロパティを開いてください。
- 左側のタブから リソース を選択します。空のプロジェクトから作った場合などはクリックしろ、とかリンクが出てくるのでクリックしてください。
- 上部ツールバーが「文字列」になっていると思いますので、「イメージ」に変更してください。(アイコンの場合はアイコンで)
- 「リソースの追加」の右のメニューを押し、既存のファイルの追加から最初に用意した画像ファイルを選択してください。
コーディング
fubPlugin.dllに含まれているCommandBarというclassがツールバーとしてはお勧めです。私の作成したプラグインは大抵このツールバーを使っています。選択肢としては他にMS謹製のSystem.Windows.Forms.ToolBarとSystem.Windows.Forms.ToolStripがあります。
但し自分用なのでデザイナに対応させていません。ポトペタ感覚ではありませんが、対して難しくも無いかと。
HTMLを触るプラグインを書く場合はfubhtml.dllも参照に加えてください。fubhtml.dllには含まれないタグを使用する場合はMicrosoft.mshtml.dllを使って構わないのですが、今後配布対象からは外します。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using System.Text.RegularExpressions; using fubPlugin; using fubhtml; namespace fubPlugin { // インタフェースの種類 // PluginBase :必須 // IToolbar :ツールバー型 // IExplorerbar :サイドバー型 // IModule :ショートカットキーやマウスジェスチャーから機能を呼び出す場合は必要 // Execute(string command)をイベント代わりに実装 // ISyncActiveTab :アクティブタブと同期を取る必要がある場合に必要 // OnSelectedTabChange(), OnActiveTabNavigated()をイベント代わりに実装 public partial class NavigationBar : PluginBase, IToolbar, IModule { private CommandBar toolBar; // ツールバー public NavigationBar() { InitializeComponent(); // プラグイン名設定 this.PluginName = "ナビゲーションバー"; // ツールバー作成 toolBar = new CommandBar(); // ボタン追加 // 引数1:追加したイメージリソース // 引数2:イベントハンドラ(今回は小さいので匿名メソッドで書いてあります) // イメージの後にstringでテキストも表示できます。今回は割愛。 // 仕様はインテリセンスで確認してください。 CommandBarItem prevButton = new CommandBarItem( global::NavigationBar.Properties.Resources.prev, delegate(object sender, EventArgs e) { navigation(false); }); CommandBarItem nextButton = new CommandBarItem( global::NavigationBar.Properties.Resources.next, delegate(object sender, EventArgs e) { navigation(true); }); toolBar.Items.AddRange(new CommandBarItem[] { prevButton, nextButton }); toolBar.Resize += new EventHandler(toolBar_Resize); this.Controls.Add(toolBar); } // テーマの適用(ツールバーの場合はこれと同じで結構です) protected override void OnPaintBackground(PaintEventArgs pevent) { base.OnPaintBackground(pevent); VisualStyleAPI.DrawRebarBackground(this.Handle, pevent.Graphics, pevent.ClipRectangle, VisualStyleAPI.ThemeRebarParts.RP_BAND); } // ショートカットキーやマウスジェスチャーから呼び出すにはIModuleインタフェースを追加し // 下記Executeメソッドを実装して定義ファイルに手動で定義する必要があります // 例:Tag="NavigationBar.Prev" public void Execute(string command) { switch (command.ToLower()) { case "prev": // NavigationBar.Prev navigation(false); break; case "next": // NavigationBar.Next navigation(true); break; } } // 決めうちでもいいんですけど、ボタン数可変の場合等考えなくていいので void toolBar_Resize(object sender, EventArgs e) { this.Size = toolBar.Size; } // ナビゲーション処理 // ※COMの参照カウンタ上げっぱなしの作法の悪い例です private void navigation(bool next) { IHTMLDocument2 doc = base.GetActiveFrameDocument() as IHTMLDocument2; // LINKタグから調査 IHTMLElementCollection links = doc.all.tags("LINK") as IHTMLElementCollection; for (int i = 0; i < links.length; i++) { IHTMLLinkElement link = links.item(i, i) as IHTMLLinkElement; if (link == null || link.rel == null) continue; string rel = link.rel.ToLower(); if (!next && (rel == "prev" || rel == "previous")) { doc.url = combineUrl(doc.url, link.href); return; } if (next && (rel == "next" || rel == "child")) { doc.url = combineUrl(doc.url, link.href); return; } } // アンカーから調査(適当なリンクがあれば使う) Regex reg; if (next) reg = new Regex("^次[の|へ]", RegexOptions.Compiled); else reg = new Regex("^前[の|へ]", RegexOptions.Compiled); links = doc.all.tags("A") as IHTMLElementCollection; for (int i = 0; i < links.length; i++) { IHTMLElement el = links.item(i, i) as IHTMLElement; if (el == null || el.innerText == null) continue; string caption = el.innerText.Trim(); if (reg.IsMatch(caption)) { IHTMLAnchorElement a = el as IHTMLAnchorElement; // a.hrefは取得時に例外が発生する経験があるので握り潰す try { doc.url = combineUrl(doc.url, a.href); return; } catch { } } } } // 簡易相対URL変換 private string combineUrl(string baseurl, string url) { if (url.StartsWith("http://") || url.StartsWith("https://") || url.StartsWith("ftp://") || url.StartsWith("file://")) return url; try { Uri uri = new Uri(new Uri(baseurl), url); return uri.AbsoluteUri; } catch { return url; } } } }
ショートカットキーやマウスジェスチャーへの登録
ユーザーフォルダ内にmenu.xmlが存在しない人はmenu.defaultをユーザーフォルダにコピーし、menu.xmlにリネームしてください。
エディタで開き、定義を追加します。
<Menu Text="前の文書" Shortcut="Ctrl+Shift+Left" Tag="NavigationBar.Prev"/> <Menu Text="次の文書" Shortcut="Ctrl+Shift+Right" Tag="NavigationBar.Next"/>
どこでもいいのですが、色々作る気があるのでしたら思い切ってルートから定義してもいいです。オプションとヘルプの間辺りにプラグイン拡張というメニューを作りプラグイン毎に階層を作るとA型は整理整頓好きだなあ、とか言われます。
<Menu Text="プラグイン拡張(&P)" Shortcut="Alt+P"> <Menu Text="ナビゲーションバー(&N)"> <Menu Text="前の文書" Shortcut="Ctrl+Shift+Left" Tag="NavigationBar.Prev"/> <Menu Text="次の文書" Shortcut="Ctrl+Shift+Right" Tag="NavigationBar.Next"/> </Menu> </Menu>
メニュー定義ファイルに定義することでマウスジェスチャーのコマンド一覧にも表示されます。