ウィンドウには多くのコントロールがあります。要件は、コントロールの失われたフォーカス イベントからどのコントロールがフォーカスを取得するかを知ることです。
たとえば、テキスト ボックスにフォーカスがあります。今、私はボタンをクリックしています。これを行っている間、テキストボックスのフォーカスイベントからフォーカスをボタンに移動していることを知る必要があります。
それで、どうすればこれを達成できますか..
ウィンドウには多くのコントロールがあります。要件は、コントロールの失われたフォーカス イベントからどのコントロールがフォーカスを取得するかを知ることです。
たとえば、テキスト ボックスにフォーカスがあります。今、私はボタンをクリックしています。これを行っている間、テキストボックスのフォーカスイベントからフォーカスをボタンに移動していることを知る必要があります。
それで、どうすればこれを達成できますか..
これは私がやったことであり、私のために働いています
protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
lostFocusControl = e.OldFocus;
}
private void PauseBttn_PreviewKeyDown(object sender, KeyEventArgs e)
{
/**invoke OnPreviewLostKeyboardFocus handller**/
}
それが役立つことを願っています
次のクラスは、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);
}
}