using System; using System.ComponentModel; using System.Drawing; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows.Forms; namespace Ace.UI.Forms { public partial class ProcessSelector : UserControl { #region Imports private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam); private const int WH_MOUSE_LL = 14; private const int WM_LBUTTONUP = 0x202; [DllImport("user32.dll")] private static extern IntPtr SetWindowsHookEx(int hookType, HookProc lpfn, IntPtr hMod, int dwThreadId); [DllImport("user32.dll")] private static extern bool UnhookWindowsHookEx(IntPtr idHook); [DllImport("user32.dll")] private static extern int CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] private static extern IntPtr WindowFromPoint(Point p); [DllImport("user32.dll")] private static extern IntPtr GetAncestor(IntPtr hwnd, uint flags); [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int processId); #endregion #region Properties public Process SelectedProcess { get; private set; } #endregion #region Fields private readonly HookProc _mouseHookProcedure; private IntPtr _hookId; private bool _dragging; #endregion public ProcessSelector() { InitializeComponent(); Disposed += OnDisposed; _mouseHookProcedure = OnMouseEvent; } private void OnDisposed(object sender, EventArgs e) { UnhookMouseEvents(); } private void TargetImage_MouseDown(object sender, MouseEventArgs e) { HookMouseEvents(); _dragging = true; DoDragDrop(sender, DragDropEffects.None); } private int OnMouseEvent(int nCode, IntPtr wParam, IntPtr lParam) { if (_dragging && wParam.ToInt32() == WM_LBUTTONUP) { var window = GetAncestor(WindowFromPoint(MousePosition), 2); int processId; GetWindowThreadProcessId(window, out processId); var process = Process.GetProcessById(processId); _dragging = false; SetProcessInfo(process); } return CallNextHookEx(_hookId, nCode, wParam, lParam); } private void HookMouseEvents() { _hookId = SetWindowsHookEx(WH_MOUSE_LL, _mouseHookProcedure, IntPtr.Zero, 0); if (_hookId == IntPtr.Zero) throw new Win32Exception("Cannot perform SetWindowsHookEx."); } private void UnhookMouseEvents() { if (_hookId == IntPtr.Zero) return; UnhookWindowsHookEx(_hookId); _hookId = IntPtr.Zero; } private void SetProcessInfo(Process process) { if (InvokeRequired) { Invoke((Action) SetProcessInfo, process); return; } UnhookMouseEvents(); if (process.Id == Process.GetCurrentProcess().Id) return; ProcessIdValue.Text = process.Id.ToString(); ProcessNameValue.Text = process.ProcessName + ".exe"; SelectedProcess = process; } } }