Reputation: 3341
I have a situation where I would like to give remote access to a client using TightVNC to allow them to perform some tasks on a third party application.
I am wanting to only allow them to click on certain parts of the screen e.g. disable the 'Close' button, with a few areas disabled. I was wondering if there was a way to programmatically intercept the mouse down event on windows and if they mouse down on a particular area just return instead of performing the click? Or if there is a way to overlay a transparent background which is always at the front of the screen in the chosen areas?
My application is written in WPF c# so if there are any examples to achieve this it would be greatly appreciated. I have tried creating some dummy transparent windows, the problem is that when the user clicks on the other application they go to the background hence defeating the objective.
Thanks in advance.
Upvotes: 2
Views: 3489
Reputation: 13601
You should technically be able to attach global hooks for mouse events and suppress them when you need to. globalmousekeyhook is one of the libraries available for assigning handler(s) to mouse events and suppress them conditionally by setting e.Handled = true
.
In case you need to block mouse events only for specific applications - then you can override their WindowProc method to filter or suppress particular region based mouse-events.
For example, for a windows forms application, you can use following code to disable mouse clicks in fourth quadrant region of the window. (Note: this code needs to be added to the application you are trying to block access to)
public class Setup
{
//call this method during application start/load
public static bool Start()
{
Application.AddMessageFilter(new MessageFilter());
return true;
}
}
public class MessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
// and use other params to determine mouse click location
switch (m.Msg)
{
case 0x201:
//left button down
return IsInFourthQuadrant();//(filter the message and don't let app process it)
case 0x202:
//left button up, ie. a click
break;
case 0x203:
//left button double click
return IsInFourthQuadrant(); //(filter the message and don't let app process it)
}
return false;
}
private static bool IsInFourthQuadrant()
{
var window = Application.OpenForms[0];
var screen_coords = Cursor.Position;
var bounds = window.Bounds;
var fourthQuadrant = new Rectangle(bounds.X + bounds.Width / 2, bounds.Y + bounds.Height / 2, bounds.Width / 2, bounds.Height / 2);
return fourthQuadrant.Contains(screen_coords);
}
}
Similarly, you can use following sample code to disable mouse clicks in fourth quadrant region of a WPF application:
public class Setup
{
public static bool Start()
{
HwndSource source = PresentationSource.FromVisual(Application.Current.MainWindow) as HwndSource;
source.AddHook(WndProc);
return true;
}
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case 0x201:
//left button down
handled = IsInFourthQuadrant();//(filter the message and don't let app process it)
break;
case 0x202:
//left button up, ie. a click
break;
case 0x203:
//left button double click
handled = IsInFourthQuadrant(); //(filter the message and don't let app process it)
break;
}
return IntPtr.Zero;
}
private static bool IsInFourthQuadrant()
{
var window = Application.Current.MainWindow;
var coords = Mouse.GetPosition(Application.Current.MainWindow);
var fourthQuadrant = new Rect(window.Width / 2, window.Height / 2, window.Width / 2, window.Height / 2);
return fourthQuadrant.Contains(coords);
}
}
In case you need to block mouse clicks on specific existing running processes, provided the target applications are using .NET with either windows-forms based UI or WPF - then you can inject your .NET assemblies into the existing process/application and override its WindowsProc
behaviour as stated in Option 2. You can also refer this sample code for the same.
Upvotes: 2