Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当WPF应用程序';s控制聚焦_C#_Wpf_Setwindowshookex - Fatal编程技术网

C# 当WPF应用程序';s控制聚焦

C# 当WPF应用程序';s控制聚焦,c#,wpf,setwindowshookex,C#,Wpf,Setwindowshookex,我正试图使用SetWindowsHookEx将标题跟踪添加到我的时间跟踪器窗口中,但它只能部分工作。以下是我用来向订阅者提供共同响应事件的代码: public class Hooks { #region DllImport delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread,

我正试图使用
SetWindowsHookEx
将标题跟踪添加到我的时间跟踪器窗口中,但它只能部分工作。以下是我用来向订阅者提供共同响应事件的代码:

public class Hooks
{
    #region DllImport

    delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

    [DllImport("user32.dll")]
    static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

    private const uint WINEVENT_SKIPOWNPROCESS = 2;
    private const uint WINEVENT_SKIPOWNTHREAD = 1;
    private const uint WINEVENT_OUTOFCONTEXT = 0;
    private const uint EVENT_SYSTEM_FOREGROUND = 3;

    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); 

    #endregion DllImport

    public static event EventHandler<EventArgs<string>> WindowActivated;

    public void Bind()
    {
        var listener = new WinEventDelegate(EventCallback);
        var result = SetWinEventHook(EVENT_SYSTEM_FOREGROUND,
                        EVENT_SYSTEM_FOREGROUND,
                        IntPtr.Zero,
                        listener,
                        0,
                        0,
                        (WINEVENT_OUTOFCONTEXT));
    }

    private static void EventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd,
                                      int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        System.Diagnostics.Debug.Write("EventCallback enter!");

        if (eventType == EVENT_SYSTEM_FOREGROUND)
        {
            var buffer = new StringBuilder(300);
            var handle = GetForegroundWindow();

            System.Diagnostics.Debug.Write(string.Format("EventCallback GetWindowText: {0}, '{1}'",
                GetWindowText(handle, buffer, 300),
                buffer));

            if (GetWindowText(handle, buffer, 300) > 0 && WindowActivated != null)
            {
                System.Diagnostics.Debug.Write(string.Format(
                    "Calling handlers for WindowActivated with buffer='{0}'",
                    buffer));
                WindowActivated(handle, new EventArgs<string>(buffer.ToString()));
            } 
        }

        System.Diagnostics.Debug.Write("EventCallback leave!");
    }
}
公共类钩子
{
#德林波特地区
委托void WinEventDelegate(IntPtr hWinEventHook、uint eventType、IntPtr hwnd、int idObject、int idChild、uint dwEventThread、uint dwmsEventTime);
[DllImport(“user32.dll”)]
静态外部IntPtr SetWinEventHook(uint-eventMin、uint-eventMax、IntPtr-hmodWinEventProc、WinEventDelegate-lpfnWinEventProc、uint-idProcess、uint-idThread、uint-dwFlags);
私家侦探WINEVENT_SKIPOWNPROCESS=2;
私家侦探WINEVENT_SKIPOWNTHREAD=1;
私家侦探WINEVENT_OUTOFCONTEXT=0;
私人建筑事件系统前景=3;
[DllImport(“user32.dll”)]
静态外部IntPtr GetForegroundWindow();
[DllImport(“user32.dll”)]
静态外部int GetWindowText(IntPtr hWnd、StringBuilder文本、int计数);
#端域DllImport
已激活公共静态事件事件处理程序窗口;
公共无效绑定()
{
var listener=newwineventdelegate(EventCallback);
var结果=SetWinEventHook(事件、系统、前景、,
事件\系统\前台,
IntPtr.Zero,
听众,
0,
0,
(WINEVENT_out of context));
}
私有静态void EventCallback(IntPtr hwinethook、uint eventType、IntPtr hwnd、,
int idObject、int idChild、uint dwEventThread、uint dwmsEventTime)
{
System.Diagnostics.Debug.Write(“EventCallback回车!”);
if(eventType==事件\系统\前台)
{
var buffer=新的StringBuilder(300);
var handle=GetForegroundWindow();
System.Diagnostics.Debug.Write(string.Format(“EventCallback GetWindowText:{0},{1}”),
GetWindowText(句柄、缓冲区、300),
缓冲区);
if(GetWindowText(句柄,缓冲区,300)>0&&WindowActivated!=null)
{
System.Diagnostics.Debug.Write(string.Format(
“使用缓冲区={0}”调用WindowActivated的处理程序,
缓冲区);
WindowActivated(句柄,新事件参数(buffer.ToString());
} 
}
System.Diagnostics.Debug.Write(“EventCallback leave!”);
}
}
我有一个带有单个
Textbox
的主ui WPF应用程序,我将钩子事件绑定到文本框内容。当我运行它时,它看起来工作正常,直到它自己聚焦。也就是说,如果我点击WPF窗口的texbox,钩子将停止工作约30-40秒。在这之后,事件捕获就可以工作了,但是再次工作——直到主WPF窗口变为活动状态


你知道它是什么以及如何修复吗?

我使用标准Visual Studio模板(VS2012;.NET 4.5)创建了一个新的WPF应用程序。然后,我替换了XAML和代码,如下所示:

main window.xaml

<Window x:Class="stackoverflowtest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow">
    <Grid>
        <StackPanel VerticalAlignment="Top" Margin="15">
            <TextBox x:Name="_tb" />
            <Button Content="Does Nothing" HorizontalAlignment="Left" Margin="0,15" />
        </StackPanel>
    </Grid>
</Window>
对我来说,这很好用。我可以在不同的应用程序之间切换,它们的窗口标题反映在WPF应用程序的文本框中。即使文本框已聚焦,也没有延迟。我添加了一个DoNothing
按钮
控件,以证明无论texbox还是按钮是聚焦的,它都不会改变行为


我只能假设您遇到的问题与您在事件处理程序中执行的操作有关,或者与某种线程问题有关。

原因可能是委托被垃圾收集,因为它被分配到局部变量中。这就是为什么它在30-40秒后停止工作。

您需要跟踪自己的WPF应用程序吗?如果不是,你就不能将
WINEVENT\u SKIPOWNPROCESS
传递给
SetWinEventHook
调用,或者将回调函数接收到的
hwnd
与你自己的窗口句柄进行比较,从而过滤掉它。@Steven Rands我用你指定的标志对它进行了测试。它没有改变。你是如何设置标志的?您需要这样传递它们:
WINEVENT\u out of context\124winevent\u SKIPOWNPROCESS
。我在这里用一个测试WPF应用程序尝试过,当应用程序本身成为前台窗口时,它肯定会阻止调用
EventCallback
方法。刚才又测试了一次。编译应用程序,运行它,在切换到文本框时检查VS title是否显示在文本框中。在点击应用程序窗口之后,如果切换到另一个窗口(FAR、VS、记事本等),文本框未刷新事件。这就是问题所在。是的,你的样品有效。它看起来像是UI和core的不同程序集引起的问题。钩子类放置在核心组件中。这就是问题所在。
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace stackoverflowtest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            _hooks = new Hooks(_tb);
            _hooks.Bind();
        }

        readonly Hooks _hooks;
    }

    public class Hooks
    {
        public Hooks(TextBox textbox)
        {
            _listener = EventCallback;
            _textbox = textbox;
        }

        readonly WinEventDelegate _listener;
        readonly TextBox _textbox;
        IntPtr _result;

        public void Bind()
        {
            _result = SetWinEventHook(
                EVENT_SYSTEM_FOREGROUND,
                EVENT_SYSTEM_FOREGROUND,
                IntPtr.Zero,
                _listener,
                0,
                0,
                WINEVENT_OUTOFCONTEXT
                );
        }

        void EventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild,
            uint dwEventThread, uint dwmsEventTime)
        {
            var windowTitle = new StringBuilder(300);
            GetWindowText(hwnd, windowTitle, 300);
            _textbox.Text = windowTitle.ToString();
        }

        #region P/Invoke
        const uint WINEVENT_OUTOFCONTEXT = 0;
        const uint EVENT_SYSTEM_FOREGROUND = 3;

        [DllImport("user32.dll")]
        static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc,
            WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

        [DllImport("user32.dll")]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

        delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject,
            int idChild, uint dwEventThread, uint dwmsEventTime);
        #endregion
    }
}