我有一个各种各样的画布,来自于用于自定义绘制线条和其他几何图形的"面板",全部来自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的绘图速度。
我觉得你说得有点不对。在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
我将添加另一个可能更符合您正在寻找的答案。这是一个继承自Canvas的类,它将允许你用和你在评论中所说的相同的方式来绘制东西。
I还在创建时在随机位置创建一个文本框。
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
这不是一个完整的答案。#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的代码。文本框不显示。问题是这样的:我需要DrawingCanvas中的功能-它派生自Canvas。但是因为基类方法是Protected的,所以我不能访问它们。我只能在派生类中使用它们,除非有我不知道的其他方法。
对于如何解决这个问题有什么想法吗?