2011-12-14 2 views
11

Я хочу отключить отображение элемента управления некоторым растровым изображением, чтобы у меня был быстрый доступ к нему.Invalidate in own bitmap

К сожалению, Control.DrawToBitmap, похоже, нарисовал весь элемент управления, на который он вызывается, включая все его дочерние элементы управления. Внутри он выдает сообщение WM_PRINT с самообслуживанием DC в растровое изображение. Это временное растровое изображение затем распространяется на предоставленный пользователем битмап. Для меня неприемлемым, я бы предпочел, чтобы это растровое изображение было обновлено по мере необходимости, чтобы моя производительность удалась, когда битмап нужен, минимизирован.

В идеальном сценарии я бы хотел, чтобы форма вела себя так, как если бы она была видна на экране (но этого не может быть). Это означало бы, что если, скажем, какой-то элемент управления имеет свойство Text, форма будет частично аннулирована. Поймав соответствующие сообщения/события, я позволю себе либо указать свой собственный DC для формы, на которую нужно нарисовать, либо просто BitBlt формы DC для моих собственных.

Некоторые направления я заглянула в:

  • Параметр PaintEventArgs в OnPaint кажется держать savedGraphicsState члена, возможно, он может быть использован, чтобы выяснить, что не требует недействительности
  • Имея форму видимой но вне области экрана. Однако элементы управления не окрашиваются.
  • вручную вызова RedrawWindow() в окне, та же история
+0

Я не совсем понимаю, почему 'DrawToBitmap' (сообщение' WM_PRINT') неприемлемо для вашего использования. Вы беспокоитесь о производительности *? Очень маловероятно, что рисование в растровое изображение будет медленнее, чем рисование на экране. –

+0

Мне нужен механизм буферизации. DrawToBitmap красит весь элемент управления с нуля, в то время как система недействительности, используемая в обычных окнах, обновит только те области, которые фактически изменились. –

+0

@Frank, вы считали использовать Bitblt? http://www.codeproject.com/KB/GDI-plus/Bitblt_wrapper_class.aspx –

ответ

1

Я думаю, что есть две проблемы:

  1. выяснив недопустимую область элемента управления (без помощи из окон)
  2. рендеринга только недействительной части.

Для первого выпуска, я думаю, вы в основном сами по себе. Вы должны следить за изменениями в контроле и иметь учетную запись, которая нуждается в обновлении.

Для второй проблемы вы можете попробовать отправить сообщение WM_PRINT самостоятельно и предоставить DC, ссылаясь только на небольшое растровое изображение. Первоначальный DC API позволил вам смещать и обрезать действительную область рисования HDC. Если вам повезет, окна выведут область рендеринга из 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"); 

Я использовал написанный lxwde, найденного в The Code Project.

ControlFactory не совершенен, но он достаточно прост и легко может быть улучшен.

+0

Извините, я не вижу, как это уместно. –

+0

Вы говорите, что ваше решение, к сожалению, привлекает элементы управления для детей. У моего решения нет. Я попробовал его с панелью, содержащей кнопки. Он только рисует панель в растровое изображение, но без дочерних элементов управления. Он также работает, когда элемент управления не отображается на экране. –

+0

Я действительно не понимаю, чего вы пытаетесь достичь. Вы говорите: «Я бы хотел, чтобы форма вела себя так, как будто она была видна на экране (но этого не может быть)». Почему он не может быть видимым на экране? Почему вы хотите отобразить форму, которая не видна на экране? –

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