0

我有一个从用于自定义绘制线条和其他几何图形的“面板”派生的各种画布,全部来自 VB 代码。我从一本书中得到了这种方法,但我不确定它是否是最好的方法。绘图部分到目前为止对我有用。

但我需要的是在包含用户可以编辑的文本的控件上放置一个文本框控件。文本框需要放置在动态确定并稍后删除的坐标处。可能会处理其他控件。

下面的代码什么都不做:

    tb = New TextBox()
    tb.Text = "How now brown cow?"
    tb.BorderThickness = New Thickness(3)
    tb.BorderBrush = Brushes.CadetBlue
    drawingSurface.Children.Add(tb)

这是我的 DrawingCanvas 的定义:

    Public Class DrawingCanvas
   Inherits Panel

    Private visuals As New List(Of Visual)()
    Private hits As New List(Of DrawingVisual)()

   Protected Overrides Function GetVisualChild(ByVal index As Integer) As Visual
      Return visuals(index)
   End Function
   Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
      Get
         Return visuals.Count
      End Get
   End Property

   Public Sub AddVisual(ByVal visual As Visual)
      visuals.Add(visual)
        MyBase.AddVisualChild(visual)
      MyBase.AddLogicalChild(visual)
   End Sub

   Public Sub DeleteVisual(ByVal visual As Visual)
      visuals.Remove(visual)
        MyBase.RemoveVisualChild(visual)
      MyBase.RemoveLogicalChild(visual)
   End Sub

   Public Function GetVisual(ByVal point As Point) As DrawingVisual
      Dim hitResult As HitTestResult = VisualTreeHelper.HitTest(Me, point)
      Return TryCast(hitResult.VisualHit, DrawingVisual)
   End Function

    Public Function GetVisuals(ByVal region As Geometry) As List(Of DrawingVisual)
        hits.Clear()
        Dim parameters As New GeometryHitTestParameters(region)
        Dim callback As New HitTestResultCallback(AddressOf Me.HitTestCallback)
        VisualTreeHelper.HitTest(Me, Nothing, callback, parameters)
        Return hits
    End Function

   Private Function HitTestCallback(ByVal result As HitTestResult) As HitTestResultBehavior
      Dim geometryResult As GeometryHitTestResult = CType(result, GeometryHitTestResult)
      Dim visual As DrawingVisual = TryCast(result.VisualHit, DrawingVisual)
      If visual IsNot Nothing AndAlso geometryResult.IntersectionDetail = IntersectionDetail.FullyInside Then
            hits.Add(visual)
            MsgBox("Ouch")
      End If
      Return HitTestResultBehavior.Continue
   End Function
End Class

这是 XAML。我在 DrawingCanvas 中添加了一个文本框,只是为了查看是否出现了某些内容。什么也没做。事实上,我想在代码中执行此操作,而不是 XAML。我想我可以动态地隐藏或移动它。

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Music"
    Title="MainWindow" Height="539" Width="892">
    <DockPanel>
        <Menu DockPanel.Dock="Top" Name="MainMenu" VerticalAlignment="Top" Height="25">
            <MenuItem Name="File" Header="File">
                <MenuItem Name="Open" Header="Bla bla..."/>
            </MenuItem>
        </Menu>
        <local:DrawingCanvas DockPanel.Dock="Bottom" x:Name="drawingSurface" RenderTransformOrigin="0.5,0.5" >
            <TextBox Height="0" Name="TextBox1" Width="45" Text="How now brown cow?" />
        </local:DrawingCanvas>
    </DockPanel>
</Window>

感谢您帮助一个菜鸟。一个解决方案对我来说非常有用。使用 Windows 窗体很容易,但我需要 WPF 的绘图速度。

4

3 回答 3

0

我觉得你有点离题了。在 WPF 中,您有一个名为 Canvas 的控件。我建议您使用它而不是您自己的“DrawingCanvas”,顺便说一句,我无法使用它。:((由于某种原因,我无法创建代码块,所以如果有人可以编辑它,我会很高兴)

无论如何,

<local:DrawingCanvas DockPanel.Dock="Bottom" x:Name="drawingSurface" RenderTransformOrigin="0.5,0.5" >
   <TextBox Height="0" Name="TextBox1" Width="45" Text="How now brown cow?" />
</local:DrawingCanvas>

变成:

 <Canvas x:Name="drawingSurface">

 </Canvas>

然后添加一个文本框就像你当前的代码一样:

Dim tb as New TextBox 
drawingSurface.Children.Add(tb)

这应该给你你所需要的。

这是向画布添加矩形的代码。

Private Sub DrawBackground()
    Dim Rect As New Rectangle()
    Rect.Height = 50
    Rect.Width = 50
    Rect.Fill = Brushes.Cornsilk
    drawingSurface.SetTop(Rect, 30)
    drawingSurface.SetLeft(Rect, 100)
    drawingSurface.Children.Add(Rect)
End Sub
于 2013-04-29T07:17:56.223 回答
0

这不是一个完整的答案。#WozzeC,你使用画布是对的——几乎。

我已经设法仅在 xaml 中解决了这个问题 - 我想最终在 vb.net 中解决它。

<Window x:Class="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">
<Grid>
    <DockPanel HorizontalAlignment="Stretch" Name="DockPanel1" VerticalAlignment="Stretch" >
        <Menu Height="23" DockPanel.Dock="Top"  Name="Menu1" VerticalAlignment="Top" />
        <Canvas Name="Canvas1" Background="Aquamarine">
            <TextBox Canvas.Left="118" HorizontalScrollBarVisibility="Disabled" Canvas.Top="81" AcceptsReturn="True"  Height="auto" Name="TextBox1" Width="68" Text="Herpdiderp" BorderThickness="0" Background="Aquamarine" />
        </Canvas>
    </DockPanel>
</Grid>

这是一段根据需要扩展文本的代码。我认为这几乎完全很酷。它向右和向下扩展,就好像您实际上是在表单上打字一样。右边加的有点多,但是在这个版本中是看不到的,因为背景颜色是一样的。

这是将其扩展到右侧的事件代码。

    Imports System.Globalization
Class MainWindow
Private Sub TextBox1_TextChanged(sender As System.Object, e As System.Windows.Controls.TextChangedEventArgs) Handles TextBox1.TextChanged
    Dim ft As New FormattedText(TextBox1.Text, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, New Typeface("Verdana"), 16, Brushes.Black)
    TextBox1.Width = ft.Width
End Sub
End Class

我用我现有的解决方案尝试了这个,文本框没有出现。我把 DrawingCanvas 做成了一个普通的 Canvas,并注释掉了所有引用 DrawingCanvas 的代码。并且文本框确实出现了。问题是这样的:我需要从 Canvas 派生的 DrawingCanvas 中的功能。但是因为基类方法是受保护的,所以我无法使用它们。我只能在派生类中使用它们,除非有另一种我不知道的方式。

关于如何解决这个问题的任何想法?

于 2013-05-05T20:26:14.423 回答
0

我将添加另一个可能更符合您正在寻找的答案的答案。这是一个继承自 Canvas 的类,它允许您以与您在评论中所说的相同的方式绘制内容。

我还在创建时在随机位置创建了一个文本框。

Public Class DrawingCanvas
    Inherits Canvas
    Public RandomTextBox As New TextBox
    Protected Overrides Sub OnRender(dc As System.Windows.Media.DrawingContext)
        Dim brush As Brush = Brushes.Black
        Dim drawingPen As Pen = New Pen(Brushes.Green, 3)
        dc.DrawRectangle(brush, drawingPen, New Rect(5, 5, Me.ActualWidth - 5, Me.ActualHeight - 5))
        RandomTextBox.Text = "Herpdiderp"
        If Not Me.Children.Contains(RandomTextBox) Then
            Dim r As New Random()
            RandomTextBox.Height = 23
            RandomTextBox.Width = 100
            Me.SetTop(RandomTextBox, r.Next(0, Me.ActualHeight - RandomTextBox.Height))
            Me.SetLeft(RandomTextBox, r.Next(0, Me.ActualWidth - RandomTextBox.Width))
            Me.Children.Add(RandomTextBox)
        End If
    End Sub
End Class
于 2013-04-30T09:04:21.693 回答