250 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Windows.Forms;
 | 
						|
using System.Collections;
 | 
						|
using System.Threading;
 | 
						|
using System.Drawing;
 | 
						|
using System.Runtime.InteropServices;
 | 
						|
 | 
						|
namespace DevComponents.DotNetBar
 | 
						|
{
 | 
						|
    /// <summary>
 | 
						|
    /// Summary description for MessageHandler.
 | 
						|
    /// </summary>
 | 
						|
    internal class NonClientHook
 | 
						|
    {
 | 
						|
        private static ArrayList m_Clients = new ArrayList();
 | 
						|
        private static Hashtable m_FilterOnThread = new Hashtable();
 | 
						|
        private static ReaderWriterLock rwClientsListLock;
 | 
						|
        private static MouseProc m_MouseHook = null;
 | 
						|
 | 
						|
        private delegate IntPtr MouseProc(int nCode, IntPtr wParam, IntPtr lParam);
 | 
						|
 | 
						|
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 | 
						|
        private static extern IntPtr SetWindowsHookEx(int hookid, MouseProc pfnhook, IntPtr hinst, int threadid);
 | 
						|
 | 
						|
        //[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "SetWindowsHookEx")]
 | 
						|
        //private static extern IntPtr SetWindowsHookExKeyboard(int hookid, KeyboardProc pfnhook, IntPtr hinst, int threadid);
 | 
						|
 | 
						|
        [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
 | 
						|
        private static extern bool UnhookWindowsHookEx(IntPtr hhook);
 | 
						|
 | 
						|
        [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
 | 
						|
        private static extern IntPtr CallNextHookEx(IntPtr hhook, int code, IntPtr wparam, IntPtr lparam);
 | 
						|
        [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
 | 
						|
        private static extern int GetCurrentThreadId();
 | 
						|
 | 
						|
        private const int WH_MOUSE = 7;
 | 
						|
        private const int HC_ACTION = 0;
 | 
						|
        private const int WH_CALLWNDPROCRET = 12;
 | 
						|
        private const int WH_CALLWNDPROC = 4;
 | 
						|
 | 
						|
        // Methods
 | 
						|
        static NonClientHook()
 | 
						|
        {
 | 
						|
            NonClientHook.rwClientsListLock = new ReaderWriterLock();
 | 
						|
            m_MouseHook = new MouseProc(OnMouseHook);
 | 
						|
        }
 | 
						|
 | 
						|
        public static void RegisterHook(ISkinHook client)
 | 
						|
        {
 | 
						|
            if (m_Clients.Contains(client))
 | 
						|
                return;
 | 
						|
 | 
						|
            if (!m_FilterOnThread.ContainsKey(System.Threading.Thread.CurrentThread.GetHashCode()))
 | 
						|
                HookThread();
 | 
						|
 | 
						|
            LockCookie cookie1 = new LockCookie();
 | 
						|
            bool readerLockHeld = NonClientHook.rwClientsListLock.IsReaderLockHeld;
 | 
						|
 | 
						|
            if (readerLockHeld)
 | 
						|
            {
 | 
						|
                cookie1 = NonClientHook.rwClientsListLock.UpgradeToWriterLock(-1);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                NonClientHook.rwClientsListLock.AcquireWriterLock(-1);
 | 
						|
            }
 | 
						|
 | 
						|
            try
 | 
						|
            {
 | 
						|
                m_Clients.Add(client);
 | 
						|
            }
 | 
						|
            finally
 | 
						|
            {
 | 
						|
                if (readerLockHeld)
 | 
						|
                {
 | 
						|
                    NonClientHook.rwClientsListLock.DowngradeFromWriterLock(ref cookie1);
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    NonClientHook.rwClientsListLock.ReleaseWriterLock();
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        public static void UnregisterHook(ISkinHook client)
 | 
						|
        {
 | 
						|
            if (m_Clients.Contains(client))
 | 
						|
            {
 | 
						|
                LockCookie cookie1 = new LockCookie();
 | 
						|
                bool readerLockHeld = NonClientHook.rwClientsListLock.IsReaderLockHeld;
 | 
						|
 | 
						|
                if (readerLockHeld)
 | 
						|
                {
 | 
						|
                    cookie1 = NonClientHook.rwClientsListLock.UpgradeToWriterLock(-1);
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    NonClientHook.rwClientsListLock.AcquireWriterLock(-1);
 | 
						|
                }
 | 
						|
 | 
						|
                try
 | 
						|
                {
 | 
						|
                    m_Clients.Remove(client);
 | 
						|
                    if (m_Clients.Count == 0)
 | 
						|
                        UnHookThread();
 | 
						|
                }
 | 
						|
                finally
 | 
						|
                {
 | 
						|
                    if (readerLockHeld)
 | 
						|
                    {
 | 
						|
                        NonClientHook.rwClientsListLock.DowngradeFromWriterLock(ref cookie1);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        NonClientHook.rwClientsListLock.ReleaseWriterLock();
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        private static void HookThread()
 | 
						|
        {
 | 
						|
            if (m_FilterOnThread.ContainsKey(System.Threading.Thread.CurrentThread.GetHashCode()))
 | 
						|
                return;
 | 
						|
 | 
						|
            int id = GetCurrentThreadId();
 | 
						|
            IntPtr hook = SetWindowsHookEx(WH_MOUSE, m_MouseHook, IntPtr.Zero, id);
 | 
						|
            m_FilterOnThread.Add(System.Threading.Thread.CurrentThread.GetHashCode(), hook);
 | 
						|
        }
 | 
						|
 | 
						|
        private static void UnHookThread()
 | 
						|
        {
 | 
						|
            if (!m_FilterOnThread.ContainsKey(System.Threading.Thread.CurrentThread.GetHashCode()))
 | 
						|
                return;
 | 
						|
            IntPtr hook = (IntPtr)m_FilterOnThread[System.Threading.Thread.CurrentThread.GetHashCode()];
 | 
						|
            UnhookWindowsHookEx(hook);
 | 
						|
            m_FilterOnThread.Remove(System.Threading.Thread.CurrentThread.GetHashCode());
 | 
						|
        }
 | 
						|
 | 
						|
        private static ISkinHook[] GetMessageClients()
 | 
						|
        {
 | 
						|
            ISkinHook[] messageClients;
 | 
						|
            NonClientHook.rwClientsListLock.AcquireReaderLock(-1);
 | 
						|
            try
 | 
						|
            {
 | 
						|
                messageClients = (ISkinHook[])m_Clients.ToArray(typeof(ISkinHook));
 | 
						|
            }
 | 
						|
            finally
 | 
						|
            {
 | 
						|
                NonClientHook.rwClientsListLock.ReleaseReaderLock();
 | 
						|
            }
 | 
						|
 | 
						|
            return messageClients;
 | 
						|
        }
 | 
						|
 | 
						|
        private static unsafe IntPtr OnMouseHook(int nCode, IntPtr wParam, IntPtr lParam)
 | 
						|
        {
 | 
						|
            try
 | 
						|
            {
 | 
						|
                if (nCode == HC_ACTION)
 | 
						|
                {
 | 
						|
                    int wParamInt = WinApi.ToInt(wParam);
 | 
						|
                    if (wParamInt == (int)WinApi.WindowsMessages.WM_MOUSEMOVE)
 | 
						|
                    {
 | 
						|
                        MOUSEHOOKSTRUCT* ws = (MOUSEHOOKSTRUCT*)lParam;
 | 
						|
                        PostMouseMove(ws->hwnd, ws->pt.ToPoint());
 | 
						|
                    }
 | 
						|
                    if (wParamInt == (int)WinApi.WindowsMessages.WM_LBUTTONUP)
 | 
						|
                    {
 | 
						|
                        MOUSEHOOKSTRUCT* ws = (MOUSEHOOKSTRUCT*)lParam;
 | 
						|
                        PostMouseUp(ws->hwnd, ws->pt.ToPoint());
 | 
						|
                    }
 | 
						|
                    //CWPRETSTRUCT* ws = (CWPRETSTRUCT*)lParam;
 | 
						|
                    //if (ws->message == (uint)WinApi.WindowsMessages.WM_MOUSEMOVE || ws->message == 0x118)
 | 
						|
                    //{
 | 
						|
                    //    PostMouseMove(ws->hwnd, ws->wParam, ws->lParam);
 | 
						|
                    //}
 | 
						|
 | 
						|
                }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
                IntPtr h = (IntPtr)m_FilterOnThread[System.Threading.Thread.CurrentThread.GetHashCode()];
 | 
						|
                IntPtr res = CallNextHookEx(h, nCode, wParam, lParam);
 | 
						|
 | 
						|
                return res;
 | 
						|
            }
 | 
						|
            catch
 | 
						|
            { }
 | 
						|
            return IntPtr.Zero;
 | 
						|
        }
 | 
						|
 | 
						|
        public static bool PostMouseMove(IntPtr hWnd, Point mousePos)
 | 
						|
        {
 | 
						|
            ISkinHook[] messageClients = GetMessageClients();
 | 
						|
            foreach (ISkinHook client in messageClients)
 | 
						|
            {
 | 
						|
                client.PostMouseMove(hWnd, mousePos);
 | 
						|
            }
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        public static bool PostMouseUp(IntPtr hWnd, Point mousePos)
 | 
						|
        {
 | 
						|
            ISkinHook[] messageClients = GetMessageClients();
 | 
						|
            foreach (ISkinHook client in messageClients)
 | 
						|
            {
 | 
						|
                client.PostMouseUp(hWnd, mousePos);
 | 
						|
            }
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        private struct POINT
 | 
						|
        {
 | 
						|
            public POINT(int x, int y)
 | 
						|
            {
 | 
						|
                this.x = x;
 | 
						|
                this.y = y;
 | 
						|
            }
 | 
						|
            public int x;
 | 
						|
            public int y;
 | 
						|
 | 
						|
            public Point ToPoint()
 | 
						|
            {
 | 
						|
                return new Point(x, y);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        private struct MOUSEHOOKSTRUCT
 | 
						|
        {
 | 
						|
            public MOUSEHOOKSTRUCT(POINT pt, IntPtr hwnd, ushort wHitTestCode, IntPtr dwExtraInfo)
 | 
						|
            {
 | 
						|
                this.pt = pt;
 | 
						|
                this.hwnd = hwnd;
 | 
						|
                this.wHitTestCode = wHitTestCode;
 | 
						|
                this.dwExtraInfo = dwExtraInfo;
 | 
						|
            }
 | 
						|
            public POINT pt;
 | 
						|
            public IntPtr hwnd;
 | 
						|
            public ushort wHitTestCode;
 | 
						|
            public IntPtr dwExtraInfo;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    internal interface ISkinHook
 | 
						|
    {
 | 
						|
        void PostMouseMove(IntPtr hWnd, Point mousePos);
 | 
						|
        void PostMouseUp(IntPtr hWnd, Point mousePos);
 | 
						|
    }
 | 
						|
}
 |