Skip to content

WebView2、登場秘話

登場秘話

〜半年前に自分で埋めた種と、たーぼーさんからの一通の報告〜

このツールの誕生秘話の終章でも触れた通り、WebView2対応(v3.0.0)の種は、実は2026年3月――第7章「機械語を書いた春」とほぼ同じ時期――にすでに蒔かれていました。ここでは、その種がなぜ一度は本体と分離し、どうやって半年越しに復活したのかを、もう少し詳しく振り返ります。


きっかけ — Qiitaに落ちていた「ブレイクスルー」

すべては、1本の記事を見つけたことから始まりました。

🔗 Excel VBAだけでWebView2を動かす(Qiita)

「外部DLLの登録も、TLBの参照設定も要らない。純粋なExcel VBAのメモリ空間だけで、本物のWebView2が動く」

第7章でWinHTTPのコールバックを機械語サンクで生き延びさせた直後だったこともあり、この記事の言っていることが、体感としてすんなり信じられました。「vtableを直接叩けば、VBAでもここまでできるのか」と。


一発目の挑戦 — 動いた。けれど、本体とは別の生き物になった

3月15日、さっそく手を動かし始めます。

text
2026-03-15 WebView2を動かす基盤を作成
2026-03-15 QueryInterface が E_NOINTERFACE を返していた問題を修正
2026-03-15 vtable オフセットが間違っている影響でクラッシュする問題を修正
2026-03-15 UserFormに埋め込むウィンドウを用意しそこに埋め込むように改良

数日で、UserFormにWebView2を埋め込んで動かすところまでは辿り着きました。ただし、ここで大きな壁にぶつかります。当時の本体(main)には、まだ RaiseEvent による非同期イベント配信の仕組みがありませんでした。 それが整うのは、第8章で CDPCore.clsRaiseEvent CDPBrowserEvent 等が生まれる5月末〜6月のことで、この時点ではまだ2ヶ月以上先の話です。

共有できる土台がない以上、やれることは1つでした。

text
2026-03-17 `CDPBrowser`にあったmethodの一部を移植
2026-03-17 別ツールで分けるため、セル定義の整理
2026-03-21 `CDPBrowser`にあるほとんど機能を一旦そのまま移植
2026-03-21 `CDPBrowser`→`WebView2Browser`へ置き換え

CDPBrowser にあった機能を、ほぼそのまま WebView2Browser というクラスにコピーする形で移植しました。動きはします。しかし、結果として生まれたのは、同じ根から生えた、しかし物理的には完全に別の2本のツールでした。

  • Chromiumブラウザ制御ツール(本体)
  • WebView2専用制御ツール(新顔)

コードは似ているのに、修正は毎回2箇所。片方を直せば、もう片方も直さないと辻褄が合わない。保守が、単純につらい。 この時点の自分には、2本を統合し直す体力も、正しい設計も持ち合わせていませんでした。

一旦、諦めました

4月4日の「リファクタリング」を最後に、WebView2ブランチへのコミットは止まります。ここから約4ヶ月半、このブランチは誰にも触られません。 悔しさより、「今の本体を育てるほうが先だ」という判断が勝ちました。


本体だけが、どんどん育っていく数ヶ月

WebView2を脇に置いている間、Chromium制御ツールの方は劇的に進化していきます。

5月末〜6月、第8章の God クラス解体で CDPBrowser / CDPContext / CDPCore に責務が割れ、RaiseEvent ベースの配信基盤が整いました。これがどれだけ効いたかは、7月の v2.3.0 で証明されます。WinSock を自力実装し、WebSocket という2本目の通信路を、既存クラスにほとんど手を入れずに増設できたのです(第10章)。

皮肉なことに、「複数の通信路を素直に増やせる土台」は、まさにWebView2に一番欲しかったものでした。それが3月には無く、7月には当たり前のようにできていました。


転機 — たーぼーさんからの一通の報告

そろそろプログラミング作業から一区切り置こうかと考えていた、8月のある日。WebView2記事の書き手であるたーぼーさんから、こんな報告をいただきました。

「ページ自動制御の土台ができました」

その一文を読んだ瞬間、こう思いました。

「いまなら、あのWebView2ブランチ、復活できそうじゃね😳😳」

ちょうど新作ゲームスプラトゥーン レイダースにどっぷり浸かり始めていた時期でしたが、そっちのけでWebView2の再配線工事に取りかかることにしました。


再配線工事 — 実質、1からやり直し

いざブランチを掘り起こしてみると、想像以上の作業になりました。3月から半年近く経つ間に、本体側は

  • CDPBrowser / CDPContext / CDPCore への God クラス解体(第8章)
  • BiDiCDPJson によるJSONゼロコピー化(第9章)
  • WinSock自力実装(第10章)
  • Scripting.Dictionary から自作 Dictionary.cls への移行、src/ へのディレクトリ再編(第13章)

と、原型を留めないほど作り変えられていました。3月に書いた WebView2Browser を、その上にそのまま接ぎ木することはできません。コード構成としては、実質1からのやり直しでした。

救いだったのは、この半年でAIを使ったコーディングの精度が上がっていたことです。CDPコマンドの送受信を担う CallDevToolsProtocolMethodForSession まわりの部品調達は、AIに相談しながら比較的スムーズに揃えられました。

もう1つ、WebView2ならではの壁がありました。Pipe や WebSocket は「バイト列の断片が何回かに分かれて届く」前提でバッファを組んでいましたが、WebView2はCOMコールバック経由で 「1つの完成したJSONが一発で丸ごと届く」 という、全く違う配送のされ方をします。

text
2026-08-25 バインバイン以外の拡張ロジックにも対応させる

このコミットで、CDPCore.cls のバッファ拡張ロジックに、WebView2のこの配送パターンにも対応できる分岐を追加しました。「足りなくなったら倍々に拡張する」という、これまで通用していた前提が、WebView2相手には必ずしも当てはまらなかったということです。


第三のルート、開通

そうして、Pipe・WebSocketに続く3つ目の通信路として、WebView2がこのツールに合流しました。

到達点

あくまでもCDPツールとして作っているため、WebView2固有の高レベルメソッドはほとんど用意していません。ですが正直なところ、CDPだけでほぼ賄えます。 CDPContext.navigateCDPElement.getElementByQuery など、Pipe / WebSocket でおなじみの操作が、埋め込んだWebView2に対してもそのまま使えます。

唯一CDPの外側にあるのが、ICoreWebView2Settings(コンテキストメニューの有効/無効など)や ICoreWebView2Controller(表示サイズ・位置)のような、「Web領域の外側」の設定です。CDPはあくまでWeb(ページの中身)を制御するプロトコルなので、こういったホスト側の挙動までは届きません。

とはいえ、これも大した負担ではありませんでした。必要になるたびAIに頼んで、数行のプロシージャを1つ足すだけ。Visible / DevToolsEnabled / ContextMenuEnabled といったプロパティは、そうやって都度増設したものです。

結論 — 半年寝かせた種は、腐っていなかった

3月に諦めかけたブランチは、8月にはちゃんと芽を出しました。理由は単純です。本体側が、新しい通信路を受け止められるだけの土台に育っていたから。 蒔いた種そのものより、畑(本体の設計)を耕し続けたことのほうが、結果的にものを言った気がしています。

フィナーレ

ブレイクスルーの記事を教えてくれ、Wv2Thunks.bas という土台まで公開してくれた、たーぼーさんに改めて感謝します。あなたの一言の報告がなければ、このブランチはもうしばらく凍ったままだったはずです。

次に読む

Excel VBA × CDP / WebDriver BiDi