2011-12-14 28 views
11

我希望將屏幕呈現爲某個位圖的控件,以便我可以快速訪問它。對自己的位圖無效

不幸的是Control.DrawToBitmap似乎繪製了它被調用的整個控件,包括它的所有子控件。它在內部使用自提供的DC將WM_PRINT消息發送到位圖。這個臨時位圖然後blitted到用戶提供的位圖。對我而言,這是不可接受的,我寧願根據需要更新此位圖,以便在需要位圖時將性能降至最低。

在理想的情況下,我希望窗體的行爲就好像它在屏幕上可見(但不能)。這意味着如果某些控制的Text屬性發生更改,表單將會部分失效。捕獲相關的消息/事件將允許我指定我自己的DC來繪製表單,或者將表單DC簡單地BitBlt到我自己的表單。

我已經看了一些方向:

  • OnPaintPaintEventArgs參數似乎舉行成員savedGraphicsState,也許它可以用來找出不需要無效
  • 具有形式可見但在屏幕區域之外。然而,控件不會被繪製。
  • 手動調用RedrawWindow()的窗口上,同樣的故事
+0

我不完全清楚爲什麼`DrawToBitmap`(`WM_PRINT`消息)是不可接受的爲您使用。你擔心*表演*嗎?繪製位圖不太可能比畫在屏幕上慢。 – 2011-12-17 10:22:11

+0

我需要一個緩衝機制。 DrawToBitmap從頭開始繪製整個控件,而在正常窗口中使用的無效系統只會更新實際更改的區域。 – 2011-12-17 13:00:38

回答

1

我覺得有兩個問題:

  1. 找出控制的無效區域(不包括從Windows幫助)
  2. 只渲染失效的部分。

對於第一個問題,我認爲你主要靠自己。您應該跟蹤哪些控件更改,並且需要更新的簿記。

對於第二個問題,您可以嘗試自己發送WM_PRINT消息,並提供僅引用一個小位圖的DC。原始的DC API允許您抵消和剪切HDC的有效繪圖區域。 如果你非常幸運,windows會從HDC中推導出渲染區域,如果沒有,那麼完全脫離位圖的大部分渲染命令應該是相當便宜的,因爲沒有像素需要更改。

您應該能夠通過打印到1x1位圖並測試它是否更快來驗證此問題,並且/或驗證WM_PAINT中發送的剪輯區域是否縮小到位圖大小。

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"); 

我用寫在The Code Project發現lxwde。

ControlFactory不完美,但它很簡單,可以很容易地改進。

0

我爲你做了一個示例項目,在那裏展示了一些onPaint事件。如果你看不到它以這種方式解決,只需更新示例。

問候! OnPaint example

這裏下載: 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