Обнаружить изменение активного окна с помощью C# без опроса
Как можно вызвать обратный вызов при каждом изменении текущего активного окна. Я видел, как это можно сделать с помощью CBTProc. Тем не менее, глобальные события нелегко подключить к управляемому коду. Я заинтересован в том, чтобы найти способ, который не требует опроса. Я бы предпочел подход, ориентированный на события.
С уважением
3 ответа
Создайте новый проект форм Windows, добавьте текстовое поле, сделайте его многострочным и установите свойство Dock текстового поля для заполнения, присвойте ему имя Log и вставьте следующий код (вам нужно добавить System.Runtime.InteropServices к вашим обычаям)...
WinEventDelegate dele = null;
public Form1()
{
InitializeComponent();
dele = new WinEventDelegate(WinEventProc);
IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT);
}
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_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);
private string GetActiveWindowTitle()
{
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;
}
public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
Log.Text += GetActiveWindowTitle() + "\r\n";
}
Я знаю, что эта ветка старая, но ради будущего использования: при запуске кода через некоторое время вы увидите сбой. Это вызвано строкой в конструкторе Form:
public Form1()
{
InitializeComponent();
WinEventDelegate dele = new WinEventDelegate(WinEventProc);//<-causing ERROR
IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT);
}
Вместо вышесказанного сделайте следующую модификацию:
public Form1()
{
InitializeComponent();
dele = new WinEventDelegate(WinEventProc);
IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, dele, 0, 0, WINEVENT_OUTOFCONTEXT);
}
WinEventDelegate dele = null;
.. работает сейчас, как и ожидалось!
Ты можешь использовать SetWinEventHook
и слушать за EVENT_SYSTEM_FOREGROUND
событие. Использовать WINEVENT_OUTOFCONTEXT
флаг, чтобы избежать проблемы глобального перехвата.