How to make the Rectangle not response to mouse move?

William Liu 326 Reputation points
2024-05-31T03:27:39.53+00:00

I`m tring to draw a overlay transparent window with a red rectangle. It's a WPF Window. I am looking for how to make the rectangle not response to mouse move. Please see the screenshot for problem details. As you can see, when I move the cursor on top of rectangle, the cursor will change its shape to arrow, seems it has reaction to the rectangle. I do not want this behavior. Please let me know if it is possiable.

screenshots

Program.cs

using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

Thread.CurrentThread.SetApartmentState(ApartmentState.Unknown);
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
_ = new OverLay();

internal sealed class OverLay
{
    private readonly Window _window = new();

    public OverLay()
    {
        _window.Left = 0;
        _window.Top = 0;
        _window.WindowState = WindowState.Maximized;
        _window.Background = Brushes.Transparent;
        _window.WindowStyle = WindowStyle.None;
        _window.AllowsTransparency = true;
        _window.Topmost = true;
        _window.ShowInTaskbar = false;
        _window.IsHitTestVisible = false;
        _window.Focusable = false;

        var canvas = new Canvas { IsHitTestVisible = false, Focusable = false };
        _window.Content = canvas;

        _window.Loaded += (_, _) =>
        {
            // 画一个100x100的红色矩形
            var rectangle = new Rectangle
            {
                Width = 100,
                Height = 100,
                Stroke = Brushes.Red,
                StrokeThickness = 2,
                IsHitTestVisible = false,
                Focusable = false,
            };
            canvas.Children.Add(rectangle);
            Canvas.SetLeft(rectangle, (canvas.ActualWidth - rectangle.Width) / 2);
            Canvas.SetTop(rectangle, (canvas.ActualHeight - rectangle.Height) / 2);
        };
        _window.ShowDialog();
    }
}

csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  
  <ItemGroup>
    <FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" />
  </ItemGroup>
</Project>
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,703 questions
{count} votes

Accepted answer
  1. Viorel 114K Reputation points
    2024-05-31T15:29:23.67+00:00

    Try to add this code before ShowDialog:

    _window.SourceInitialized += ( _, _ ) =>
    {
        var hwnd = new WindowInteropHelper( _window ).Handle;
        SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong( hwnd, GWL_EXSTYLE ) | WS_EX_TRANSPARENT );
    };
    

    Also add the definitions:

    const int WS_EX_TRANSPARENT = 0x00000020;
    const int GWL_EXSTYLE = -20;
    
    [DllImport( "user32" )]
    static extern int GetWindowLong( IntPtr hwnd, int index );
    
    [DllImport( "user32" )]
    static extern int SetWindowLong( IntPtr hwnd, int index, int newStyle );
    

    It should also solve the problem of mouse pointer.

    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Hongrui Yu-MSFT 780 Reputation points Microsoft Vendor
    2024-05-31T10:03:08.4233333+00:00

    Hi,@William Liu. Welcome to Microsoft Q&A. 

    You could set the value directly to display a cursor of type IBeam.

     public OverLay()
    
     {
    
         _window.Left = 0;
    
         _window.Top = 0;
    
         _window.WindowState = WindowState.Maximized;
    
         _window.Background = Brushes.Transparent;
    
         _window.WindowStyle = WindowStyle.None;
    
         _window.AllowsTransparency = true;
    
         _window.Topmost = true;
    
         _window.ShowInTaskbar = false;
    
         _window.IsHitTestVisible = true ;
    
         _window.Focusable = false;
    
     
    
         var canvas = new Canvas { IsHitTestVisible = true, Focusable = false};
    
         _window.Content = canvas;
    
    
         var rectangle = new Rectangle
    
             {
    
                 Width = 100,
    
                 Height = 100,
    
                 Stroke = Brushes.Red,
    
                 StrokeThickness = 40,
    
                 IsHitTestVisible = true,
    
                 Cursor= Cursors.IBeam,
    
                 Focusable = false,
    
                 
    
             };
    
         
    
             canvas.Children.Add(rectangle);
    
             Canvas.SetLeft(rectangle, (canvas.ActualWidth - rectangle.Width) / 2);
    
             Canvas.SetTop(rectangle, (canvas.ActualHeight - rectangle.Height) / 2);
    
         };
    
         _window.ShowDialog();
    
     }
    
    

    When you need the current cursor of an application covered by a WPF application, you can refer to the following solution.

    Cause analysis:

    When the mouse enters a WPF program, the default mouse icon is Arrow.

     

    If you set the entire Window to Brushes.Transparent, then this area does not have the pixels of your program, which means you are not in the WPF program, and the mouse icon is based on the mouse icon outside the program.

     

    But if you set the color in Rectangle, then this area has the pixels of your program, which means you are in the WPF program, and the mouse icon changes to the default Arrow.

     

    Solution:Use the MouseEnter event to set the Cursor of the current control to the mouse icon before entering the current control

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments