Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.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# 捕捉活动窗口开关(也在同一应用程序中,例如Chrome选项卡)_C#_Windows_Winapi_Events - Fatal编程技术网

C# 捕捉活动窗口开关(也在同一应用程序中,例如Chrome选项卡)

C# 捕捉活动窗口开关(也在同一应用程序中,例如Chrome选项卡),c#,windows,winapi,events,C#,Windows,Winapi,Events,我正在开发跟踪活动并将其记录到数据库的工具(稍后将添加,我目前正在TextBox中测试)。因此,它将读取活动窗口标题并计算在每个窗口上花费的时间 我知道有一个解决办法 但我注意到,如果谷歌浏览器被打开,我在标签之间切换,它不会做出反应。我必须点击其他窗口,然后点击Chrome选项卡,在这种情况下,检测到活动窗口开关 我在想,也许可以通过每X秒运行一次CheckForWindowTitle(),并与当前的GetActiveWindowTitle.GetActiveWindowTitleMethod

我正在开发跟踪活动并将其记录到数据库的工具(稍后将添加,我目前正在TextBox中测试)。因此,它将读取活动窗口标题并计算在每个窗口上花费的时间

我知道有一个解决办法

但我注意到,如果谷歌浏览器被打开,我在标签之间切换,它不会做出反应。我必须点击其他窗口,然后点击Chrome选项卡,在这种情况下,检测到活动窗口开关

我在想,也许可以通过每X秒运行一次
CheckForWindowTitle()
,并与当前的
GetActiveWindowTitle.GetActiveWindowTitleMethod()
进行比较来解决这个问题,如果它们不匹配,则改为
CheckForWindowTitle()
。有没有更好的解决办法

GetActiveWindowTitle.cs:

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace Activitytracker
{
    class GetActiveWindowTitle
    {
        public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

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

        public const uint WINEVENT_OUTOFCONTEXT = 0;
        public 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);

        public static string GetActiveWindowTitleMethod()
        {
            const int nChars = 256;
            IntPtr handle = IntPtr.Zero;
            StringBuilder Buff = new StringBuilder(nChars);
            handle = GetForegroundWindow();

            if (GetWindowText(handle, Buff, nChars) > 0)
            {
                return Buff.ToString();
            }
            return null;
        }

    }
}
MainWindow.xaml.cs:

    GetActiveWindowTitle.WinEventDelegate dele = null;
    Stopwatch stopwatch = new Stopwatch();

    public MainWindow()
    {
        InitializeComponent();

        dele = new GetActiveWindowTitle.WinEventDelegate(WinEventProc);
        IntPtr m_hhook = GetActiveWindowTitle.SetWinEventHook(GetActiveWindowTitle.EVENT_SYSTEM_FOREGROUND,
            GetActiveWindowTitle.EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, GetActiveWindowTitle.WINEVENT_OUTOFCONTEXT);

        //_ = CheckForWindowTitle();

    }

    public async Task CheckForWindowTitle()
    {
        while (true)
        {
            var delayTask = Task.Delay(100);
            TextBoxMain.Text = GetActiveWindowTitle.GetActiveWindowTitleMethod();
            await delayTask;
        }
    }

    public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject,
        int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        stopwatch.Stop();
        var milliSeocnds = stopwatch.ElapsedMilliseconds;
        var timeSpan = stopwatch.Elapsed;
        var CurrentDate = DateTime.Now;

        TextBoxMain.Text += GetActiveWindowTitle.GetActiveWindowTitleMethod() + " " + timeSpan + " " + CurrentDate + "\r\n";

        stopwatch.Start();
    }

编辑:

我不确定效率,但如果有人感兴趣,这里有一些进展(它也在跟踪Chrome和其他应用程序中的每个窗口):


编辑2:

我现在一直在尝试下面的答案中提供的工作方法。我需要分配变量,以便在以下情况下使用它:

        dele = new GetActiveWindowTitle.WinEventDelegate(WinEventProc);
        IntPtr m_hhook = GetActiveWindowTitle.SetWinEventHook(GetActiveWindowTitle.EVENT_OBJECT_FOCUS,
            GetActiveWindowTitle.EVENT_OBJECT_FOCUS, IntPtr.Zero, dele, 0, 0, GetActiveWindowTitle.WINEVENT_OUTOFCONTEXT);
我试过:

public const uint EVENT_OBJECT_FOCUS = 3;
但这些都不起作用

方法如下:

    public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd,
        int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        GetActiveWindowTitle.stopwatch.Stop();

        milliSeocnds = GetActiveWindowTitle.stopwatch.ElapsedMilliseconds;
        timeSpan = GetActiveWindowTitle.stopwatch.Elapsed;
        CurrentDate = DateTime.Now;

        MainProcess.AddRecordToDatatable(GetActiveWindowTitle.GetActiveWindowTitleMethod(),
            milliSeocnds / 1000, CurrentDate, MainProcess.AdminHoursCode, MainProcess.userName);

        // Group DataTable records
        MainProcess.OrganizeDataTable();

        ActivityLogGrid.ItemsSource = MainProcess.ActivityLogGrouped.DefaultView;

        GetActiveWindowTitle.stopwatch.Start();
    }
经过一些测试,它应该是

public const uint EVENT_OBJECT_FOCUS = 0x8005;
但我注意到,如果谷歌浏览器被删除,它不会做出反应 打开,我在选项卡之间切换


在选项卡之间切换会导致焦点改变,因此您可以使用(另外)来涵盖这种情况。

谢谢您的提示!我现在已经尝试过这种方法,但还没有成功。将
事件\系统\前景=3
更改为
事件\对象\焦点=0x8005
。这是正确的方法吗?@哈曼这一行(C++中,<代码> StWiNeVeSooCK(EnvivObjutsFixFielk,EnvivObjutsFixCar,NULL,WEVEESTPROC,0, 0,Win事件,OutoFrEnter);<代码>当您单击Chrome的选项卡时,将为您获取
EVENT\u OBJECT\u FOCUS
事件。@hatman您是否能够接收EVENT\u OBJECT\u FOCUS EVENT?我已经开始循环,但我认为正确的方法是使用您提供的上述解决方案。为了测试你的解决方案,我必须重写“两行”。我会在本周尝试这样做,并发布回复或接受答案。抱歉耽搁了。还没有时间继续此项目。看起来它应该是
public consuint EVENT\u OBJECT\u FOCUS=0x8005。这似乎是正确的变量。使用其他进程触发该方法。
public const uint EVENT_OBJECT_FOCUS = 0x8005;