即使是这样的透明画布也必须重新绘制其背景(包括其背后的东西)。也许这有一些技巧,但每次我遇到组件闪烁问题时,从来没有真正令人满意的解决方案,包括利用组件(甚至自定义)双缓冲。当像这样的实时图形交互成为应用程序的必要部分时,我总是发现最好的选择是转向以“正确方式”处理图形的东西。WPF、XNA 或 DirectX 可能是这个问题的最佳答案。WPF 还添加了诸如路由事件之类的东西,这使得这种单事件->多组件范例更易于编码。
以下是在 winforms 应用程序中使用 WPF 互操作性组件的示例:
1)在表单中添加一个新的 ElementHost(我在这里调用它elementHost1
)
2)向您的项目添加一个新的 WPF UserControl(我称之为TreeCanvas
)
XAML
<UserControl x:Class="WindowsFormsApplication1.TreeCanvas"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="300" Height="300">
<Grid>
<Canvas Name="Canvas1">
<TreeView Canvas.Left="0" Canvas.Top="0" Height="300" Name="TreeView1" Width="300" />
</Canvas>
</Grid>
TreeCanvas 背后的代码不需要任何东西 - 生成的代码InitializeComponent();
就是您现在所需要的。
还有你的表单代码
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
//make a new TreeCanvas
private TreeCanvas MyTreeCanvas = new TreeCanvas();
public Form1()
{
InitializeComponent();
//attach the TreeCanvas component to the element host
this.Width = 400;
this.Height = 400;
elementHost1.Child = MyTreeCanvas;
elementHost1.Location = new System.Drawing.Point(30, 30);
elementHost1.Height = 300;
elementHost1.Width = 300;
// Just adding some random stuff to the treeview
int i = 0;
int j = 0;
for (i = 0; i <= 10; i++)
{
TreeViewItem nitm = new TreeViewItem();
nitm.Header = "Item " + Convert.ToString(i);
MyTreeCanvas.TreeView1.Items.Add(nitm);
for (j = 1; j <= 3; j++)
{
TreeViewItem itm = (TreeViewItem)MyTreeCanvas.TreeView1.Items[i];
itm.Items.Add("Item " + Convert.ToString(j));
}
}
//Draw a line on the canvas with the treeview
Line myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.Red;
myLine.X1 = 1;
myLine.X2 = 50;
myLine.Y1 = 1;
myLine.Y2 = 300;
myLine.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
MyTreeCanvas.Canvas1.Children.Add(myLine);
}
}
}
这为您在画布内提供了一个树视图,您可以在其顶部进行绘制,同时仍然可以单击和操作下面的树视图(包括鼠标滚动事件等)。
如果您直接在一行上单击,则单击将不会通过,同样,如果鼠标直接悬停在画布上的一行上,则滚动事件之类的事情将不会通过,但是如果您阅读了Routed Events您可以很容易地连线在 TreeCanvas 类中将它们组合在一起。