【问题标题】:Get mouse position on canvas with transparent background在具有透明背景的画布上获取鼠标位置
【发布时间】:2012-07-31 10:03:39
【问题描述】:

我正在构建一个简单的WPF 应用程序。我有一个透明最大化 Window 和一个 Canvas (canvas1)。

我想在canvas1MainWindow 中获取鼠标位置(在这种情况下是相同的)。

为此,我使用以下代码:

Point p = Mouse.GetPosition(canvas1); //and then I have p.X and p.Y

此代码适用于不透明 Canvas。问题是我有一个透明 Canvas,而这段代码不起作用......(它不会给我错误,但坐标是p.X = 0p.Y = 0) .

我该如何解决这个问题?

【问题讨论】:

  • 您可以为您的画布提供Z-Index 属性,因为它可以靠近您在应用程序中获得的其他一些东西。
  • Z-索引 = ?也许你会给出答案。如果对我有帮助,我会 +1 并标记它。
  • 你试过用不透明度代替透明背景吗?
  • 我没有半透明窗口/画布,因为 MainWindow 位于顶部(topmost = true)。我想让点击成为可能。
  • @harry180,刚刚学习。如果您有想法,请发布。 :)

标签: c# .net wpf canvas


【解决方案1】:

一种可能的解决方法是使用GetCursorPos Win32 函数:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetCursorPos(out System.Drawing.Point lpPoint); 

如果你想在 WPF 中使用它,你必须将坐标从像素转换为点。

用法示例:

System.Drawing.Point point;
if(!GetCursorPos(out point))
    throw new InvalidOperationException("GetCursorPos failed");
// point contains cursor's position in screen coordinates.

【讨论】:

  • @John,System.Drawing.Point point;GetCursorPos(out point);point 将包含鼠标坐标。不要忘记添加 System.Drawing.dll 引用。
  • 只是一个评论。论点最终不一定是System.Drawing.Point。在 Win32 中,它是一个POINT 结构。您也可以使用两个整数成员定义自己的结构并将其用作参数类型。因此,您将摆脱 System.Drawing.dll 依赖项。
  • @John 还有一个问题。您现在将如何使用此功能?在无限循环中不断更新当前鼠标位置?我仍然认为你需要MouseHook
【解决方案2】:

C#

    using System.Windows;
    using System.Windows.Input;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System;
    using System.Windows.Threading;
    namespace Test
    {
        public partial class MainWindow : Window
        {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool GetCursorPos(ref Win32Point pt);

            [StructLayout(LayoutKind.Sequential)]
            internal struct Win32Point
            {
                public Int32 X;
                public Int32 Y;
            };
            public static Point GetMousePosition()
            {
                Win32Point w32Mouse = new Win32Point();
                GetCursorPos(ref w32Mouse);
                return new Point(w32Mouse.X, w32Mouse.Y);
            }

            private double screenWidth;
            private double screenHeight;

            public MainWindow()
            {
                InitializeComponent();
            }

            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
                screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight;

                this.Width = screenWidth;
                this.Height = screenHeight;
                this.Top = 0;
                this.Left = 0;
                DispatcherTimer timer = new DispatcherTimer();
                timer.Tick += new EventHandler(timer_Tick);
                timer.Start();
            }

            void timer_Tick(object sender, EventArgs e)
            {
                var mouseLocation = GetMousePosition();
                elipse1.Margin = new Thickness(mouseLocation.X, mouseLocation.Y, screenWidth - mouseLocation.X - elipse1.Width, screenHeight - mouseLocation.Y- elipse1.Height);
            }
        }
    }

XAML

    <Window x:Class="Test.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" 
            Height="350" Width="525" 
            WindowStyle="None" 
            Topmost="True" 
            AllowsTransparency="True" 
            Background="Transparent"
            ShowInTaskbar="False"
            Loaded="Window_Loaded">
        <Grid>
                <Ellipse Width="20" Height="20" Fill="Red" Name="elipse1"/>
        </Grid>
    </Window>

解决了!但是来晚了:(

【讨论】:

  • 哦,谢谢。但就像我在评论中所说的那样,我不想要半透明画布:Opacity="0.01"... 因为我想可以点击另一个窗口(例如 Firefox 窗口),WPF 窗口仍然在顶部。
  • @John 您希望如何同时在两个应用程序中获取鼠标事件?鼠标在透明覆盖窗口中移动并单击其他应用程序?这行不通!
  • @Clemens 我相信它可以通过 Win32 完成。我记得很久以前读过一些关于 win32 消息黑客的东西,虽然我不记得细节了。
  • @John 或者如果你只想要坐标,你可以使用GetCursorPos 函数。这是 pinvoke 的签名:pinvoke.net/default.aspx/user32.getcursorpos(不过,您需要将像素转换为点)
  • 同意!或者这个link
猜你喜欢
  • 2016-09-24
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 1970-01-01
  • 2022-11-15
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多