English 中文(简体)
如何使用旋转和转换路径的可视性来使用鼠标点击测试
原标题:How to Mouse Hittest using IsVisible with rotated and transformed paths

我用 GDI+ 绘制可缩放矢量图形, 我需要在鼠标移动时进行点击测试。 我所看到的所有例子都使用模型空间 = 世界空间, 没有变换。 下面是问题的一个简化示例 :

Imports System.Drawing.Drawing2D

Public Class Form1

  Private myrect As New GraphicsPath

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

      The rectangle s centre is at 30,10. Move to origin to rotate
    e.Graphics.TranslateTransform(-30, -10, Drawing2D.MatrixOrder.Append)
    e.Graphics.RotateTransform(45, Drawing2D.MatrixOrder.Append)

      Move it back, 50x50 away from the origin 
      (80,60 because we moved -30,-10 to rotate)
    e.Graphics.TranslateTransform(80, 60, Drawing2D.MatrixOrder.Append)
    e.Graphics.DrawPath(New Pen(Brushes.Black, 2), myrect)

      ...loads more painting, many paths, many varying transformations

  End Sub

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load

      Make a rectangle 60x20 with top-left corner at the origin
    myrect.AddLine(0, 0, 60, 0)
    myrect.AddLine(60, 0, 60, 20)
    myrect.AddLine(60, 20, 0, 20)
    myrect.CloseFigure()

      ...loads more shapes created here

  End Sub

  Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove

      Pretend that all the drawing stuff above happened some unspecified time ago, 
      in different assembly, written by a martian, in some other vile language.
      Obviously, his "e.graphics" has long since been garbage-collected.
    If myrect.IsVisible(e.Location) Then
          Works when moving over the path at the origin, ignores transforms.
        Debug.WriteLine("Over the rectangle at " & e.Location.ToString)
    End If

  End Sub

End Class

Which produces (mouse moving in red) enter image description here

在变形前的矩形“强”是“强”之前的矩形。

我知道如果我有在Onpaint使用的图形, 我可以用它来用变换来进行测试, 但金则说“永远不要保存图形”。

欢迎提出任何建议。


死后:请记录一下, 文森特回答的落实情况,

Imports System.Drawing.Drawing2D

Public Class Form1

  Private myrect As New GraphicsPath
  Private mytransform As Matrix

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

      The rectangle s centre is at 30,10. Move to origin to rotate
    e.Graphics.TranslateTransform(-30, -10, Drawing2D.MatrixOrder.Append)
    e.Graphics.RotateTransform(45, Drawing2D.MatrixOrder.Append)

      Move it back, 50x50 away from the origin 
      (80,60 because we moved -30,-10 to rotate)
    e.Graphics.TranslateTransform(80, 60, Drawing2D.MatrixOrder.Append)
    e.Graphics.DrawPath(New Pen(Brushes.Black, 2), myrect)
    mytransform = e.Graphics.Transform

      ...loads more painting, many paths, many varying transformations

  End Sub

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load

      Make a rectangle 60x20 with top-left corner at the origin
    myrect.AddLine(0, 0, 60, 0)
    myrect.AddLine(60, 0, 60, 20)
    myrect.AddLine(60, 20, 0, 20)
    myrect.CloseFigure()

      ...loads more shapes created here

  End Sub

  Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove

    mytransform.Invert()
    Dim mouseat() As Point = {e.Location}
    mytransform.TransformPoints(mouseat)
    If myrect.IsVisible(mouseat(0)) Then
          Works when moving over the path at the origin, ignores transforms.
        Debug.WriteLine("Over the rectangle at " & e.Location.ToString)
    End If

  End Sub

End Class
最佳回答

保存图形对象的世界变换矩阵( Graphics. transform), 反转它( 因此它从页面到世界坐标 - 我认为在这样的情况下, 页面坐标等于设备坐标, 但如果不是您需要做更多的工作来计算缩放), 并在进行撞击测试之前用它来转换点 。

编辑 : 您也可以将用于构建世界的OnPaint 中的逻辑计算为一种不需图形对象的单独方法, 并返回一个矩阵, 然后与图形一起使用该矩阵。 Multiply Transform, 或反转, 并用于修改输入坐标 。

问题回答

缩放 变换 和 转换 变换 方法 更改图形的属性。 您想要保持图形的属性。 您想要保持此属性, 将相同的变换应用到鼠标的位置将会是 < em> very 方便的 。 如果您对单个形状应用变换, 您想要为每个形状保存矩阵 。

矩阵。 Transformpoints () 然后解决您的问题 。





相关问题
Bring window to foreground after Mutex fails

I was wondering if someone can tell me what would be the best way to bring my application to the foreground if a mutex was not able to be created for a new instance. E.g.: Application X is running ...

How to start WinForm app minimized to tray?

I ve successfully created an app that minimizes to the tray using a NotifyIcon. When the form is manually closed it is successfully hidden from the desktop, taskbar, and alt-tab. The problem occurs ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

Handle DataTable.DataRow cell change event

I have a DataTable that has several DataColumns and DataRow. Now i would like to handle an event when cell of this DataRow is changed. How to do this in c#?

Apparent Memory Leak in DataGridView

How do you force a DataGridView to release its reference to a bound DataSet? We have a rather large dataset being displayed in a DataGridView and noticed that resources were not being freed after the ...

ALT Key Shortcuts Hidden

I am using VS2008 and creating forms. By default, the underscore of the character in a textbox when using an ampersand is not shown when I run the application. ex. "&Goto Here" is not ...

WPF-XAML window in Winforms Application

I have a Winforms application coded in VS C# 2008 and want to insert a WPF window into the window pane of Winforms application. Could you explain me how this is done.

热门标签