■63502 / inTopicNo.1) |
モードレスフォーム上のWebBrowserでのタブキー有効化 |
□投稿者/ ななお (1回)-(2012/09/02(Sun) 16:00:04)
|
分類:[C#]
お世話になっております。皆様のご意見を頂戴できますでしょうか。
開発環境:VisualStudio2005
使用言語:C# 2.0
InternetExplorerで表示したHTMLページ内JScriptから、ActiveXObjectオブジェクトを使用して、C#で作成したDLLを
インスタンス化し、DLLのメソッドを呼び出してモードレスフォームを表示しています。
このモードレスフォームには、.NETのWebBrowserコントロールが貼り付けられており、この中に別のWebページを表示
しています。
# 普通にJavaScriptでwindow.openしたかったけれど、それでは別の要件を満たせずやむなくC#のフォームを表示する
# かたちとなっております。
しかし、実際にWebBrowserコントロール内でページを表示させると、タブキーによるページ内のフォーカス移動が出来ない、
という問題で困っております。
まず、そもそもDLLから表示したモードレスフォームでは、タブキーは有効にならないという「仕様」ということでした。
↓MSの該当KB。「PRB: DLL 内のモードレスのダイアログ ボックスが処理されない Tab キー」
http://support.microsoft.com/kb/233263
これを回避するため、上記KBにもあるように、以下を参考にしてWindowsメッセージをフックすることで、ひとまずモードレス
フォーム上のコントロール間において、タブキーを用いたフォーカス移動が出来るようになりました。
参考ページ:
Winform keyboard doesn't work when called modeless from VB6
http://www.dotnet247.com/247reference/msgs/49/245508.aspx
Windows Hooks in the .NET Framework
http://msdn.microsoft.com/ja-jp/magazine/cc188966%28en-us%29.aspx#edupdate
しかし、WebBrowserコントロールをフォーカスし、その中に表示したHTMLページのボタンやリンクをフォーカスさせた状態で
タブキーを押しても、HTMLページ内のフォーカスは移動せず、WebBrowserコントロールの次のタブインデックスを持つコント
ロールにフォーカスが移ってしまいます。
これを、WebBrowserコントロールで表示したページ内でのタブキーによるフォーカス移動を可能にするには、どのようにすれば
よいのでしょうか?
-- HTMLページ内のスクリプト部分
<script language="jscript">
function openDotNetForm() {
// 名前空間ActiveXSampleのControllerクラスをインスタンス化
var obj = new ActiveXObject("ActiveXSample.Controller");
// モードレスフォームを開くメソッドを呼ぶ
obj.OpenMainForm();
}
</script>
----
-- C#ソース
-- 上記「Windows Hooks in the .NET Framework」からダウンロードした「WindowsHook.cs」も取り込んでいます。
// COM公開のためのインターフェース(IController.cs)
using System;
using System.Collections.Generic;
using System.Text;
namespace ActiveXSample
{
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.InterfaceType(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsDual)]
[System.Runtime.InteropServices.Guid("D62189BE-C74D-46f5-8223-E0B8EC508BE5")]
interface IController
{
void OpenMainForm();
}
}
// IControllerの実装クラス(Controller.cs)
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ActiveXSample
{
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDispatch)]
[System.Runtime.InteropServices.Guid("36fafa84-91be-4d6b-a916-bc6667677b65")]
public class Controller : IController
{
public void OpenMainForm()
{
MainForm frm = new MainForm();
// モードレス表示
frm.Show();
}
}
}
// モードレス表示するフォーム
// フォーム上に、WebBrowserコントロールと数個のボタンがある
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ActiveXSample
{
public partial class MainForm : Form
{
[StructLayout(LayoutKind.Sequential)]
struct MSG
{
IntPtr hwnd;
uint Msg;
IntPtr wParam;
IntPtr lParam;
int time;
//POINT pt
int x;
int y;
}
[DllImport("user32.dll")]
private static extern int IsDialogMessage(IntPtr hDlg, IntPtr lpMsg);
private MsdnMag.LocalWindowsHook lwh;
public MainForm()
{
InitializeComponent();
lwh = new MsdnMag.LocalWindowsHook(MsdnMag.HookType.WH_GETMESSAGE);
lwh.HookInvoked += new MsdnMag.LocalWindowsHook.HookEventHandler(lwh_HookInvoked);
}
protected override void WndProc(ref Message m)
{
const int WM_CREATE = 0x0001;
const int WM_DESTROY = 0x0002;
if (m.Msg == WM_CREATE)
{
lwh.Install();
}
if (m.Msg == WM_DESTROY)
{
lwh.Uninstall();
}
base.WndProc(ref m);
}
private void lwh_HookInvoked(object sender, MsdnMag.HookEventArgs e)
{
const int WM_NULL = 0;
const int PM_REMOVE = 0x0001;
const int WM_KEYFIRST = 0x0100;
const int WM_KEYLAST = 0x0109;
if (e.HookCode >= 0 && new IntPtr(PM_REMOVE) == e.wParam)
{
uint msg = (uint)Marshal.ReadInt32(e.lParam, Marshal.OffsetOf(typeof(MSG), "Msg").ToInt32());
if (msg >= WM_KEYFIRST && msg <= WM_KEYLAST)
{
if (IsDialogMessage(this.Handle, e.lParam) != 0)
{
Marshal.WriteInt32(e.lParam, Marshal.OffsetOf(typeof(MSG), "Msg").ToInt32(), WM_NULL);
Marshal.WriteInt32(e.lParam, Marshal.OffsetOf(typeof(MSG), "wParam").ToInt32(), 0);
Marshal.WriteInt32(e.lParam, Marshal.OffsetOf(typeof(MSG), "lParam").ToInt32(), 0);
}
}
}
}
}
}
|
|