2009-05-07 30 views
19

WPFでUIコントロールを開発して、既存のWindows Forms/MFCアプリケーションエンジン(Rhino 3D)で使用するようにしています。WPF TextBoxはElementHostのウィンドウフォームでの入力を受け付けません

アプリケーションエンジンは、本質的にWindows FormsコントロールをEnginesインターフェイスにドックすることができる子ウィンドウ内に配置できる「Dockbar」を作成する機能を公開しています。

Dockbarに追加されたElementHostコントロール内に単純なWPF TextBoxを配置しようとしています。一見するとこれはうまくいくように見えます。 TextBoxに入力しようとすると、特定のシーケンスだけが実際にTextBoxに表示されます。 BACKSPACECOPYPASTE、および選択TEXT作業を削除します。 A-Z、1-9などを入力すると、それらのキーは表示されません。

私はネットを狙っており、ElementHost.EnableModelessKeyboardInterop()について聞いたことがありますが、これはフォームから作成されたWPF Windowsにのみ適用されます。 WPF UserControlsを作成し、ElementHostコントロールでそれらをホストしています。 keyUpイベント PreviewKeyDown、PreviewKeyUp

System.Windows.Threading.Dispatcher.Run(); 

は私がDispatcher.Run()の話のポストを見て、それは一種の動作しますが、フォームの残りの部分を壊します、KeyDownイベントはすべてTextBoxで発生しますが、テキストボックスにはテキストが表示されません。

私はWindowsのメッセージについてよく分かりませんが、WinSpectorを使用すると、TextBoxからWM_GETTEXTメッセージが届いていないことに気付きました(わからない場合でも)。

また、新しいWindowsフォームプロジェクトを作成して同じことを行ったため、うまく動作するため、ウィンドウの作成方法とRhino 3Dエンジン内のドッキング方法に問題があります。ここで

は動作しませんサンプルコードです:

ElementHost el = new ElementHost(); 
System.Windows.Controls.TextBox t = new System.Windows.Controls.TextBox(); 
t.Width = 100; 
t.Text = "TEST"; 
el.Child = t; 
panel1.Controls.Add(el); 

答えて

19

私は最終的にMFCダイアログウィンドウがWM_CHARを取っていた...ヘッドscatchingの2日後に

それを考え出しましたメッセージが制御され、入力が処理されなくなります。だからこれを防ぐために、私はHwndSourceをフックし、私がWM_GETDLGCODEというメッセージを受け取るたびに、受け入れる入力のタイプを返答し、そのイベントを処理済みとしてマークします。

私は(下記参照)、すべてのテキストボックスを修正する必要がないようにするために、私自身のテキストボックスを作成しました:

/// <summary> 
    /// Interop Enabled TextBox : This TextBox will properly handle WM_GETDLGCODE Messages allowing Key Input 
    /// </summary> 
    class IOTextBox : TextBox 
    { 
     private const UInt32 DLGC_WANTARROWS = 0x0001; 
     private const UInt32 DLGC_WANTTAB = 0x0002; 
     private const UInt32 DLGC_WANTALLKEYS = 0x0004; 
     private const UInt32 DLGC_HASSETSEL = 0x0008; 
     private const UInt32 DLGC_WANTCHARS = 0x0080; 
     private const UInt32 WM_GETDLGCODE = 0x0087; 

     public IOTextBox() : base() 
     { 
      Loaded += delegate 
          { 
           HwndSource s = HwndSource.FromVisual(this) as HwndSource; 
           if (s != null) 
            s.AddHook(new HwndSourceHook(ChildHwndSourceHook)); 
          }; 
     } 

     IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
     { 
      if (msg == WM_GETDLGCODE) 
      { 
       handled = true; 
       return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL); 
      } 
      return IntPtr.Zero; 
     } 
    } 
+0

ありがとう、これは私が必要としていたものです。私はそれをUserControlに入れました.IvanHは以下のように提案しました。魅力的な作品! –

+0

ありがとう!これは今日私たちのための問題として浮上し、これはすぐにそれを解決しました! –

9

この非常に同じことについて自分の質問をチェックしてください。wxWidgetsの親ウィンドウと私は同様の問題を持っている

Window window1 = new Window(); 
ElementHost.EnableModelessKeyboardInterop(window1); 
window1.Show(); 

Why is my WPF textbox "kinda" readonly?

+3

実際に私の質問では、あなたの解決策は、私はウィンドウではない、MFCダイアログウィンドウ内のElementHost内のUserControl、適用されないと述べた... –

+3

あなたの右、私の悪い。私は細心の注意を払わなかったためにそれに値する。 – Russ

6

と埋め込まれたWPFのTextBoxコントロール:しかし、最後に、あなたが必要なのは、このようなものです。私はChildHwndSourceHookを付けることはキーボード入力を受けないという問題を解決しますが、時折重複したスペース文字で終わってしまうことがわかりました。 WM_KEYDOWNメッセージはスペース文字を確実に処理するようですが、一部のスペースについては重複したWM_CHARメッセージも受信されます。これを解決するために、私は単純にWM_CHARの空白文字を無視するChildHwndSourceHook機能、本体に次の句を追加しました:

 const UInt32 WM_CHAR = 0x0102; 

     if (msg == WM_CHAR) 
     { 
      // avoid duplicated spaces when parent window is a native window 
      if (wParam.ToInt32() == 32) 
       handled = true; 
     } 
+0

男、デバッグの1日後に人生を救った...私は入力キーと同様の問題を抱えている、時には2回送られた。 WM_KEYDOWN - WM_CHAR - WM_KEYUP、これは注文でした。 Enter LookのWM_CHARを「食べる」ことは倍増の問題を修正する以外は何の問題も生じません。 – Zotyi

5

派生テキストボックスを作成する必要はありません。 IOTextBoxのコードは、テキストボックスをホストするUserControlで使用できます。 VS2010パッケージで使用されているカスタムオプションページに使用されているWPFコントロールを使用して正常にテストしました。

関連する問題