2011-12-14 20 views
11

Chciałbym, aby poza ekranem zrenderować Kontrolę do niektórych bitmap, tak, że mam szybki dostęp do niego.Unieważnij do własnej mapy bitowej

Niestety, wydaje się, że Control.DrawToBitmap narysuje całą kontrolkę, na której się ją nazywa, włącznie ze wszystkimi kontrolkami podrzędnymi. Wewnętrznie wysyła wiadomość WM_PRINT z dostarczonym przez siebie DC do bitmapy. Ta tymczasowa bitmapa jest następnie przesyłana do dostarczonej przez użytkownika mapy bitowej. Dla mnie nie do przyjęcia, wolałbym, aby ta bitmapa była aktualizowana w razie potrzeby, więc moja wydajność, gdy bitmapa jest potrzebna, została zminimalizowana.

W idealnym scenariuszu chciałbym, aby formularz zachowywał się tak, jakby był widoczny na ekranie (ale nie może być). Oznaczałoby to, że jeśli, na przykład, niektóre elementy sterowania mają zmienioną właściwość Text, formularz zostanie częściowo unieważniony. Wychwycenie odpowiednich komunikatów/zdarzeń umożliwiłoby mi określenie własnego DC dla formularza, który ma być narysowany, lub po prostu BitBlt form DC do mojego własnego.

niektórych kierunkach Szukałem w:

  • Parametr w OnPaintPaintEventArgs wydaje się posiadać człon savedGraphicsState, być może mogłyby być wykorzystane, aby dowiedzieć się, co nie wymaga unieważnienia
  • mające postać widoczna ale poza obszarem ekranu. Kontrolki nie są malowane.
  • Ręczne wywołanie RedrawWindow() w oknie, sama historia
+0

Nie do końca wiadomo, dlaczego 'DrawToBitmap' (komunikat' WM_PRINT') jest niedopuszczalny do Twojego użytku. Martwisz się * wydajnością *? Jest bardzo mało prawdopodobne, że wciąganie do bitmapy będzie wolniejsze niż rysowanie na ekranie. –

+0

Potrzebuję mechanizmu buforującego. DrawToBitmap maluje całą kontrolę od zera, podczas gdy system unieważniający używany w normalnych oknach aktualizowałby tylko te regiony, które uległy zmianie. –

+0

@Frank, czy rozważałeś użycie Bitblt? http://www.codeproject.com/KB/GDI-plus/Bitblt_wrapper_class.aspx –

Odpowiedz

1

Myślę, że istnieją dwa problemy:

  1. ustaleniu nieprawidłowy obszar kontroli (bez pomocy Windows)
  2. renderowania tylko unieważniona część.

W pierwszym numerze, myślę, że jesteś w dużej mierze samodzielny. Powinieneś śledzić, które kontroluje zmiany, i mieć księgowość, która wymaga aktualizacji.

W drugim numerze możesz spróbować wysłać wiadomość WM_PRINT samemu, i podać DC, odnosząc się tylko do małej bitmapy. Oryginalne interfejsy DC API pozwoliły na przesunięcie i przycięcie prawidłowego obszaru rysowania HDC. Jeśli masz dużo szczęścia, okna wywnioskują region renderowania z HDC, a jeśli nie, większość poleceń renderowania, które całkowicie wypadają z mapy bitowej, powinna być dość tania, ponieważ nie ma pikseli, które trzeba zmienić.

Powinieneś być w stanie to zweryfikować, drukując bitmapę 1x1 i sprawdzając, czy jest szybsza, i/lub sprawdź, czy region klipu wysłany w WM_PAINT jest zredukowany do rozmiaru bitmapy.

0

myślę, że będzie działać, jeśli kontrola jest sklonowany, aby uzyskać kontrolę, która nie siedzieć na formularzu, którego nie ma Kontrola dziecko:

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

użyłem napisany przez lxwde znalezionego w The Code Project.

The ControlFactory nie jest idealny, ale jest prosty i można go łatwo poprawić.

+0

Niestety, nie widzę, jak to ma znaczenie. –

+0

Mówisz, że twoje rozwiązanie niestety wymaga kontroli nad dziećmi. Moje rozwiązanie nie. Próbowałem go z panelem zawierającym przyciski. Przyciąga panel tylko do bitmapy, ale bez elementów sterujących podrzędnych. Działa również, gdy kontrola nie jest widoczna na ekranie. –

+0

Nie bardzo rozumiem, co próbujesz osiągnąć. Mówisz: "Chciałbym, aby formularz zachowywał się tak, jakby był widoczny na ekranie (ale nie może być)". Dlaczego nie może być widoczny na ekranie? Dlaczego chcesz renderować formularz, który nie jest widoczny na ekranie? –

0

Zrobiłem dla ciebie przykładowy projekt, w którym pokazałem kilka wydarzeń onPaint. Jeśli nie możesz go rozwiązać w ten sposób, po prostu zaktualizuj przykład.

Pozdrawiam! OnPaint example

pobrania tutaj: 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 
Powiązane problemy