2016-10-13 4 views
-1

Ich bekomme eine sehr schlechte peformance Zeichnung mit Win32. Es braucht zu viel Zeit und muss verbessert werden. Bitte beraten.Drawing peformance mit Win32

Hier ist was ich mache.

HDC dc = GetDC(wnd); 
HDC memoryDc = CreateCompatibleDC(dc); 
HBITMAP memoryMapBitmap = CreateCompatibleBitmap(dc, 400, 400); 
HGDIOBJ originalBitmap = SelectObject(memoryDc, memoryMapBitmap); 

Dann zeichne ich in einer for-Schleife wie folgt.

HBRUSH brush = (HBRUSH)GetStockObject(DC_BRUSH); 
SetDCBrushColor(memoryDc, colorRef); 
FillRect(memoryDc, &rect, brush); 

Und schließlich habe ich eine Bereinigung

SelectObject(memoryDc, originalBitmap); 
DeleteDC(memoryDc); 
ReleaseDC(wnd, dc); 

Zeichnung viel Zeit (mehrere Sekunden) dauert. Gibt es eine Möglichkeit, mit Win32 schneller zu zeichnen?

Vielen Dank im Voraus!

+1

'EnableFastDrawing (DRAWING_SPEED_ULTRA_FAST)'. Aber im Ernst, zeigen Sie uns [mcve] und wir können Ihnen helfen –

+0

Klingt so, als würden Sie Ihre Zeichnung erstellen, wenn Sie einen Renderzyklus durchführen. Das ist eine kostspielige Operation. Erstellen Sie immer nur einen Domänencontroller, wenn sich die Fenstergröße ändert. Und es sei denn, Sie haben einen sehr guten Grund ™, um nicht Ihr ganzes Rendering von Ihrem 'WM_PAINT'-Handler durchzuführen, tun Sie es einfach nicht. – IInspectable

+0

No-no, Zeichnung wird nicht in WM_PAINT gemacht. Ich zeichne nach dem Laden einer Datei, dann setze ich die Bitmap in ein Steuerelement Irgendwie ist das Zeichnen auf der Speicherbitmap sehr langsam. Microsoft-Dokumentation hilft mir leider nicht viel. Ich werde weiter schauen ... – Bambur

Antwort

0

Es sieht so aus, als ob ich es gelöst habe. Unten ist die Lösung mit einigen Kommentaren.

Ich habe einen Dialog in RC-Datei definiert. Es gibt ein Steuerelement, um ein Bitmap-Bild im Dialogfeld anzuzeigen.

CONTROL   "", IDC_MEMORY_MAP, WC_STATIC, SS_BITMAP | SS_CENTERIMAGE | SS_SUNKEN, 9, 21, 271, 338, WS_EX_LEFT 

Im Laufzeit ich erstellen müssen, zeichnen und eine Bitmap-Anzeige:

HWND map = GetDlgItem(dlg, IDC_MEMORY_MAP); 
HBITMAP bitmap = createMemoryMapBitmap(map); 
bitmap = (HBITMAP)SendMessage(map, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmap); 
DeleteObject(bitmap); // (!) this is a very important line, otherwise old bitmap leaks 

Code, der die Größe des Bitmap erstellen findet heraus:

HBITMAP createMemoryMapBitmap(HWND map) { 
    RECT rect = {0, 0, 0, 0}; 
    GetClientRect(map, &rect); 
    SIZE size = {rect.right - rect.left, rect.bottom - rect.top}; 

    HDC dc = GetDC(map); 
    HBITMAP bitmap = doCreateMemoryMapBitmap(dc, &size); 
    ReleaseDC(map, dc); 

    return bitmap; 
} 

Schließlich erstellen wir die Bitmap und zeichnen darauf:

HBITMAP doCreateMemoryMapBitmap(HDC dc, LPSIZE bitmapSize) { 
    // create 24bpp bitmap in memory in order to draw fast 

    BITMAPINFO info; 
    memset(&info, 0, sizeof(info)); 
    info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    info.bmiHeader.biWidth = bitmapSize->cx; 
    info.bmiHeader.biHeight = bitmapSize->cy; 
    info.bmiHeader.biPlanes = 1; 
    info.bmiHeader.biBitCount = 24; 
    info.bmiHeader.biCompression = BI_RGB; 

    void *pixels = NULL; 
    HBITMAP memoryBitmap = CreateDIBSection(dc, &info, DIB_RGB_COLORS, &pixels, NULL, 0); 

    HDC memoryDc = CreateCompatibleDC(dc); // (!) memoryDc is attached to current thread 
    HGDIOBJ originalDcBitmap = SelectObject(memoryDc, memoryBitmap); 

    // drawing code here 

    // perform windows gdi cleanup 

    SelectObject(memoryDc, originalDcBitmap); // restore original bitmap in memoryDC (optional step) 
    DeleteDC(memoryDc); // this releases memoryBitmap from memoryDC 

    return memoryBitmap; 
} 

Die obige Idee ist, eine 24bpp-Bitmap im Speicher zu erstellen und darauf zu zeichnen. Auf diese Weise ist das Zeichnen schnell, wie @Intspectable gezeigt hat.

Wenn sich die Anzeige im indizierten Farbmodus befindet, z. Mit 16 oder 256 Farben scheint die native Windows-Steuerung intelligent genug zu sein, um die Farbtiefe automatisch zu konvertieren und die Bitmap anzuzeigen.