/* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using System; using System.Collections.Generic; using GreenshotPlugin.UnmanagedHelpers; using GreenshotPlugin.Core; namespace Greenshot.Helpers { public class HookHelper { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(HookHelper)); private static List hooks = new List(); private static WinEventDelegate _winEventProc; private static uint oleEventThread = 0; /// /// Remove the made hooks /// public static void Unhook() { LOG.Debug("Cleaning winEvent hooks"); foreach (IntPtr hook in hooks) { if (hook != IntPtr.Zero) { User32.UnhookWinEvent(hook); } } } /// /// Hook the WinEvents we are interested in /// public static void Hook() { LOG.Debug("Starting winEvent hooks"); _winEventProc = new WinEventDelegate(WinEventProc); int processID = 0; //Process.GetCurrentProcess().Id; hooks.Add(User32.SetWinEventHook(WinEvent.EVENT_OBJECT_CREATE, WinEvent.EVENT_OBJECT_HIDE, IntPtr.Zero, _winEventProc, processID, 0, WinEventHookFlags.WINEVENT_SKIPOWNPROCESS)); hooks.Add(User32.SetWinEventHook(WinEvent.EVENT_OBJECT_LOCATIONCHANGE, WinEvent.EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, _winEventProc, 0, 0, WinEventHookFlags.WINEVENT_SKIPOWNPROCESS)); hooks.Add(User32.SetWinEventHook(WinEvent.EVENT_SYSTEM_MENUSTART, WinEvent.EVENT_SYSTEM_MENUPOPUPEND, IntPtr.Zero, _winEventProc, processID, 0, WinEventHookFlags.WINEVENT_SKIPOWNPROCESS)); } /// /// Handle the WinEvent /// /// The Hook IntPtr /// Event Type to handle, enum WinEvent /// Window handle which caused the event /// Object ID, enum EventObjects /// Child ID of the window /// Thread which generated the ID /// private static void WinEventProc(IntPtr hWinEventHook, WinEvent eventType, IntPtr hwnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime) { // Check if it's an event generated by a Window if (hwnd == IntPtr.Zero || idObject != EventObjects.OBJID_WINDOW) { // Other events do not interest us. return; } String classname = null; // Check if the event was generated by the OLE Event Thread, which causes a lot of create/destroy if (oleEventThread != 0 && dwEventThread == oleEventThread) { return; } // Only get the classname when it's not a destroy (classname is not available) if (eventType == WinEvent.EVENT_OBJECT_CREATE) { classname = WindowDetails.GetClassName(hwnd); // Make sure the OleMainThreadWndClass events are ignored. if (oleEventThread == 0) { if (classname == "OleMainThreadWndClass") { oleEventThread = dwEventThread; return; } } } LOG.DebugFormat("eventType={0},hwnd={1},classname={4},idObject={2},idChild={3},dwEventThread={5}", eventType, hwnd, idObject, idChild, classname, dwEventThread); } } }