通过SendMessage函数或异步的东西GetForegroundWindow? [英] asynchronously GetForegroundWindow via SendMessage or something?

查看:380
本文介绍了通过SendMessage函数或异步的东西GetForegroundWindow?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有得到通知时,焦点更改任何窗口到另一个窗口(甚至是Windows应用程序之间),这样我就可以有我的代表呼吁立即当用户将焦点更改??的一种方式

Is there a way to be notified of when focus changes from any window to another window(even between windows applications) such that I can just have my delegate called immediately when the user changes focus??

我一直在想我可能只是需要做轮询:( :(每1秒,并调用GetForegroundWindow,但我真的不想这样做。

I keep thinking I may just have to do polling :( :( every 1 second and call GetForegroundWindow but I really don't want to do that.

推荐答案

SetWinEventHook()可能是你最好的选择;你可以听要么EVENT_SYSTEM_FOREGROUND监听前台窗口的变化 - 甚至EVENT_OBJECT_FOCUS监听应用程序内和控制内更精细的焦点更改

SetWinEventHook() is probably your best bet; you can listen to either the EVENT_SYSTEM_FOREGROUND to listen for foreground window changes - or even EVENT_OBJECT_FOCUS to listen for more fine-grain focus changes within apps and within controls.

您需要与WINEVENT_OUTOFCONTEXT标志使用;这意味着变更通知将被异步发送到您自己的应用程序,这样你就不会需要一个单独的DLL - 你仍然需要的P / Invoke虽然。但是,该通知不会的即时的 - 有可能是一个小的延迟 - 但与的异步的暗示。如果你想绝对马上做一些事情没有延迟任何,你将需要使用C ++和一个进程挂钩(无论是SetWinEventHook与WINEVENT_INCONTEXT或SetSetWindowsHookEx式挂钩。)

You'll need to use this with the WINEVENT_OUTOFCONTEXT flag; this means that the change notification will be delivered asynchronously to your own app, so you won't need a separate DLL - you'll still need to P/Invoke though. But the notification won't be instant - there may be a small delay - but that's implied with asynchronous. If you want to do something absolutely immediately with no delay whatsoever, you're going to need to use C++ and an in-process hook (either SetWinEventHook with WINEVENT_INCONTEXT or the SetSetWindowsHookEx-style hook.)

下面是似乎做你要找什么样的:

Here's a sample that seems to do what you're looking for:

using System;
using System.Windows;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class ForegroundTracker
{
            // Delegate and imports from pinvoke.net:

    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);

    [DllImport("user32.dll")]
    static extern bool UnhookWinEvent(IntPtr hWinEventHook);

            // Constants from winuser.h
    const uint EVENT_SYSTEM_FOREGROUND = 3;
    const uint WINEVENT_OUTOFCONTEXT = 0;

    // Need to ensure delegate is not collected while we're using it,
    // storing it in a class field is simplest way to do this.
    static WinEventDelegate procDelegate = new WinEventDelegate(WinEventProc);

    public static void Main()
    {
        // Listen for foreground changes across all processes/threads on current desktop...
        IntPtr hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero,
                procDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);

        // MessageBox provides the necessary mesage loop that SetWinEventHook requires.
        MessageBox.Show("Tracking focus, close message box to exit.");

        UnhookWinEvent(hhook);
    }

    static void WinEventProc(IntPtr hWinEventHook, uint eventType,
        IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        Console.WriteLine("Foreground changed to {0:x8}", hwnd.ToInt32()); 
    }
}

这篇关于通过SendMessage函数或异步的东西GetForegroundWindow?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆