【问题标题】:Erasing drawn objects on Desktop using Pinvoke on C# WPF在 C# WPF 上使用 Pinvoke 擦除桌面上的绘制对象
【发布时间】:2013-09-08 13:40:12
【问题描述】:

我正在尝试为需要使用多个桌面光标的https://www.leapmotion.com 设备创建一个界面程序。由于 windows 不允许多个光标,我的第一个任务是创建一个可以在桌面和其他窗口中移动的可视光标。

我现在这样做的方式是实现一个循环并在清除它的同时不断绘制光标对象。绘图部分工作正常,但我在做清理部分时遇到问题。我曾尝试在 Pinvoke 中使用 RedrawWindow(),但下面的代码在测试期间会中断。

错误信息: 调用 PInvoke 函数 'WpfApplication1!WpfApplication1.MainWindow::RedrawWindow' 使堆栈不平衡。这可能是因为托管的 PInvoke 签名没有 匹配非托管目标签名。检查调用约定和参数 的 PInvoke 签名匹配目标非托管签名。

感谢您提供的任何建议。

    [DllImport("user32.dll")]
    static extern int RedrawWindow(IntPtr hWnd, [In] ref RECT lprcUpdate, IntPtr hrgnUpdate, uint flags);

    ....

    private void Timer_Tick(object sender, EventArgs e)
    {
        using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
        {

            ///throw new NotImplementedException();
            System.Drawing.Point pt = System.Windows.Forms.Cursor.Position;



            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(new System.Drawing.Point(pt.X - 10, pt.Y - 10), new System.Drawing.Size(20, 20));


            g.DrawEllipse(Pens.Black, rect);

            g.Dispose();

            RECT rc = new RECT( pt.X - 20, pt.Y - 20, pt.X + 20, pt.Y + 20 );

            RedrawWindow(IntPtr.Zero, ref rc, IntPtr.Zero, 0x0400/*RDW_FRAME*/ | 0x0100/*RDW_UPDATENOW*/| 0x0001/*RDW_INVALIDATE*/);

        }

    }

编辑:

我已根据 Alex Farber 的建议修改了上面的代码。 (谢谢!)

我还根据 Sriram Sakthivel 的建议添加了额外的参考。所以现在它可以毫无错误地编译和运行,但是绘制的椭圆仍然没有被 RedrawWindow() 命令清除。

知道有什么问题吗?

【问题讨论】:

  • 我在 PInvoke 声明中看到两个问题:Win32 中的 BOOL 是 32 位值,使用 int 作为返回码,RECT 必须通过引用传递,而不是通过值传递。
  • 是的,扩展亚历克斯所说的,我认为正确的声明是: [DllImport("user32.dll")] static extern bool RedrawWindow(IntPtr hWnd, [In] ref RECT lprcUpdate, IntPtr hrgnUpdate , RedrawWindowFlags 标志);来源:pinvoke.net/default.aspx/user32.redrawwindow
  • 这与WPF无关。
  • 说它在 WPF 上只是把事情放到上下文中。有些方法适用于 Windows 窗体,但不适用于 WPF。

标签: c# wpf leap-motion


【解决方案1】:

我认为问题是您在 P/Invoke 声明中缺少 ref

 [DllImport("user32.dll")]
    static extern bool RedrawWindow(IntPtr hWnd, [In] ref RECT lprcUpdate, IntPtr hrgnUpdate, uint flags);

并将其称为

RedrawWindow(IntPtr.Zero, ref rc, IntPtr.Zero, ...);
                          ^ Note ref keyword here

【讨论】:

  • 嗨 Siriam,我还根据您的建议添加了额外的参考。所以现在它可以毫无错误地编译和运行,但是绘制的椭圆仍然没有被 RedrawWindow() 命令清除。知道有什么问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
  • 2010-12-04
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多