2

I'm currently writing a program that holds down a mouse button when initially clicked, and continues to hold it until the user presses the mouse button for a second time.

The program works by detecting input globally using a MouseHookListener and then uses an input simulator to hold down the mouse button that has been pressed.

The program is able to hold down the mouse as intended, but there is an issue with the original mouse click that signals the program to simulate the button being held; it still gets carried out. I know that the MouseHookListener uses low level hooks to operate, but it's HookCallBack() method can't be overridden due to it being protected.

Is there any way to block out the original mouse input? Or is there a way to make the original input held in until the mouse is clicked once more?

This is the code I've produced, thus far (note - the mListener is being activated in a forum else where):

    public MouseHold()
    {
        mListener = new MouseHookListener(new GlobalHooker());
        mListener.MouseClick += mListener_MouseClick;
    }

    private bool isDown;
    private int count = 0;
    private InputSimulator sim = new InputSimulator();

    public MouseHookListener mListener;        

    private void mListener_MouseClick(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            if (isDown)
            {
                isDown = false;                    
                Console.Out.WriteLine(count);
            }

            else
            {
                Console.Out.WriteLine(count);
                isDown = true;
                sim.Mouse.LeftButtonDown();

            }
        }
    }
George Mamaladze
  • 7,593
  • 2
  • 36
  • 52
Liam Kelly
  • 231
  • 3
  • 15

2 Answers2

2

I am the author of the library you mentioned https://github.com/gmamaladze/globalmousekeyhook.

To enable your usecase I have extended the library by one more event. Please note that the construction of listener has also slightly changed in the new version.

I beleave that with the example below you are able to accomplish your scenario without involving InputSimulator library.

How it works?

  1. First mouse down set the flag m_SupressNextUp - down is fired.
  2. Mouse button up which follows previous down is supressed and set the flag m_SupressNextDown
  3. Second down is supressed too and reset the flag m_SupressNextUp
  4. Second up is fired and reset m_SupressNextDown
  5. System is returned to initial state.

internal class Sample
{
    private IKeyboardMouseEvents m_GlobalHook;
    private bool m_SupressNextUp;
    private bool m_SupressNextDown;

    public void Subscribe()
    {
        m_GlobalHook = Hook.GlobalEvents();

        m_GlobalHook.MouseDownExt += GlobalHookMouseDownExt;
        m_GlobalHook.MouseUpExt += GlobalHook_MouseUpExt;
    }

    void GlobalHook_MouseUpExt(object sender, MouseEventExtArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            if (m_SupressNextUp)
            {
                Console.WriteLine(@"First mouse up supress.");
                e.Handled = true;
                m_SupressNextDown = true;
            }
            else
            {
                Console.WriteLine(@"Second mouse up - make it heppen.");
                m_SupressNextDown = false;
            }
        }
    }

    private void GlobalHookMouseDownExt(object sender, MouseEventExtArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            if (m_SupressNextDown)
            {
                Console.WriteLine(@"Second mouse down supress.");
                e.Handled = true;
                m_SupressNextUp = false;
            }
            else
            {
                Console.WriteLine(@"First mouse down - make it heppen.");
                m_SupressNextUp = true;
            }
        }
    }

    public void Unsubscribe()
    {
        m_GlobalHook.MouseDownExt -= GlobalHookMouseDownExt;
        m_GlobalHook.MouseUpExt -= GlobalHook_MouseUpExt;

        m_GlobalHook.Dispose();
    }
}
Community
  • 1
  • 1
George Mamaladze
  • 7,593
  • 2
  • 36
  • 52
  • This code does what it needs to. It's nice to see a developer taking an interest in smaller problems for their code. ^^ The updated code works for holding the mouse down when pressed, however it doesn't appear to work in certain applications - but does work. This might be the application I was testing it on, though. I was testing it on a game called Warframe (this tool I'm developing is to reduce the strain on fingers btw) and it didn't work there, but works on other programs for highlighting text, and what not. Just something for others who use this to take note of. – Liam Kelly May 21 '15 at 17:52
  • Further testing shows that it is in fact that application I was testing it on. It was previously allowing input via input simulator, however. – Liam Kelly May 21 '15 at 18:15
0

after reviewing the documentation for the input simulator I am guessing you need to reverse the mouse down input.

the source code for the input simulator has a mouse up method

    private void mListener_MouseClick(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
    {
        if (isDown)
        {
            isDown = false;                    
            Console.Out.WriteLine(count);
            sim.Mouse.LeftButtonUp(); //maybe try this
        }

        else
        {
            Console.Out.WriteLine(count);
            isDown = true;
            sim.Mouse.LeftButtonDown();

        }
    }
}
RadioSpace
  • 953
  • 7
  • 15
  • Unfortunately this doesn't change much. I should have explained the code a little, so this is my bad. The code for when isDown is true, is only entered when the user clicks the mouse for the second time. It is unaffected by the simulated input. Again, my problem is that I need to stop the original mouse click from being sent to the destination (i.e the program it was meant for). However, thank you for the suggestion. As for the part about reversing the input, when the user clicks the mouse again, it releases the previously set LeftButtonDown. – Liam Kelly May 05 '15 at 21:16
  • @LiamKelly so `mListener` only fires on the second click? bool defaults to false. so i thought that the is `Down=true` was being triggered first. – RadioSpace May 06 '15 at 01:23
  • No, mListener fires on each click from the user. The first (activation) click falls into the else condition, and then on the second (terminating) click falls into the first condition. – Liam Kelly May 06 '15 at 09:18