Обработка событий в WinForm C#

552
17 февраля 2017, 00:55

Есть следующая проблема, на форме расположен компонент, форма создана без элементов управления и обработка перемещения формы по рабочему столу производится "своим" кодом. В частности обратываются события клика по форме (нажал\отпустил левую кнопку мыши), перемещения указателя мыши. Компонент, который расположен на форме занимает все пространтсво формы, соответсвенно, события мыши обрабатываются для него, а не для формы. Можно ли как нибудь игнорировать эти события для компонента, но обрабатывать их для формы?

Answer 1

Самый хороший результат получился в результате использования хука для мышки. Проверяю находится ли мышь над формой приложения, а дальше классически обрабатываю события мышки (Down,Up,Move) единственное, эвенты в хуке возвращают позицию указателя в экранных координатах, что нужно учитывать при установке перемещения (ну это логично). Приведу код хука сюда, может быть кому нибудь понадобится. Код найден на просторах интернета.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MouseHook
{
    public static class MouseHook
    {
        #region Declarations
        public static event MouseEventHandler MouseDown;
        public static event MouseEventHandler MouseUp;
        public static event MouseEventHandler MouseMove;
        [StructLayout(LayoutKind.Sequential)]
        struct MOUSEHOOKSTRUCT
        {
            public POINT pt;
            public IntPtr hwnd;
            public int wHitTestCode;
            public IntPtr dwExtraInfo;
        }
        [StructLayout(LayoutKind.Sequential)]
        struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public int mouseData;
            public int flags;
            public int time;
            public IntPtr dwExtraInfo;
        }
        [StructLayout(LayoutKind.Sequential)]
        struct POINT
        {
            public int X;
            public int Y;
            public POINT(int x, int y)
            {
                this.X = x;
                this.Y = y;
            }
            public static implicit operator Point(POINT p)
            {
                return new Point(p.X, p.Y);
            }
            public static implicit operator POINT(Point p)
            {
                return new POINT(p.X, p.Y);
            }
        }
        const int WM_LBUTTONDOWN = 0x201;
        const int WM_LBUTTONUP = 0x202;
        const int WM_MOUSEMOVE = 0x0200;
        const int WM_MOUSEWHEEL = 0x020A;
        const int WM_RBUTTONDOWN = 0x0204;
        const int WM_RBUTTONUP = 0x0205;
        const int WM_MBUTTONUP = 0x208;
        const int WM_MBUTTONDOWN = 0x207;
        const int WM_XBUTTONDOWN = 0x20B;
        const int WM_XBUTTONUP = 0x20C;
        static IntPtr hHook = IntPtr.Zero;
        static IntPtr hModule = IntPtr.Zero;
        static bool hookInstall = false;
        static bool localHook = true;
        static API.HookProc hookDel;
        #endregion
        /// <summary>
        /// Hook install method.
        /// </summary>
        public static void InstallHook()
        {
            if (IsHookInstalled)
                return;
            hModule = Marshal.GetHINSTANCE(AppDomain.CurrentDomain.GetAssemblies()[0].GetModules()[0]);
            hookDel = new API.HookProc(HookProcFunction);
            if (localHook)
                hHook = API.SetWindowsHookEx(API.HookType.WH_MOUSE,
                    hookDel, IntPtr.Zero, AppDomain.GetCurrentThreadId()); // Если подчеркивает необращай внимание, так надо.
            else
                hHook = API.SetWindowsHookEx(API.HookType.WH_MOUSE_LL,
                    hookDel, hModule, 0);
            if (hHook != IntPtr.Zero)
                hookInstall = true;
            else
                throw new Win32Exception("Can't install low level keyboard hook!");
        }
        /// <summary>
        /// If hook installed return true, either false.
        /// </summary>
        public static bool IsHookInstalled
        {
            get { return hookInstall && hHook != IntPtr.Zero; }
        }
        /// <summary>
        /// Module handle in which hook was installed.
        /// </summary>
        public static IntPtr ModuleHandle
        {
            get { return hModule; }
        }
        /// <summary>
        /// If true local hook will installed, either global.
        /// </summary>
        public static bool LocalHook
        {
            get { return localHook; }
            set
            {
                if (value != localHook)
                {
                    if (IsHookInstalled)
                        throw new Win32Exception("Can't change type of hook than it install!");
                    localHook = value;
                }
            }
        }
        /// <summary>
        /// Uninstall hook method.
        /// </summary>
        public static void UnInstallHook()
        {
            if (IsHookInstalled)
            {
                if (!API.UnhookWindowsHookEx(hHook))
                    throw new Win32Exception("Can't uninstall low level keyboard hook!");
                hHook = IntPtr.Zero;
                hModule = IntPtr.Zero;
                hookInstall = false;
            }
        }
        /// <summary>
        /// Hook process messages.
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        static IntPtr HookProcFunction(int nCode, IntPtr wParam, [In] IntPtr lParam)
        {
            if (nCode == 0)
            {
                if (localHook)
                {
                    MOUSEHOOKSTRUCT mhs = (MOUSEHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MOUSEHOOKSTRUCT));
                    #region switch
                    switch (wParam.ToInt32())
                    {
                        case WM_LBUTTONDOWN:
                            if (MouseDown != null)
                                MouseDown(null,
                                    new MouseEventArgs(MouseButtons.Left,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_LBUTTONUP:
                            if (MouseUp != null)
                                MouseUp(null,
                                    new MouseEventArgs(MouseButtons.Left,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_MBUTTONDOWN:
                            if (MouseDown != null)
                                MouseDown(null,
                                    new MouseEventArgs(MouseButtons.Middle,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_MBUTTONUP:
                            if (MouseUp != null)
                                MouseUp(null,
                                    new MouseEventArgs(MouseButtons.Middle,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_MOUSEMOVE:
                            if (MouseMove != null)
                                MouseMove(null,
                                    new MouseEventArgs(MouseButtons.None,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_MOUSEWHEEL:
                            // Данный хук не позволяет узнать куда вращается колесо мыши.
                            break;
                        case WM_RBUTTONDOWN:
                            if (MouseDown != null)
                                MouseDown(null,
                                    new MouseEventArgs(MouseButtons.Right,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_RBUTTONUP:
                            if (MouseUp != null)
                                MouseUp(null,
                                    new MouseEventArgs(MouseButtons.Right,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        default:
                            //Debug.WriteLine(string.Format("X:{0}; Y:{1}; Handle:{2}; HitTest:{3}; EI:{4}; wParam:{5}; lParam:{6}",
                            //    mhs.pt.X, mhs.pt.Y, mhs.hwnd, mhs.wHitTestCode, mhs.dwExtraInfo, wParam.ToString(), lParam.ToString()));
                            break;
                    }
                    #endregion
                }
                else
                {
                    MSLLHOOKSTRUCT mhs = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                    #region switch
                    switch (wParam.ToInt32())
                    {
                        case WM_LBUTTONDOWN:
                            if (MouseDown != null)
                                MouseDown(null,
                                    new MouseEventArgs(MouseButtons.Left,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_LBUTTONUP:
                            if (MouseUp != null)
                                MouseUp(null,
                                    new MouseEventArgs(MouseButtons.Left,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_MBUTTONDOWN:
                            if (MouseDown != null)
                                MouseDown(null,
                                    new MouseEventArgs(MouseButtons.Middle,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_MBUTTONUP:
                            if (MouseUp != null)
                                MouseUp(null,
                                    new MouseEventArgs(MouseButtons.Middle,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_MOUSEMOVE:
                            if (MouseMove != null)
                                MouseMove(null,
                                    new MouseEventArgs(MouseButtons.None,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_MOUSEWHEEL:
                            if (MouseMove != null)
                                MouseMove(null,
                                    new MouseEventArgs(MouseButtons.None, mhs.time,
                                        mhs.pt.X, mhs.pt.Y, mhs.mouseData >> 16));
                            //Debug.WriteLine(string.Format("X:{0}; Y:{1}; MD:{2}; Time:{3}; EI:{4}; wParam:{5}; lParam:{6}",
                            //            mhs.pt.X, mhs.pt.Y, mhs.mouseData, mhs.time, mhs.dwExtraInfo, wParam.ToString(), lParam.ToString()));
                            break;
                        case WM_RBUTTONDOWN:
                            if (MouseDown != null)
                                MouseDown(null,
                                    new MouseEventArgs(MouseButtons.Right,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        case WM_RBUTTONUP:
                            if (MouseUp != null)
                                MouseUp(null,
                                    new MouseEventArgs(MouseButtons.Right,
                                        1,
                                        mhs.pt.X,
                                        mhs.pt.Y,
                                        0));
                            break;
                        default:
                            break;
                    }
                    #endregion
                }
            }
            return API.CallNextHookEx(hHook, nCode, wParam, lParam);
        }
    }
    static class API
    {
        public delegate IntPtr HookProc(int nCode, IntPtr wParam, [In] IntPtr lParam);
        [DllImport("user32.dll")]
        public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, [In] IntPtr lParam);
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn,
        IntPtr hMod, int dwThreadId);
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool UnhookWindowsHookEx(IntPtr hhk);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);
        public enum HookType : int
        {
            WH_JOURNALRECORD = 0,
            WH_JOURNALPLAYBACK = 1,
            WH_KEYBOARD = 2,
            WH_GETMESSAGE = 3,
            WH_CALLWNDPROC = 4,
            WH_CBT = 5,
            WH_SYSMSGFILTER = 6,
            WH_MOUSE = 7,
            WH_HARDWARE = 8,
            WH_DEBUG = 9,
            WH_SHELL = 10,
            WH_FOREGROUNDIDLE = 11,
            WH_CALLWNDPROCRET = 12,
            WH_KEYBOARD_LL = 13,
            WH_MOUSE_LL = 14
        }
    }
}
READ ALSO
Есть ли способ делать не такие громозкие события?

Есть ли способ делать не такие громозкие события?

Реализация в модели (в паттерне MVVM), каждой публичной переменной так:

479
Разница get; set;

Разница get; set;

Не совсем понял разницу между

327
Сборка dll из il кода

Сборка dll из il кода

Доброго времени суток! У меня есть dll написанная на C#Я дизассемблировал исходники этой dll с помощью ildasm

315
Считать данные с файла и преобразовать в число

Считать данные с файла и преобразовать в число

Здравствуйте! Подскажите пожалуйста как в WinForme сделать так чтобы программа считывала данные с файлаtxt и преобразовывала их в числа? А после...

390