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...