1. 記事一覧 >
  2. ブログ記事
Windows
category logo

C++,C# WebBrowserコントロールでIE11のActiveXを延命

(更新) (公開)

はじめに

2022 年 6 月 15 日に IE11 がサポート終了になります。ActiveX が使えなくなり、今まで「IE11 を使ってください。」と言っていた機能が使えなくなり、Edge,Chrome,Firefox,Safari...用に同等機能の開発が必要になると思います。
対応が難しい場合、Edge の IE11 モード、あるいは、WebBrowser コントロールを使用したアプリを使うことになると思います。これにより、ActiveX は今まで通り使用できます。
今回、WebBrowser コントロールを使用したアプリを Visual Studio 2019 で実装、ビルドするところまで紹介したいと思います。


C++版、C#版両方紹介しますが、ほぼ同等機能で、関連していません。どちらかをビルドすればOKです。


Edge の IE11 モードでも、本記事の WebBrowser コントロールでも、例えば、IE11 のウィンドウ名を取得していたりした場合、ActiveX が使えなくなるか、一部機能が失われるかもしれません。

Edge の IE11 モードは、2029年1月9日に終了という情報がありますので、その頃には、この記事の内容も使えなくなると思います。


概要

WebBrowser コントロールとは、下記の図のように、IE のガワ以外のブラウザ機能を利用するものです。

WebBrowserコントロールの図


今回実装する内容は、本ブログ別記事「カスタム URL スキームでエクスプローラーを起動してフォルダを開く msi ビルド全手順」のように、カスタム URL をクリックして、IE11 画面が表示されて、ActiveX が起動するところまでがゴールです。

「Hello world.」表示部分が ActiveX


「Hello world.」表示部分が ActiveX です。


ActiveX

ただ単に 「Hello world.」 と表示する ActiveX を独自に作成しました。
(赤枠内が ActiveX です。)
ActiveX表示


この ActiveX がインストールされた状態です。
ActiveXがインストールされた状態


以下の HTML で表示します。

<HTML>
<HEAD>
</HEAD>
<BODY>
<OBJECT CLASSID="CLSID:de1a48df-a483-4876-b4dc-04421671f3f3" WIDTH="200" HEIGHT="100">
<PARAM NAME="Caption" VALUE="Hello world.">
<EMBED TYPE="application/x-test-activex" WIDTH="200" HEIGHT="100" Caption="Hello world.">
</OBJECT>
</BODY>
</HTML>

IE11モードではない Edge の場合は、以下のように起動しません。 ActiveXがインストールされた状態


ソースコード(C++)

ウィザードで生成されたソースコードを少し変更するのみです。
IEView.htm以外は、差分のみ表示です。


変更するのは、
IEView.htm
IEView.cpp
IEViewDlg.cpp
IEViewDlg.h
の4つです。


主に以下の事を行っています。
・OK、キャンセルボタンの削除
・引数の受け渡し
・引数の URL へ遷移

BOOL CIEViewDlg::PreTranslateMessage(MSG* pMsg)
{
    if (WM_KEYDOWN == pMsg->message) {
        switch (pMsg->wParam) {
        case VK_RETURN:
        case VK_ESCAPE:
            return FALSE;
        }
    }
    return CDHtmlDialog::PreTranslateMessage(pMsg);
}

は ダイアログベース の MFC アプリを Esc, Enter で閉じないようにしています。


IEView.htm
<html>
<head>
<style>
body {
background-color: #c0c0c0;
}
</style>
</head>
<body>
</body>
</html>
IEView.cpp CHANGED
@@ -42,39 +42,22 @@
42
42
 
43
43
  // ダイアログにシェル ツリー ビューまたはシェル リスト ビュー コントロールが
44
44
  // 含まれている場合にシェル マネージャーを作成します。
45
- CShellManager *pShellManager = new CShellManager;
45
+ CShellManager* pShellManager = nullptr;
46
+ //CShellManager* pShellManager = new CShellManager;
46
47
 
47
48
  // MFC コントロールでテーマを有効にするために、"Windows ネイティブ" のビジュアル マネージャーをアクティブ化
48
49
  CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
49
50
 
50
- // 標準初期化
51
- // これらの機能を使わずに最終的な実行可能ファイルの
52
- // サイズを縮小したい場合は、以下から不要な初期化
53
- // ルーチンを削除してください。
54
- // 設定が格納されているレジストリ キーを変更します。
55
- // TODO: 会社名または組織名などの適切な文字列に
56
- // この文字列を変更してください。
57
- SetRegistryKey(_T("アプリケーション ウィザードで生成されたローカル アプリケーション"));
51
+ int dwArgc;
52
+ LPTSTR* lpszArgv = CommandLineToArgvW(GetCommandLineW(), &dwArgc);
53
+ CString url = lpszArgv[1];
54
+ if (url.Find(_T(':'), 0) >= 0) {
55
+ url = url.Mid(url.Find(_T(':'), 0) + 1);
56
+ }
58
57
 
59
- CIEViewDlg dlg;
58
+ CIEViewDlg dlg(url);
60
59
  m_pMainWnd = &dlg;
61
60
  INT_PTR nResponse = dlg.DoModal();
62
- if (nResponse == IDOK)
63
- {
64
- // TODO: ダイアログが <OK> で消された時のコードを
65
- // 記述してください。
66
- }
67
- else if (nResponse == IDCANCEL)
68
- {
69
- // TODO: ダイアログが <キャンセル> で消された時のコードを
70
- // 記述してください。
71
- }
72
- else if (nResponse == -1)
73
- {
74
- TRACE(traceAppMsg, 0, "警告: ダイアログの作成に失敗しました。アプリケーションは予期せずに終了します。\n");
75
- TRACE(traceAppMsg, 0, "警告: ダイアログで MFC コントロールを使用している場合、#define _AFX_NO_MFC_CONTROLS_IN_DIALOGS を指定できません。\n");
76
- }
77
-
78
61
  // 上で作成されたシェル マネージャーを削除します。
79
62
  if (pShellManager != nullptr)
80
63
  {
IEViewDlg.cpp CHANGED
@@ -16,15 +16,14 @@
16
16
  // CIEViewDlg ダイアログ
17
17
 
18
18
  BEGIN_DHTML_EVENT_MAP(CIEViewDlg)
19
- DHTML_EVENT_ONCLICK(_T("ButtonOK"), OnButtonOK)
20
- DHTML_EVENT_ONCLICK(_T("ButtonCancel"), OnButtonCancel)
21
19
  END_DHTML_EVENT_MAP()
22
20
 
23
21
 
24
- CIEViewDlg::CIEViewDlg(CWnd* pParent /*=nullptr*/)
22
+ CIEViewDlg::CIEViewDlg(const CString& url, CWnd* pParent /*=nullptr*/)
25
23
  : CDHtmlDialog(IDD_IEVIEW_DIALOG, IDR_HTML_IEVIEW_DIALOG, pParent)
26
24
  {
27
25
  m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
26
+ m_url = url;
28
27
  }
29
28
 
30
29
  void CIEViewDlg::DoDataExchange(CDataExchange* pDX)
@@ -48,6 +47,9 @@
48
47
  SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定
49
48
 
50
49
  // TODO: 初期化をここに追加します。
50
+ int pos = m_url.ReverseFind(_T('/'));
51
+ this->SetWindowTextW(m_url.Mid(pos + 1));
52
+ this->Navigate(m_url);
51
53
 
52
54
  return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
53
55
  }
@@ -88,14 +90,14 @@
88
90
  return static_cast<HCURSOR>(m_hIcon);
89
91
  }
90
92
 
91
- HRESULT CIEViewDlg::OnButtonOK(IHTMLElement* /*pElement*/)
92
- {
93
- OnOK();
94
- return S_OK;
95
- }
96
-
97
- HRESULT CIEViewDlg::OnButtonCancel(IHTMLElement* /*pElement*/)
93
+ BOOL CIEViewDlg::PreTranslateMessage(MSG* pMsg)
98
94
  {
99
- OnCancel();
100
- return S_OK;
95
+ if (WM_KEYDOWN == pMsg->message) {
96
+ switch (pMsg->wParam) {
97
+ case VK_RETURN:
98
+ case VK_ESCAPE:
99
+ return FALSE;
100
+ }
101
+ }
102
+ return CDHtmlDialog::PreTranslateMessage(pMsg);
101
103
  }
IEViewDlg.h CHANGED
@@ -10,7 +10,7 @@
10
10
  {
11
11
  // コンストラクション
12
12
  public:
13
- CIEViewDlg(CWnd* pParent = nullptr); // 標準コンストラクター
13
+ CIEViewDlg(const CString& url, CWnd* pParent = nullptr); // 標準コンストラクター
14
14
 
15
15
  // ダイアログ データ
16
16
  #ifdef AFX_DESIGN_TIME
@@ -20,12 +20,10 @@
20
20
  protected:
21
21
  virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート
22
22
 
23
- HRESULT OnButtonOK(IHTMLElement *pElement);
24
- HRESULT OnButtonCancel(IHTMLElement *pElement);
25
-
26
23
  // 実装
27
24
  protected:
28
25
  HICON m_hIcon;
26
+ CString m_url;
29
27
 
30
28
  // 生成された、メッセージ割り当て関数
31
29
  virtual BOOL OnInitDialog();
@@ -33,4 +31,6 @@
33
31
  afx_msg HCURSOR OnQueryDragIcon();
34
32
  DECLARE_MESSAGE_MAP()
35
33
  DECLARE_DHTML_EVENT_MAP()
34
+ public:
35
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
36
36
  };

ソースコード(C#)

ウィザードで生成されたソースコードを少し変更するのみです。差分のみ表示です。


変更するのは、
Form1.Designer.cs
Form1.cs
Program.cs
の3つです。


主に以下の事を行っています。
WebBrowserの初期化
・引数の受け渡し
・引数の URL へ遷移

Form1.Designer.cs CHANGED
@@ -29,13 +29,38 @@
29
29
  /// </summary>
30
30
  private void InitializeComponent()
31
31
  {
32
- this.components = new System.ComponentModel.Container();
32
+ this.webBrowser1 = new System.Windows.Forms.WebBrowser();
33
+ this.SuspendLayout();
34
+ //
35
+ // webBrowser1
36
+ //
37
+ this.webBrowser1.AllowWebBrowserDrop = false;
38
+ this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
39
+ this.webBrowser1.IsWebBrowserContextMenuEnabled = false;
40
+ this.webBrowser1.Location = new System.Drawing.Point(0, 0);
41
+ this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20);
42
+ this.webBrowser1.Name = "webBrowser1";
43
+ this.webBrowser1.Size = new System.Drawing.Size(1096, 661);
44
+ this.webBrowser1.TabIndex = 0;
45
+ this.webBrowser1.Url = new System.Uri("", System.UriKind.Relative);
46
+ //
47
+ // Form1
48
+ //
49
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
33
50
  this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
34
- this.ClientSize = new System.Drawing.Size(800, 450);
51
+ this.ClientSize = new System.Drawing.Size(1096, 661);
52
+ this.Controls.Add(this.webBrowser1);
53
+ this.Name = "Form1";
54
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
35
55
  this.Text = "Form1";
56
+ this.ResumeLayout(false);
57
+
36
58
  }
37
59
 
38
60
  #endregion
61
+
62
+ private System.Windows.Forms.WebBrowser webBrowser1;
63
+ private string m_url;
39
64
  }
40
65
  }
41
66
 
Form1.cs CHANGED
@@ -12,9 +12,12 @@
12
12
  {
13
13
  public partial class Form1 : Form
14
14
  {
15
- public Form1()
15
+ public Form1( string url )
16
16
  {
17
+ m_url = url;
17
18
  InitializeComponent();
19
+ this.webBrowser1.Url = new System.Uri(m_url, System.UriKind.Absolute);
20
+ this.Text = m_url.Substring(m_url.LastIndexOf("/") + 1);
18
21
  }
19
22
  }
20
23
  }
Program.cs CHANGED
@@ -14,9 +14,13 @@
14
14
  [STAThread]
15
15
  static void Main()
16
16
  {
17
+ string[] args = Environment.GetCommandLineArgs();
18
+ string url = args[1];
19
+ url = url.Substring(url.IndexOf(":") + 1);
20
+
17
21
  Application.EnableVisualStyles();
18
22
  Application.SetCompatibleTextRenderingDefault(false);
19
- Application.Run(new Form1());
23
+ Application.Run(new Form1(url));
20
24
  }
21
25
  }
22
26
  }

C++ 版ビルド手順

exe ビルド

Visual Studio 2019 は、インストールしたての状態が前提です。

プロジェクト作成準備

Visual Studio Installer を起動します。
「変更」をクリックします。
Visual Studio Installerを起動 「変更」をクリック


「C++ によるデスクトップ開発」→ 右側の詳細部分の「最新の v142 ビルドツール C++ MFC (x86...」にチェックを入れ、「変更」をクリックします。 「最新のv142ビルドツール C++ MFC (x86...」にチェック


プロジェクト作成

Visual Studio Installer を閉じて、Visual Studio 2019 を起動します。
「新しいプロジェクトの作成」をクリックします。
「新しいプロジェクトの作成」をクリック


「MFC アプリ」を選択して、「次へ」をクリックします。 「MFCアプリ」を選択して、「次へ」をクリック


プロジェクト名:IEView
ソリューション名:IEView
とし、(入力内容は任意です。)「作成」をクリックします。 プロジェクト名 ソリューション名


左側ペインの「アプリケーションの種類のオプション」 「アプリケーションの種類」 : ダイアログベース 「ダイアログベースのオプション」 : HTML ダイアログを使用する とします。 「アプリケーションの種類のオプション」


左側ペインの「ユーザーインターフェース機能」をクリックします。 「最小化ボックス」「最大化ボックス」チェックボックスにチェックを入れ、「バージョン情報ボックス」のチェックを外します。(このあたりの選択は任意です。) 「ユーザーインターフェース機能」


左側ペインの「高度な機能」をクリックします。 「高度な機能:」のチェックを全て外します。(このあたりの選択は任意です。) 「完了」をクリックします。 「高度な機能」


ソースコード編集

この時点で、リポジトリパスにある程度のプログラムが作成されていますので、
(リポジトリパス例:C:\Users\admin\source\repos\IEView\IEView
github リポジトリ(itc-lab/IEView)

IEView.htm
IEView.cpp
IEViewDlg.cpp
IEViewDlg.h
の4つを上書きします。
4つを上書き


ビルド実行

いきなり本番ビルドするため、Release x86に変更します。 Release x86


「ビルド」→「IEView のビルド」をクリックします。 IEView のビルド


C:\Users\admin\source\repos\IEView\Release\IEView.exe
が作成されます。


msi ビルド

本ブログ別記事「カスタム URL スキームでエクスプローラーを起動してフォルダを開く msi ビルド全手順」「拡張機能インストール」の手順とほぼ同じですので、詳細は省略します。
概ね以下の手順になります。


拡張機能の Microsoft Visual Studio Installer Projects をインストールします。

IEView.sln ソリューションを開きます。

ファイル → 追加 → 新しいプロジェクト → 「Setup Project」選択し、「次へ」をクリックします。

プロジェクト名:IEViewInstaller とし、「作成」をクリックします。

「Application Folder」をクリックして、DefaultLocation の値を [LocalAppDataFolder]IEView とします。

「Application Folder」選択状態で、右ペインを右クリック →「Add」→「ファイル」をクリックします。

ビルド済みの IEView.exe
例:C:\Users\admin\source\repos\IEView\Release\IEView.exe
を追加します。

レジストリエディタ―に切り替えます。

HKEY_CLASSES_ROOT のところで、右クリック →「新しいキー」をクリックします。
以降、同要領で、 HKEY_CLASSES_ROOT\ieview\shell\open\command まで作成します。

command を選択し、右ペインを右クリック →「New」→「文字列の値」をクリックします。

Name を空白にします。※「New Value #1」を空白にすると、「(Default)」になります。

(Default)をクリックして、Value の値を "[TARGETDIR]IEView.exe" "%1" とします。

HKEY_CLASSES_ROOT\ieview をクリックして、
Name: (Default)
Value: URL: IEView

Name: URL Protocol
(Value は何も登録しません。)
を登録します。

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION までキーを作成します。

右ペインを右クリック →「New」→「DWORD の値」をクリックします。

Name: IEView.exe
Value: 11001
を登録します。

FEATURE_BROWSER_EMULATION

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION

IEView.exe = REG_DWORD 0x00002af9(11001) を登録する理由は、IE11モードで起動したいからです。

デフォルトは、IE7互換表示モードです。


「ビルド」→「IEViewInstaller のビルド」をクリックして、IEViewIntaller.msi ができます。
(例:C:\Users\admin\source\repos\IEView\IEViewInstaller\Release\IEViewIntaller.msi


C# 版ビルド手順

exe ビルド

Visual Studio 2019 は、インストールしたての状態が前提です。

プロジェクト作成準備

Visual Studio Installer を起動します。
「変更」をクリックします。
Visual Studio Installerを起動 「変更」をクリック


「.NET デスクトップ開発」→ 右側の詳細部分はそのままにして、「変更」をクリックします。 「.NET デスクトップ開発」


プロジェクト作成

Visual Studio Installer を閉じて、Visual Studio 2019 を起動します。
「新しいプロジェクトの作成」をクリックします。
「新しいプロジェクトの作成」をクリック


「Windows フォームアプリケーション (.NET Framework)」を選択して、「次へ」をクリックします。 「Windows フォームアプリケーション (.NET Framework)」


プロジェクト名:IEViewCS
ソリューション名:IEViewCS
とし、(入力内容は任意です。)「作成」をクリックします。 プロジェクト名 ソリューション名


ソースコード編集

この時点で、リポジトリパスにある程度のプログラムが作成されていますので、
(リポジトリパス例:C:\Users\admin\source\repos\IEViewCS\IEViewCS
github リポジトリ(itc-lab/IEViewCS)

Program.cs
Form1.Designer.cs
Form1.cs
の3つを上書きします。
3つを上書き


ビルド実行

いきなり本番ビルドするため、Release Any CPU に変更します。 Release Any CPU


「ビルド」→「IEViewCS のビルド」をクリックします。 IEViewCS のビルド


C:\Users\admin\source\repos\IEViewCS\Release\IEViewCS.exe
が作成されます。


msi ビルド

本ブログ別記事「カスタム URL スキームでエクスプローラーを起動してフォルダを開く msi ビルド全手順」「拡張機能インストール」の手順とほぼ同じですので、詳細は省略します。
概ね以下の手順になります。


拡張機能の Microsoft Visual Studio Installer Projects をインストールします。

IEViewCS.sln ソリューションを開きます。

ファイル → 追加 → 新しいプロジェクト → 「Setup Project」選択し、「次へ」をクリックします。

プロジェクト名:IEViewCSInstaller とし、「作成」をクリックします。

「Application Folder」をクリックして、DefaultLocation の値を [LocalAppDataFolder]IEViewCS とします。

「Application Folder」選択状態で、右ペインを右クリック →「Add」→「ファイル」をクリックします。

ビルド済みの IEViewCS.exe
例:C:\Users\admin\source\repos\IEViewCS\bin\IEViewCS.exe
を追加します。

レジストリエディタ―に切り替えます。

HKEY_CLASSES_ROOT のところで、右クリック →「新しいキー」をクリックします。
以降、同要領で、 HKEY_CLASSES_ROOT\ieviewcs\shell\open\command まで作成します。

command を選択し、右ペインを右クリック →「New」→「文字列の値」をクリックします。

Name を空白にします。※「New Value #1」を空白にすると、「(Default)」になります。

(Default)をクリックして、Value の値を "[TARGETDIR]IEViewCS.exe" "%1" とします。

HKEY_CLASSES_ROOT\ieviewcs をクリックして、
Name: (Default)
Value: URL: IEViewCS

Name: URL Protocol
(Value は何も登録しません。)
を登録します。

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION までキーを作成します。

右ペインを右クリック →「New」→「DWORD の値」をクリックします。

Name: IEViewCS.exe
Value: 11001
を登録します。

FEATURE_BROWSER_EMULATION IEViewCS.exe

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION

IEView.exe = REG_DWORD 0x00002af9(11001) を登録する理由は、IE11モードで起動したいからです。

デフォルトは、IE7互換表示モードです。


「ビルド」→「IEViewCSInstaller のビルド」をクリックして、IEViewCSIntaller.msi ができます。
(例:C:\Users\admin\source\repos\IEViewCS\IEViewCSInstaller\Release\IEViewCSIntaller.msi


動作例

C++版動作例です。
Edge から IE11 の画面が開き、ActiveX が起動しています。

C++版動作例


C#版の方もほとんど同じです。

C++版動作例


IE11で開くと、以下のような感じです。

C++版動作例

loading...