2012-02-03 19 views
6

Mam kilka niestandardowych (winformy) składników, które rysują na ekranie przy użyciu GDI +.Co może spowodować, że Double Buffering zabije moją aplikację?

Aby zapobiec migotaniu na repaint, postanowiłem włączyć podwójne buforowanie, więc dodałem linię do mojego konstruktora:

public ColourWheel() 
{ 
    InitializeComponent(); 
    this.DoubleBuffered = true; 
} 

Które działa dobrze na tym składniku (ColourWheel). Kiedy dodać taką samą linię do konstruktora jednej z moich dwóch innych (podobnie strukturyzowanych) komponentów, mam kilka dziwnych objawów:

  1. gdy próbuję uruchomić formularz ze składnikiem sprawie, otrzymuję Wyjątek argumentu na Application.Run(new Form());.
  2. Po przejściu do trybu projektowania pojawia się błąd dotyczący składnika mającego nieobsługiwany wyjątek związany z parametrem.

Nie ma znaczenia, czy zmieniam podwójne buforowanie na jednym czy z każdym, nadal działa na ColourWheel, ale nie na innych.

Dla przypomnienia, wypróbowałem także kilka innych technik doublebuffering.

Co może powodować podwójne buforowanie do pracy na jednym komponencie, ale inne nie?


EDIT: Oto szczegóły wyjątek od objawu run-time:

System.ArgumentException był nieobsługiwany Message = Parametr nie jest ważny. Źródło = System.Drawing StackTrace: w System.Drawing.Graphics.GetHdc() w System.Drawing.BufferedGraphics.RenderInternal (HandleRef refTargetDC bufor BufferedGraphics) w System.Drawing.BufferedGraphics.Render() w System.Windows .Forms.Control.WmPaint (Message & m) w System.Windows.Forms.Control.WndProc (Message & m) w System.Windows.Forms.ScrollableControl.WndProc (Message & m) w System.Windows.Forms .UserControl.WndProc (Message & m) w System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Wiadomość & m) w System.Windows.Forms.Co ntrol.ControlNativeWindow.WndProc (Message & m) w System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd, Int32 MSG IntPtr wParam, IntPtr LPARAM) w System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW (MSG & MSG) w System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (IntPtr dwComponentID, Int32 powodu Int32 pvLoopData) w System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (Int32 powód, kontekst ApplicationContext) w System.Windows.Forms.Application.ThreadContext.RunMessageLoop (Int32 powód, kontekst ApplicationContext) w S ystem.Windows.Forms.Application.Run (Form mainForm) w TestForm.Program.Główny() w D: \ Documents and Settings \ Tom Wright \ Moje dokumenty \ Visual Studio 2010 \ Projects \ ColourPicker \ TestForm \ Program.cs: wiersz 18 w System.AppDomain._nExecuteAssembly (zestaw RuntimeAssembly, String [] args) w System.AppDomain.ExecuteAssembly (string assemblyFile, Evidence assemblySecurity, String [] args) w Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() w System.Threading.ThreadHelper.ThreadStart_Context (stan obiektu) w System.Threading .ExecutionContext.Run (ExecutionContext executionContext, ContextCallback callback, Stan obiektu, Boolean ignoreSyncCtx) w System.Threading.ExecutionContext.Run (ExecutionContext executionContext, Callback ContextCallback, Stan obiektu) w System.Threading.ThreadHelper.ThreadStart() InnerException:


EDIT 2: Handler OnPaint z jednego (bardziej skomplikowane) dwóch elementów, które powodują problemy:

private void ValueSlider_Paint(object sender, PaintEventArgs e) 
{ 
     using (Graphics g = e.Graphics) 
     { 
      g.DrawImage(this.gradientImage, new Rectangle(0, 0, paintArea.Width, paintArea.Height)); 
      if (this.showmarker) 
      { 
       ColourHandler.HSV alt = ColourHandler.RGBtoHSV(new ColourHandler.RGB(this.SelectedColour.R, this.SelectedColour.G, this.SelectedColour.B)); 
       alt.Saturation = 0; 
       alt.value = 255 - alt.value; 
       using (Pen pen = new Pen(ColourHandler.HSVtoColour(alt))) 
       { 
        pen.Width = (float)MARKERWIDTH; 
        g.DrawRectangle(pen, 0 - pen.Width, this.brightnessPoint.Y - MARKERWIDTH, this.paintArea.Width + (pen.Width * 2), MARKERWIDTH * 2); 
       } 
      } 
     } 
} 
+0

Proszę udostępnić wyjątek. – roken

+1

@roken Wszystkie twoje przyjacielu. –

+0

Czy nadpisujesz OnPaint() w obraźliwych kontrolkach? Jeśli tak, jak to wygląda? – roken

Odpowiedz

8

Nie należy udostępniać obiektu Graphics wypożyczonego w trakcie imprezy Paint, a to właśnie blokuje niewłaściwie Twój blok .

Objawem jest to, że następnym razem Zdarzenie Paint, masz taką samą Graphics obiekt z powrotem, ale to nie jest już związany z in-memory HDC, powodując Graphics.GetHdc() na niepowodzenie, jak widać w ślad stosu.

  1. Jest możliwe, że żyją dłużej pojedynczy Paint zdarzenie (i to jest bardzo prawdopodobne w przypadku podwójnego buforowania, choć możliwe jest również z pojedynczym buforowaniem jeśli styl CS_OWNDC okno jest ustawione).

  2. Dla zdarzenia Paint może być więcej niż jeden program obsługi.

Więc obsługi zdarzeń nie powinno nazywać Dispose na Graphics obiektów lub pozwolić using blok, aby to zrobić. Zamiast tego środowisko .NET oczyszcza zasoby odpowiednio po zakończeniu obsługi zdarzeń.

+1

To działało przez ponad rok, a następnie, kiedy przeniosłem klasy kontroli użytkownika do własnego pliku rozpoczęty, zgłaszając błąd OP tutaj. To, co zasugerowałeś, zadziałało - C# czasami może być naprawdę dziwne! –

1

Powinieneś przetestować to na innym komputerze, aby sprawdzić, czy to tylko komputer, czy nie. W większości przypadków nie powinno to mieć miejsca w wyniku podwójnego buforowania, ale sprawdź, czy nie wyrzucasz żadnych elementów, których nie powinieneś znajdować się w zdarzeniu Paint, ani nie wykonuj niczego w kodzie, który powodowałby problemy, gdyby został wykonany dwukrotnie.

+2

Nie sądzę, że powinieneś pozbyć się obiektu 'Graphics' przydzielonego ci podczas zdarzenia' Paint'. –

+0

@ben ma rację. Nie rób "używania" na "g", ponieważ spowoduje to wyrzucenie obiektu Graphics po wyjściu z tego zakresu, ale nie jesteś "właścicielem" tego obiektu. –

+0

Dzięki chłopaki. Robiłem 'using (Graphics g = e.Graphics) {}'. Usunięcie tego było kluczowe. –

Powiązane problemy