K
Without claiming the perfect solution, the public demo code is still the answer.
Thank you. https://ru.stackoverflow.com/users/184217/alexander-petrov for the right direction.using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
....
static class Program
{
#region Объявление WinApi-констант и функций
private const int WINEVENT_INCONTEXT = 4;
private const int WINEVENT_OUTOFCONTEXT = 0;
private const int WINEVENT_SKIPOWNPROCESS = 2;
private const int WINEVENT_SKIPOWNTHREAD = 1;
private const int EVENT_SYSTEM_FOREGROUND = 3;
//Это call-back для нашего хука:
delegate void WinEventDelegate(IntPtr hWinEventHook,
uint eventType, IntPtr hwnd, int idObject,
int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll")]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[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 lpString, int nMaxCount);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);
#endregion
//Хук
private static IntPtr hookHandle;
//Главная форма приложения
private static fmMain mainForm;
//Точка входа в приложение
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Создаём главную форму
mainForm = new fmMain();
//Вешаем хук
hookHandle = SetWinEventHook(EVENT_SYSTEM_FOREGROUND,
EVENT_SYSTEM_FOREGROUND, IntPtr.Zero,
WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
//Запускаем приложение
Application.Run(mainForm);
//Снимаем хук
UnhookWinEvent(hookHandle);
}
//Вспомогательные функции для получения сведений о перехваченных окнах и процессах
private static string GetProcessName(int pid)
{
Process p = Process.GetProcessById(pid);
return p.ProcessName;
}
private static uint GetPIDbyHwnd(IntPtr hwnd)
{
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
return pid;
}
//Реализация callback для хука - основная обработка именно тут:
private static void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild,
uint dwEventThread, uint dwmsEventTime)
{
//Фильтр по типу события - перехватываем сообщение, когда какое-либо
//окно в системе становится активным (окном переднего плана)
if (eventType == EVENT_SYSTEM_FOREGROUND)
{
//Посредством класса StringBuilder готовим буфер для получения заголовка окна
StringBuilder sb = new StringBuilder(500);
//Получаем заголовок активного окна в буфер
GetWindowText(hwnd, sb, sb.Capacity);
//По хэндлу активного окна получаем Process Identifier (PID)
var PID = (int)GetPIDbyHwnd(hwnd);
//Зная PID - получим имя процесса:
var processName = GetProcessName(PID);
//Выводим полученные сведения в форму:
mainForm.m_list.Items.Insert(0,
$"Окно HWND={hwnd}, ProcessName=\"{processName}\", заголовок окна: " + sb.ToString());
}
}
}
There's nothing on the main form except the ListBox counter with the name m_list♪ In the form for convenience itself TopMost issued in true♪