禁用鼠标单击Windows屏幕c#wpf的某些区域

时间:2017-07-30 10:31:19

标签: c# wpf windows mouseevent

我有一种情况,我希望使用TightVNC远程访问客户端,以允许他们在第三方应用程序上执行某些任务。

我只想让他们点击屏幕的某些部分,例如禁用“关闭”按钮,禁用一些区域。我想知道是否有一种方法可以在Windows上以编程方式拦截鼠标按下事件,如果他们在特定区域上按下鼠标,只返回而不是执行点击?或者,如果有办法覆盖始终位于所选区域屏幕前方的透明背景?

我的应用程序是用WPF c#编写的,所以如果有任何实例可以实现这一点,我们将不胜感激。我试过创建一些虚拟透明窗口,问题是,当用户点击其他应用程序时,他们会转到后台,从而击败目标。

提前致谢。

1 个答案:

答案 0 :(得分:1)

选项1:

从技术上讲,您应该能够attach global hooks获取鼠标事件,并在需要时禁止它们。 globalmousekeyhook是可用于为鼠标事件分配处理程序的库之一,并通过设置e.Handled = true来有条件地抑制它们。

选项2:

如果您需要仅针对特定应用程序阻止鼠标事件 - 那么您可以覆盖其WindowProc方法来过滤或抑制基于特定区域的鼠标事件。

例如,对于 Windows窗体应用程序,您可以使用以下代码禁用窗口第四象限区域中的鼠标单击。 (注意:此代码需要添加到您尝试阻止访问的应用程序中)

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);
    }
}

同样,您可以使用以下示例代码禁用WPF应用程序的第四象限区域中的鼠标单击:

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);
    }
}

选项3:

如果你需要阻止鼠标点击特定的现有正在运行的进程,只要目标应用程序使用基于Windows窗体的UI或WPF的.NET,那么你可以inject your .NET assemblies into the existing process / application覆盖它的{{ 1}} 选项2 中所述的行为。您也可以参考此sample code来获取相同内容。