C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

モードレスフォーム上のWebBrowserでのタブキー有効化


(過去ログ 106 を表示中)

[トピック内 1 記事 (1 - 1 表示)]  << 0 >>

■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);
                    }
                }
            }
        }
    }
}


引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -