SetWindowsHookEx and clicking minimize/maximize/close buttons on form freezing
Asked Answered
D

1

2

After setting the global hook SetWindowsHookEx standard form's buttons working oddly. For example, if I click close button, then the mouse freezes for 5-10 seconds and form too.

I found topic with same problem C# low level mouse hook and form event handling but there is only one answer. And I do not like that solution, because it needs to do each time Hook, when form deactivated, and UnHook, when program activated...

Is there a better way to solve this problem?

Edited

Here is my code:

using System.Windows.Forms;
using Gma.UserActivityMonitor;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace WinFormsHook
{
    public partial class Form1 : Form
    {
        int s_MouseHookHandle;

        public Form1()
        {
            InitializeComponent();
            IntPtr hInst = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
            s_MouseHookHandle = SetWindowsHookEx( WH_MOUSE_LL, MouseHookProc, hInst, 0);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnhookWindowsHookEx(s_MouseHookHandle);
        }

        private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                Debug.WriteLine(wParam);
                if (wParam == WM_LBUTTONDOWN)
                {
                    Action action = () => this.Text += ".";
                    this.Invoke(action);
                }
            }

            //call next hook
            return CallNextHookEx(s_MouseHookHandle, nCode, wParam, lParam);
        }

        private const int WH_MOUSE_LL = 14;
        private const int WM_LBUTTONDOWN = 0x201;

        private delegate int HookProc(int nCode, int wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        private static extern int UnhookWindowsHookEx(int idHook);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx( int idHook, int nCode, int wParam, IntPtr lParam);
    }
}
Dauntless answered 23/7, 2013 at 10:50 Comment(4)
Is this some kind of global hook?Tjader
@KingKing, yes. This is hook for MouseDoubleClick eventDauntless
What are you going to do once the user has double clicked? Do you need to use a hook? What I'm asking is why are you doing this as there may be another way.Prophylaxis
@TheKingDave, In most programs, double-click on the text leads to the selection of the word under the cursor. I need to immediately after double clicking get highlighted word into my program, and I could continue to work with this. For this reason, I need to follow the double click, resorting to SetWindowsHookEx...Dauntless
K
2

You need an handle to a native module. Don't expect that this will work as a global hook: your hook implementation requires the .NET JIT to be executed!

Indeed every non-managed process will fail to execute your handler! I suppose that this is the reason of the system block.

...

After re-reading your code it seems you don't want a global hook ('this' has no meanng in other processes). So, RTFM of SetWindowsHookEx and set the last argument appropriately.

For reference, I suggest an old question of mine.

Kerin answered 23/7, 2013 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.