nie wiadomo co i jak duzego rysujesz
Rzeczywiście, nie wiadomo... :) Kiedy pierwszy raz pisałem ten temat, to w ostatnim zdaniu nacisnąłem coś przez przypadek i usunąłem siobie wszytko :D I przy powtórnym pisaniu widać zapomniałem dodać. Bitmapa ma szerokość i wysokość okna w którym jest rysowana, czyli obecnie 1000x1000. A jeśli chodzi o to CO rysuję, to... nie ma to aż takiego znaczenia - musiałbym umieścić i udokumentować całą klasę. W każdym razie w pominiętym fragmencie obiekt drawing rysuje sobie coś na bitmapie (parę lini oraz 10 - 20 obiektów typu DrawPath), A drawing.GetBitmap zwraca tą bitmapę.
Nie wiadomo co jest w pierwszej petli (wiec nie wiadomo z czym porownujesz)
-->
I nie chodzi tu o sam wynik (tryb debugowania, komputer już nie najnowszy) ale o proporcję.
Przecież chyba nie jest konieczne przy samym prostym (bez przekształceń) rysowaniu bitmapy 1000x1000 aż tyle czasu! 24500 milisekund daje ćwierć sekundy, a żeby było 100% płynnie powinno być około 10 fps...
POST II:
Hmm... znalazłem coś takiego jab BitBlt (BitBlockTransfer) -> podobno jest szybka. Problem w tym że u mnie nie chce działać ;(
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern int BitBlt(
IntPtr hDestDC,
int xDest,
int yDest,
int nWidth,
int nHeight,
IntPtr hSrcDC,
int xSrc,
int ySrc,
System.Int32 dwRop);
Próbowałem:
Graphics g = e.Graphics;
Graphics d = Graphics.FromImage(drawing.Bitmap);
//...
IntPtr hDestDC = g.GetHdc();
IntPtr hSrcDC = d.GetHdc();
BitBlt(hDestDC, 0, 0, 500, 500, hSrcDC, 0, 0, 0x00CC0020);
g.ReleaseHdc(hDestDC);
d.ReleaseHdc(hSrcDC);
Ale wyświetla po prostu czarny prostokąt! (no dobra, kwadrat)!!!
POST III
AAACH!!!
Po 4 godzinach szukania i próbowanie (im dłużej patrzę na zegar systemowy tym bardziej wydaje mi się że to było 5 godzin...) wreszcie mi się udało!!!
Pracowałem w osobnym projekcie, stworzonym tylko do testów i musiałem napisać mniej więcej coś takiego:
Bitmap bit = new Bitmap(100, 100);
public Form1()
{
InitializeComponent();
Graphics graphicsBit = Graphics.FromImage(bit);
graphicsBit.FillRectangle(Brushes.Red, new Rectangle(new Point(0, 0), bit.Size));
}
const int SRCCOPY = 0xcc0020;
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern int BitBlt(
IntPtr hdcDest, // handle to destination DC (device context)
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
System.Int32 dwRop // raster operation code
);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hDC,
IntPtr hObject);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
public static extern bool DeleteDC(IntPtr hdc);
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics graphTarget = e.Graphics;
IntPtr GraphTargetDC = graphTarget.GetHdc();
IntPtr pSource = CreateCompatibleDC(GraphTargetDC);
SelectObject(pSource, bit.GetHbitmap());
int x = BitBlt(GraphTargetDC, 0, 0, 100, 100, pSource, 0, 0, 0xCC0020);
DeleteDC(pSource);
graphTarget.ReleaseHdc(GraphTargetDC);
pictureBox1.Image = bit;
}
}
Edit: tak, wiem... 3 posty pod rząd... Może trochę przesadziłem, ale zrobiłem to w nadzieji że pomogę komuś kto będzie miał identyczny problem jak ja...
POST IV
Tak, wiem...
Najpierw kod:
Bitmap bit = (Bitmap)drawing.bitmap.Clone();
Graphics targetGraph = e.Graphics;
IntPtr GraphTargetDC = targetGraph.GetHdc();
IntPtr SourcePtr = GDIfxs.CreateCompatibleDC(GraphTargetDC);
GDIfxs.SelectObject(SourcePtr, bit.GetHbitmap());
GDIfxs.BitBlt(GraphTargetDC, 0, 0, ClientSize.Width, ClientSize.Height, SourcePtr, 0, 0, 0x00CC0020);
GDIfxs.DeleteDC(SourcePtr);
targetGraph.ReleaseHdc(GraphTargetDC);
bit.Dispose();
Wszystko działa ładnie i szybko, ale... tylko przez chwilę. Później zaczyna się zacinać. Powód? Jako że jeden obraz wart tysiąca słów, oto informacja od menadżera zadań windows.
Wszystkie te GDI funkcje umieściłem jako statyczne w osobnej klasie (czy to może być powodem?). Domyślam się że nie zwalniam jakiegoś niezarządzanego zasobu, ale nie wiem jakiego. Kilka razy sprawdzałem kod, i nie mogę znaleźć czegoś, co nie byłoby zwalniane. W kodzie nie występuje błąd, czyli nie jest tak że nie dochodzi do momentu zwolnienia. Wewnętrzne funkcje GDI też wykonują się poprawnie (zwraca jeden, czyli true, czyli sukces). Skonsultowałem się z paroma innymi przykładami (chociaż żaden z niech nie polegał na kopiowaniu z bitmapy do formy).
Jedyne co mi przychodzi do głowy to: [???]
Czy ktoś wie, o co może chodzć?
Drobna uwaga: żeby nie załamać moderetorów, których wytrzymałość psychiczną i tak już nadwyrężyły 3 poprzednie posty, połączyłem je wszystkie w jeden. Jak tak dalej pójdzie to wydrukuje ten temat i będę sprzedawał w księgarniach pod swoim nazwiskiem.
I jeszcze jedna edycja: Zastanawiam się czy jest to powodowane przez niezarządzane zasoby, czy po prostu przez ciągłe tworzenie zarządzanych, z którymi GC sobie po prostu nie radzi.