2

ウィンドウには多くのコントロールがあります。要件は、コントロールの失われたフォーカス イベントからどのコントロールがフォーカスを取得するかを知ることです。

たとえば、テキスト ボックスにフォーカスがあります。今、私はボタンをクリックしています。これを行っている間、テキストボックスのフォーカスイベントからフォーカスをボタンに移動していることを知る必要があります。

それで、どうすればこれを達成できますか..

4

4 に答える 4

3

これは私がやったことであり、私のために働いています

 protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
   {
     lostFocusControl = e.OldFocus;
   }

   private void PauseBttn_PreviewKeyDown(object sender, KeyEventArgs e)
   {
      /**invoke OnPreviewLostKeyboardFocus handller**/
   }

それが役立つことを願っています

于 2013-07-23T12:58:25.467 に答える
0

次のクラスは、FocusManager でフォーカスの変更を監視します。これはループ スレッドであるため、実行中という事実に我慢する必要がありますが、フォーカスが変更されると、何が変更されたかを知らせるイベントが発生します。

これら 2 つのクラスをプロジェクトに追加するだけです。

    public class FocusNotifierEventArgs : EventArgs
    {
        public object OldObject { get; set; }
        public object NewObject { get; set; }
    }

    public class FocusNotifier : IDisposable
    {
        public event EventHandler<FocusNotifierEventArgs> OnFocusChanged;
        bool isDisposed;
        Thread focusWatcher;
        Dispatcher dispatcher;
        DependencyObject inputScope;
        int tickInterval;

        public FocusNotifier(DependencyObject inputScope, int tickInterval = 10)
        {
            this.dispatcher = inputScope.Dispatcher;
            this.inputScope = inputScope;
            this.tickInterval = tickInterval;
            focusWatcher = new Thread(new ThreadStart(FocusWatcherLoop))
            {
                Priority = ThreadPriority.BelowNormal,
                Name = "FocusWatcher"
            };
            focusWatcher.Start();
        }

        IInputElement getCurrentFocus()
        {
            IInputElement results = null;
            Monitor.Enter(focusWatcher);
            dispatcher.BeginInvoke(new Action(() =>
                {
                    Monitor.Enter(focusWatcher);
                    results = FocusManager.GetFocusedElement(inputScope);
                    Monitor.Pulse(focusWatcher);
                    Monitor.Exit(focusWatcher);
                }));
            Monitor.Wait(focusWatcher);
            Monitor.Exit(focusWatcher);
            return results;
        }

        void FocusWatcherLoop()
        {
            object oldObject = null;
            while (!isDisposed)
            {
                var currentFocus = getCurrentFocus();
                if (currentFocus != null)
                {
                     if (OnFocusChanged != null)
                        dispatcher.BeginInvoke(OnFocusChanged, new object[]{ this,  new FocusNotifierEventArgs()
                        {
                            OldObject = oldObject,
                            NewObject = currentFocus
                        }});
                    oldObject = currentFocus;
                    }
                }
                Thread.Sleep(tickInterval);
            }
        }

        public void Dispose()
        {
            if (!isDisposed)
            {
                isDisposed = true;
            }
        }
    }

次に、コード ビハインドで、Focus Notifier クラスの新しいインスタンスを作成し、その OnFocusChanged イベントにフックします。最後に破棄することを忘れないでください。そうしないと、スレッドがアプリを開いたままにします。

public partial class MainWindow : Window
{
    FocusNotifier focusNotifier;

    public MainWindow()
    {
        InitializeComponent();
        focusNotifier = new FocusNotifier(this);
        focusNotifier.OnFocusChanged += focusNotifier_OnFocusChanged;
    }

    void focusNotifier_OnFocusChanged(object sender, FocusNotifierEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine(e.OldObject);
        System.Diagnostics.Debug.WriteLine(e.NewObject);

    }

    protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
    {
        focusNotifier.Dispose();
        base.OnClosing(e);
    }
}
于 2013-07-23T13:21:59.970 に答える