我希望屏幕外显示一个控件到一些位图,以便我可以快速访问它。
不幸的是Control.DrawToBitmap
似乎绘制了它所调用的整个控件,包括它的所有子控件。在内部,它向位图发出带有自提供DC的WM_PRINT消息。然后将此临时位图blitting到用户提供的位图。对我来说不可接受,我宁愿根据需要更新这个位图,以便在需要位图时我的性能最小化。
在理想情况下,我希望表单的行为就像它在屏幕上可见(但它不可能)。这意味着,如果某个控件的Text
属性发生了变化,则表单将部分失效。捕获相关的消息/事件将允许我为要绘制的表单指定我自己的DC,或者简单地将表单DC BitBlt到我自己的。
我看过的一些方向:
PaintEventArgs
中的OnPaint
参数似乎包含一个成员savedGraphicsState,也许它可以用来找出不需要无效的内容答案 0 :(得分:1)
我认为有两个问题:
对于第一期,我认为你很大程度上依靠自己。您应该跟踪哪些控件发生变化,并进行需要更新的簿记。
对于第二个问题,您可以尝试自己发送WM_PRINT消息,并提供仅涉及小位图的DC。原始DC API允许您偏移和剪切HDC的有效绘图区域。 如果你很幸运,windows会从HDC中推断出渲染区域,如果没有,那么大部分完全脱离位图的渲染命令应该非常便宜,因为没有像素需要改变。
您应该能够通过打印到1x1位图并测试它是否更快来验证这一点,和/或验证WM_PAINT中发送的剪辑区域是否减少到位图大小。
答案 1 :(得分:0)
我认为如果克隆了控件,它会起作用,这样你就可以获得一个不在表单上并且没有子控件的控件:
Control ctrl = ControlFactory.CloneCtrl(this.button3);
Bitmap bmp = new Bitmap(ctrl.Width, ctrl.Height);
ctrl.DrawToBitmap(bmp, new Rectangle(0, 0, ctrl.Width, ctrl.Height));
bmp.Save(@"C:\Users\Oli\Desktop\test.bmp");
我使用了ControlFactory中找到的lxwde编写的The Code Project。
ControlFactory并不完美,但它很简单,很容易改进。
答案 2 :(得分:0)
我为你做了一个示例项目,在那里我展示了一些onPaint事件。如果您无法通过这种方式看到它,请更新示例。
问候!
在此下载: http://www.goldengel.ch/temp/OnPaintExample.zip
Private Sub Button1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles Button1.Paint
Dim bm As New Bitmap(Me.Button1.Width, Me.Button1.Height, PixelFormat.Format32bppRgb)
Button1.DrawToBitmap(bm, New Rectangle(0, 15, bm.Width -5, bm.Height+2))
Using gr As Graphics = Graphics.FromImage(bm)
gr.DrawString(DateTime.Now.ToLongTimeString, Me.Font, Brushes.Lime, 0, 0)
End Using
Me.PictureBox1.BackgroundImageLayout = ImageLayout.Tile
Me.PictureBox1.BackgroundImage = bm
End Sub
Public Class myTextBox
Inherits System.Windows.Forms.TextBox
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
e.Graphics.Clear(Color.Yellow)
e.Graphics.DrawString(DateTime.Now.ToLongTimeString, Me.Font, Brushes.Gray, 0, 0)
End Sub
Public Sub New()
SetStyle(ControlStyles.UserPaint, True)
End Sub
End Class