PectoralisMajor PectoralisMajor - 7 months ago 22
Vb.net Question

Prevent MouseUp/MouseClick from happening after MouseDown

We're using GMA MouseHook for an elaborate Outlook VSTO AddIn.
Because of the complicated nature of our AddIn, we kinda developed ourselves into a corner on certain issues.

Our Problem:
We have Outlook maximized and the Mail.Compose window is also maximized on top of it. If we click the close-button on the Mail.Compose Window, we call the actual window-close in the MouseDown-Event.
Now the Mail.Compose window closes and the MouseUp + MouseClick events are firing on the close-button of the underlying Outlook mainwindow.

I tried setting the MouseEventArgs' e.Handled = True, but it still executes the MouseUp + MouseClick events after.

Any Ideas on how to solve this?

EDIT Thanks mehrdad safa for pointing me in the right direction!
Here is how I solved my problem:

First, I created (e.g. copied and pasted from the web) this class:

Imports System.Runtime.InteropServices

Public Class MouseInterceptor

Public Delegate Function CallBack( _
ByVal nCode As Integer, _
ByVal wParam As IntPtr, _
ByVal lParam As IntPtr) As Integer

'Declare the mouse hook constant.
'For other hook types, obtain these values from Winuser.h in Microsoft SDK.
Dim WH_MOUSE As Integer = 7
Shared hHook As Integer = 0

'Keep the reference so that the delegate is not garbage collected.
Private hookproc As CallBack

'Import for the SetWindowsHookEx function.
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function SetWindowsHookEx _
(ByVal idHook As Integer, ByVal HookProc As CallBack, _
ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
End Function

'Import for the CallNextHookEx function.
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function CallNextHookEx _
(ByVal idHook As Integer, ByVal nCode As Integer, _
ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
'Import for the UnhookWindowsHookEx function.
<DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function UnhookWindowsHookEx _
(ByVal idHook As Integer) As Boolean
End Function

'Point structure declaration.
<StructLayout(LayoutKind.Sequential)> Public Structure Point
Public x As Integer
Public y As Integer
End Structure

'MouseHookStruct structure declaration.
<StructLayout(LayoutKind.Sequential)> Public Structure MouseHookStruct
Public pt As Point
Public hwnd As Integer
Public wHitTestCode As Integer
Public dwExtraInfo As Integer
End Structure

Public Shared Function MouseHookProc( _
ByVal nCode As Integer, _
ByVal wParam As IntPtr, _
ByVal lParam As IntPtr) As Integer
Dim MyMouseHookStruct As New MouseHookStruct()

If (nCode < 0) Then
Return CallNextHookEx(hHook, nCode, wParam, lParam)
End If

MyMouseHookStruct = CType(Marshal.PtrToStructure(lParam, MyMouseHookStruct.GetType()), MouseHookStruct)

Return CallNextHookEx(hHook, nCode, wParam, lParam)

End Function


Then I just call it in my MouseDown Event BEFORE closing the Window:

MouseInterceptor.MouseHookProc(0, "0x201", 0)


The first param tells the Hook if the system should continue with other events if the value is < 0. So I use 0 to stop after MouseDown. The second param means "Left Mouse Button Down", the thirs param seems to indicate if it is a single or double click. I just left it at 0 for now.

Answer

You should set a callback for LowLevelMouseProc using setWindowsHook function to handle global mouse event. then you can prevent sending mouse up event back to windows and other applications. just don't call callNextHook function to prevent windows to forward the message!

use this example:

class InterceptMouse  

{  

private static LowLevelMouseProc _proc = HookCallback;  

private static IntPtr _hookID = IntPtr.Zero;  

public static void Main()  

{  

    _hookID = SetHook(_proc);  

    Application.Run();  

    UnhookWindowsHookEx(_hookID);  

}  

private static IntPtr SetHook(LowLevelMouseProc proc)  

{  

    using (Process curProcess = Process.GetCurrentProcess())  

    using (ProcessModule curModule = curProcess.MainModule)  

    {  

        return SetWindowsHookEx(WH_MOUSE_LL, proc,  

            GetModuleHandle(curModule.ModuleName), 0);  

    }  

}  

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

private static IntPtr HookCallback(  

    int nCode, IntPtr wParam, IntPtr lParam)  

{  

    if (nCode >= 0 &&  

        MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)  

    {  

        MSLLHOOKSTRUCT hookStruct =   (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));  

        Console.WriteLine(hookStruct.pt.x + “, ” + hookStruct.pt.y);  

    }  

    return CallNextHookEx(_hookID, nCode, wParam, lParam);  

}  

private const int WH_MOUSE_LL = 14;  

private enum MouseMessages  

{  

    WM_LBUTTONDOWN = 0x0201,  

    WM_LBUTTONUP = 0x0202,  

    WM_MOUSEMOVE = 0x0200,  

    WM_MOUSEWHEEL = 0x020A,  

    WM_RBUTTONDOWN = 0x0204,  

    WM_RBUTTONUP = 0x0205  

}  

[StructLayout(LayoutKind.Sequential)]  

private struct POINT  

{  

    public int x;  

    public int y;  

}  

[StructLayout(LayoutKind.Sequential)]  

private struct MSLLHOOKSTRUCT  

{  

    public POINT pt;  

    public uint mouseData;  

    public uint flags;  

    public uint time;   

    public IntPtr dwExtraInfo;  

}  

[DllImport(“user32.dll”, CharSet = CharSet.Auto, SetLastError = true)]  

private static extern IntPtr SetWindowsHookEx(int idHook,  

    LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);  

[DllImport(“user32.dll”, CharSet = CharSet.Auto, SetLastError = true)]  

[return: MarshalAs(UnmanagedType.Bool)]  

private static extern bool UnhookWindowsHookEx(IntPtr hhk);  

[DllImport(“user32.dll”, CharSet = CharSet.Auto, SetLastError = true)]  

private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,  

    IntPtr wParam, IntPtr lParam);  

[DllImport(“kernel32.dll”, CharSet = CharSet.Auto, SetLastError = true)]  

private static extern IntPtr GetModuleHandle(string lpModuleName);  

}

Warning: preventing mouse up event from happening may occurs unexpected further problems.