Endlich Pixelkontrolle Visual Studio 22



  • Hallo Leute, ich war ziemlich heftig im Internet am wühlen, bis ich es endlich geschafft habe, einem C++ - Programm
    die Möglichkeit zu verleihen mittels indizierten Pixelzugriffs eine bunte Graphik aufs Fenster zu zeichnen:

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Zeichencode, der hdc verwendet, hier einfügen...
            //==========PIXELSET SUBROUTINE=================================================
            int  x, y;               // Coordinates.
            COLORREF Light = RGB(200, 200, 00);
            COLORREF Dark  = RGB(255,  50, 90);
            int X_Cnt; int Y_Cnt;
                X_Cnt = 100;
            while (X_Cnt > 0)
            { X_Cnt --;
              Y_Cnt = 100;
              while(Y_Cnt > 0 )
              { Y_Cnt--;
                x = 50 + X_Cnt;
                y = 50 + Y_Cnt;
                if( ((X_Cnt & 12) == 12)   &&  ((Y_Cnt & 12) == 12)   )
                             SetPixel(hdc, x, y, Light);
                else         SetPixel(hdc, x, y, Dark);
              };
            };
            //========PIXELSET SUBROUTINE======================================================
    

    Ich habe mir die kostenlose microsoft visual Studio 22 Software herunter geladen, und habe ein neues Projekt erstellt,
    und zwar eine Windows- Desktop-Anwendung, mit graphischer Benutzeroberfläche, die unter Windows ausgeführt wird.
    Da habe ich diese Codesektion, die ich hier poste, erstmal an einer anderen Stelle

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    switch (message)
    {
    case WM_COMMAND:
    {
    int wmId = LOWORD(wParam);
    // Menüauswahl analysieren:
    switch (wmId)
    {
    case IDM_ABOUT:
    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    //==========PIXELSET SUBROUTINE=================================================
    //==========PIXELSET SUBROUTINE=================================================

    eingefügt, doch das ging in die hose, der meldete den Compilerfehler daß die Variable wcex in ATOM MyRegisterClass(HINSTANCE hInstance) nicht initialisiert ist. Das ist reichlich seltsam, wenn ich einen
    Befehl GetDC() hinzufüge, und schon ist die Variable nicht initialisiert, die ohne den Befehl initialisiert ist.

    Aber ich habe es dann an der richtigen Stelle eingefügt, und endlich lief es. Das war ein zähes Ringen,
    denn ich musste an die INFORMATION heran kommen. Und diese INFORMATION hat mich etliche
    Tage gekostet, in einer sehr unübersichtlichen Internet-Suchmaschine google. Das war auch wieder ein
    Krampf an diese Dateien ran zu kommen, ich musste erstmal MinGW installieren mit dem G++ - Compiler
    im MingGW\bin - Verzeichnis und mit einem MinGW\include - Verzeichnis. Dort wurde ich dann endlich fündig, mit der
    windows.h -Datei, die Winbase includiert, und wingdi.h und vieles mehr. Dort muss ich jetzt weiter wühlen für die schnellen
    gepufferten Bitmap-Tools, Mauskontrolle und so weiter. Habt ihr Info ?



  • @ralfsobe sagte in Endlich Pixelkontrolle Visual Studio 22:

    Habt ihr Info ?

    I haz info.



  • Aber mal ernsthaft: wenn du ein Windows GDI Programm schreiben willst, dann könntest du z.B. mal ein bisschen in der Windows GDI Doku stöbern: https://docs.microsoft.com/en-us/windows/win32/gdi/windows-gdi

    Und falls du nicht/schlecht Englisch kannst hab ich eine Mission für dich: lern Englisch. Denn ohne gute Englischkenntnisse wird Programmieren Lernen eher mühsam.



  • @ralfsobe sagte in Endlich Pixelkontrolle Visual Studio 22:

    Aber ich habe es dann an der richtigen Stelle eingefügt, und endlich lief es. Das war ein zähes Ringen,
    denn ich musste an die INFORMATION heran kommen. Und diese INFORMATION hat mich etliche
    Tage gekostet, in einer sehr unübersichtlichen Internet-Suchmaschine google.

    Dran bleiben! Das wird mit der Zeit einfacher, wenn man mehr Erfahrung hat. Dann muss man zwar immer noch sehr viel nachschlagen, aber man weiss wo man suchen muss und versteht besser, wie alles zusammenhängt. Ich denke auch von denjenigen mit langjähriger Erfahrung wird wohl so ziemlich keiner wirklich alle benötigten APIs komplett auswendig kennen.

    Der Link von @hustbaer ist ein guter Einstieg und die Sache mit dem Englisch ein Tip, bei dem ich mich anschliessen möchte.

    Ergänzend möchte ich noch erwähnen, dass GDI SetPixel nicht gerade die flotteste Methode für Pixelgrafik ist. Man kann die Pixel-Daten z.B. auch direkt in den Buffer-Speicherbereich eines DIB Bitmap schreiben und das Bitmap dann via Blitter-Funktionen ins Fenster zeichnen (BitBlt-Funktionsfamilie). CreateDIBitmap und BitBlt wären hier Recherche-Einstiegspunkte. Damit wäre man in etwa auf dem Niveau von klassicher CPU-getriebener Grafik (wie z.B. via VESA BIOS-Funktionen). Details müsste ich aber auch erstmal recherchieren - vielleicht kannst du das ja selbst herausfinden und dabei mehr lernen.

    Noch flotter geht es natürlich mit grafiktreiberunterstützter Hardwarebeschleunigung, z.b. via OpenGL, Direct3D, oder sogar Vulkan (letzteres aber nur, wenn du es wirklich genau wissen willst und extrem hart im Nehmen bist. Vulkan ist verdammt lowlevel und nur für Fortsgeschrittene mit genügend Muße zu empfehlen). Das wären Optionen zum weiter forschen. Mit all diesen APIs kann man auch ohne weiteres lediglich 2D-Grafik machen.

    Maus- und Tastatursteuerung läuft üblicherweise mit entsprechenden Nachrichten an deine WndProc. Da gibts dann Nachrichten wie WM_KEYDOWN, WM_KEYUP, WM_KEYPRESS oder WM_MOUSEMOVE die musst du entsprechend verarbeiten und dein Programm auf diese Ereignisse reagieren lassen.

    Für flüssige Animationen würde ich allerdings einen zweiten Thread für die Grafik empfehlen. Der Haupt-Thread, in dem der Event-loop läuft, der letztendlich die WndProc aufruft, blockiert nämlich, wenn keine Fenster-Nachricht in der Warteschlange ist. Man kann zwar auch regelmässige WM_TIMER-Events erzeugen lassen, damit erhält man aber eher ruckelige Animationen. Üblicherweise ballert eine Render-Schleife, in der Grafik erzeugt wird, permanent durch und wartet bestenfalls auf ein VSync - so läuft es zumindest für gewöhnlich in Programmen, welche die o.g. Grafik-APIs nutzen, die dann auch anfangen mehr Sinn zu machen, wenn du Grafik auf so einem Niveau machen willst. Aber das ist vielleicht eher was für später - ich erwähne es hier nur mal, damit du es schonmal weisst.

    Einfacher geht es natürlich noch mit Bibliotheken, die einem für solche Programme einiges an Arbeit abnehmen können (Simple Grafik und Event-Loops). Da sei z.B. SFML genannt, speziell für solche Experimente, wie du sie da scheinbar gerade machst. Eventuell ist das eine Option. "Zu Fuß" lernt man natürlich mehr, aber je nachdem was deine tatsächlichen Ziele sind, könnte das auch eher Ballast sein.

    Viel Erfolg!



  • @Finnegan Danke für die Mühe ! Ich brauch keine Supergeschwindigkeit, aber es müsste schnell genug sein, für eine flüssige Interaktion mit einer großflächig veränderlichen Graphik. SetPixel ist da eh zu langsam, das muß gepuffert werden. Momentan zeigt es sogar erste Anzeichen einer Reaktion auf externe Signale !



  • @ralfsobe sagte in Endlich Pixelkontrolle Visual Studio 22:

    @Finnegan Danke für die Mühe ! Ich brauch keine Supergeschwindigkeit, aber es müsste schnell genug sein, für eine flüssige Interaktion mit einer großflächig veränderlichen Graphik. SetPixel ist da eh zu langsam, das muß gepuffert werden. Momentan zeigt es sogar erste Anzeichen einer Reaktion auf externe Signale !

    Dann recherchier mal was was mit BitBlt und die Pixel direkt in das Bitmap Schreiben so geht. Das ist machbar, ist aber bei mir schon ewig her. Im Zweifel bekommt man denke ich mit auch SFML schnell etwas in die Richtung hin und spart sich jede Menge Win32-API-Gefummel.



  • Im höchsten Maße nützlich wäre natürlich ein fertiges DEMO-Programm, was man einfach mal als Projekt in dieses Visual Studio laden, und modifizieren kann !



  • @ralfsobe sagte in Endlich Pixelkontrolle Visual Studio 22:

    Im höchsten Maße nützlich wäre natürlich ein fertiges DEMO-Programm, was man einfach mal als Projekt in dieses Visual Studio laden, und modifizieren kann !

    Mal sehen, viellecht stoppel' ich morgen mal was kleines zusammen, wenn ich zeit finde. Ohne Garantie 😉



  • @Finnegan sagte in Endlich Pixelkontrolle Visual Studio 22:

    @ralfsobe sagte in Endlich Pixelkontrolle Visual Studio 22:

    @Finnegan Danke für die Mühe ! Ich brauch keine Supergeschwindigkeit, aber es müsste schnell genug sein, für eine flüssige Interaktion mit einer großflächig veränderlichen Graphik. SetPixel ist da eh zu langsam, das muß gepuffert werden. Momentan zeigt es sogar erste Anzeichen einer Reaktion auf externe Signale !

    Dann recherchier mal was was mit BitBlt und die Pixel direkt in das Bitmap Schreiben so geht. Das ist machbar, ist aber bei mir schon ewig her. Im Zweifel bekommt man denke ich mit auch SFML schnell etwas in die Richtung hin und spart sich jede Menge Win32-API-Gefummel.

    ... Womit man sich SFML-Gefummel einhandelt, keine Ahnung, was weniger schlimm ist. Momentan will ich
    SendMessage( ... WM_PRINT ... ) probieren, der muß irgendwie meine Eingabe verdauen, nur leider kommt die Nachricht nicht an.



  • @ralfsobe sagte in Endlich Pixelkontrolle Visual Studio 22:

    ... Womit man sich SFML-Gefummel einhandelt, keine Ahnung, was weniger schlimm ist. Momentan will ich
    SendMessage( ... WM_PAINT ... ) probieren, der muß irgendwie meine Eingabe verdauen, nur leider kommt die Nachricht nicht an.

    Ich arbeite damit zwar nicht regelmässig, aber ich bin verdammt sicher, dass das "SFML-Gefummel" deutlich angenehmer ist - wenn die Bibliothek einmal läuft. Win32-API ist echt übel.



  • @ralfsobe Kleine Quick-and-Dirty GDI-Demo mit Bitmap als Buffer und BitBlt um den Buffer zu zeichnen. Pixel im direkten Speicherzugriff lesbar/modifizierbar. Zeichnen mit gedrückter Maustaste, Buffer löschen mit rechter Maustaste:

    #if !defined(UNICODE)
        #define UNICODE
    #endif
    #include <cstdint>
    #include <cmath>
    #include <algorithm>
    #include <random>
    #define NOMINMAX
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <windowsx.h>
    
    static constexpr int pixel_buffer_width = 500;
    static constexpr int pixel_buffer_height = 500;
    
    std::mt19937 random{ std::random_device{}() };
    
    HDC pixel_buffer_dc;
    HBITMAP pixel_buffer_bitmap;
    std::uint32_t* pixel_buffer;
    
    constexpr
    auto rgba_to_color(float r, float g, float b, float a = 1.0f) -> std::uint32_t
    {
        return
            static_cast<std::uint8_t>(std::clamp(b, 0.0f, 1.0f) * 255.0f)
            | (static_cast<std::uint8_t>(std::clamp(g, 0.0f, 1.0f) * 255.0f) << 8)
            | (static_cast<std::uint8_t>(std::clamp(r, 0.0f, 1.0f) * 255.0f) << 16)
            | (static_cast<std::uint8_t>(std::clamp(a, 0.0f, 1.0f) * 255.0f) << 24);
    }
    
    void clear(std::uint32_t color = rgba_to_color(0.0f, 0.0f, 0.0f))
    {
        std::fill(
            pixel_buffer,
            pixel_buffer + pixel_buffer_width * pixel_buffer_height,
            color
        );
    }
    
    void draw_box(int x0, int y0, int x1, int y1, std::uint32_t color)
    {
        if (x0 > x1)
            std::swap(x0, x1);
        if (y0 > y1)
            std::swap(y0, y1);
    
        x0 = std::clamp(x0, 0, pixel_buffer_width);
        y0 = std::clamp(y0, 0, pixel_buffer_height);
        x1 = std::clamp(x1, 0, pixel_buffer_width);
        y1 = std::clamp(y1, 0, pixel_buffer_height);
    
        auto begin = pixel_buffer + y0 * pixel_buffer_width + x0;
        auto end = begin + x1 - x0;
    
        for (int y = y0; y < y1; y++)
        {
            std::fill(begin, end, color);
            begin += pixel_buffer_width;
            end += pixel_buffer_width;
        }
    }
    
    auto next_color(bool reset = false) -> std::uint32_t
    {
        static std::uniform_real_distribution<float> random_color_component(0.0f, 1.0f);
        static float r0, g0, b0;
        static float r1 = random_color_component(random);
        static float g1 = random_color_component(random);
        static float b1 = random_color_component(random);
        static float t = 1.0f;
        if (reset || t >= 1.0f)
        {
            r0 = r1;
            g0 = g1;
            b0 = b1;
            r1 = random_color_component(random);
            g1 = random_color_component(random);
            b1 = random_color_component(random);
            t = 0.0f;
        }
        auto color = rgba_to_color(
            std::lerp(r0, r1, t),
            std::lerp(g0, g1, t),
            std::lerp(b0, b1, t)
        );
        t += 0.01f;
        return color;
    }
    
    auto CALLBACK WndProc(
        HWND window_handle,
        UINT message,
        WPARAM wparam,
        LPARAM lparam
    ) -> LRESULT
    {
        switch (message)
        {
            case WM_RBUTTONDOWN:
            {
                clear();
                InvalidateRect(window_handle, nullptr, false);
            }
            case WM_LBUTTONUP:
            {
                next_color(true);
                break;
            }
            case WM_MOUSEMOVE:
            {
                int x = GET_X_LPARAM(lparam);
                int y = GET_Y_LPARAM(lparam);
                if (wparam & MK_LBUTTON)
                {
                    draw_box(x - 5, y - 5, x + 5, y + 5, next_color());
                    InvalidateRect(window_handle, nullptr, false);
                }
                break;
            }
            case WM_PAINT:
            {
                PAINTSTRUCT ps;
                auto paint_dc = BeginPaint(window_handle, &ps);
                BitBlt(
                    paint_dc,
                    ps.rcPaint.left,
                    ps.rcPaint.top,
                    ps.rcPaint.right - ps.rcPaint.left,
                    ps.rcPaint.bottom - ps.rcPaint.top,
                    pixel_buffer_dc,
                    ps.rcPaint.left,
                    ps.rcPaint.top,
                    SRCCOPY
                );
                EndPaint(window_handle, &ps);
                break;
            }
            case WM_DESTROY:
            {
                PostQuitMessage(0);
                break;
            }
            default:
                return DefWindowProc(window_handle, message, wparam, lparam);
        }
        return 0;
    }
    
    auto APIENTRY WinMain(
        HINSTANCE instance_handle,
        HINSTANCE previous_instance_handle,
        LPSTR command_line,
        int show_window_mode
    ) -> int
    {
        auto gdi_demo_wndclass = WNDCLASSEXW{
            .cbSize = sizeof(WNDCLASSEX),
            .style = CS_HREDRAW | CS_VREDRAW,
            .lpfnWndProc = WndProc,
            .hInstance = instance_handle,
            .lpszClassName = L"gdi-demo"
        };
        RegisterClassExW(&gdi_demo_wndclass);
    
        DWORD window_style = WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX;
        // This calculates the correct window dimensions for given buffer size.
        RECT window_rect = {
            .left = 0,
            .top = 0,
            .right = pixel_buffer_width,
            .bottom = pixel_buffer_height
        };
        AdjustWindowRect(&window_rect, window_style, false);
    
        HWND window_handle = CreateWindowW(
            L"gdi-demo", 
            L"GDI Demo",
            window_style,
            CW_USEDEFAULT,
            0,
            window_rect.right - window_rect.left,
            window_rect.bottom - window_rect.top,
            nullptr,
            nullptr,
            instance_handle,
            nullptr
        );
    
        auto pixel_buffer_bitmap_info = BITMAPINFO{
            .bmiHeader = {
                .biSize = sizeof(BITMAPINFOHEADER),
                .biWidth = pixel_buffer_width,
                // Negative height, so bitmap is not upside down (Windows default).
                .biHeight = -pixel_buffer_height,
                .biPlanes = 1,
                .biBitCount = 32,
                .biCompression = BI_RGB,
                .biSizeImage = pixel_buffer_width * pixel_buffer_height * 4
            }
        };
    
        pixel_buffer_dc = CreateCompatibleDC(GetDC(window_handle));
        pixel_buffer_bitmap = CreateDIBSection(
            pixel_buffer_dc,
            &pixel_buffer_bitmap_info,
            DIB_RGB_COLORS,
            reinterpret_cast<void**>(&pixel_buffer),
            nullptr,
            0
        );
        SelectObject(pixel_buffer_dc, pixel_buffer_bitmap);
    
        clear();
        ShowWindow(window_handle, show_window_mode);
        UpdateWindow(window_handle);
    
        MSG message;
        while (GetMessage(&message, nullptr, 0, 0))
        {
            TranslateMessage(&message);
            DispatchMessage(&message);
        }
    
        DeleteObject(pixel_buffer_bitmap);
        DeleteDC(pixel_buffer_dc);
        DestroyWindow(window_handle);
        UnregisterClassW(L"gdi-demo", instance_handle);
    
        return 0;
    }
    

    Code ist nur ein Prototyp und sehr simpel gehalten - z.B. keinerlei Fehlerbehandlung und Buffer hat feste Größe (Fenster nicht skalierbar).

    Gestestet mit VS22, GCC11.2/MingW und Clang13.0.1/MingW. Code verwendet C++20-Features (in VS aktivieren bzw. GCC/Clang -std=c++20 - und natürlich -lgdi32 mitgeben).



  • @Finnegan Danke ich versuche es mal, zum Leben zu erwecken !



  • Wenn ich mich recht erinnere sollte DrawDibDraw eine der schnellsten Möglichkeiten (wenn nicht die schnellste) sein rohe Pixel aus einem eigenen RAM Puffer in einem "device independent" Format auf den Schirm zu bekommen. Zumindest wenn man Direct2D/Direct3D mal aussen vor lässt.

    Hab' jetzt keinen Beispielcode zur Hand, aber mit etwas Geduld sollte sich das ergoogeln lassen.

    ps: Mit "schnell" meine ich die Laufzeit, nicht wie lange man braucht den Code zu schreiben 🙂



  • @hustbaer sagte in Endlich Pixelkontrolle Visual Studio 22:

    Wenn ich mich recht erinnere sollte DrawDibDraw eine der schnellsten Möglichkeiten (wenn nicht die schnellste) sein rohe Pixel aus einem eigenen RAM Puffer in einem "device independent" Format auf den Schirm zu bekommen. Zumindest wenn man Direct2D/Direct3D mal aussen vor lässt.

    Interessant. Sieht sehr ähnlich aus wie BitBlt und scheint irgendwie zu Video-Rendering-Funktionen zu gehören. Ich kann mir aber nur schwer vorstellen, dass BitBlt nicht ausreichen sollte. Das dürfte eigentlich letztendlich durchs selbe Silizium laufen. Zwischen Arbeitsspeicher und VRAM hin- und her zu kopieren ist eigentlich eine ziemlich grundlegende Funktion von Grafikchips.

    Edit: Ah, aber man scheint direkt einen selbst-reservierten Speicherbereich damit zeichnen zu können. Ohne den Umweg über ein Bitmap-Objekt, das einem den Speicher reserviert. Da ginge dann auch ein z.B. std::vector::data(). Das macht es natürlich etwas interessanter. Das würde einige Zeilen Code bei meinem Beispiel einsparen.

    ps: Mit "schnell" meine ich die Laufzeit, nicht wie lange man braucht den Code zu schreiben 🙂

    Ja, wenn man nicht genau wissen will, wie die Win32 API funktioniert, halte ich auch immer noch sowas wie SFML für die wahrscheinlich simpelste Lösung vom "Code schreiben" her. Würd mich nicht wundern wenn das da grad mal um die 5 Zeilen wären 😉



  • Ich hab' das vor langer, langer Zeit mal probiert, und ich meine eben mich zu erinnern dass DrawDibDraw schneller war als alles andere was ich probiert habe. Wobei es da wirklich um Videos ging die noch dazu im YUV (bzw. YUY2) Format reinbekommen sind, und auch noch mit Interpolation skaliert werden sollten. Und ich kann mich auch nicht mehr erinnern welche anderen APIs ich noch alle probiert habe.

    Ich hab die Videos Frames allerdings auch immer als volle Frames bekommen, direkt unkomprimiert von einer Capture-Karte (bzw. mehreren Capture-Karten). D.h. rein technisch hätte ich genau so gut mit StretchDIBits o.ä. arbeiten können. War aber eben langsamer bzw. eine der Möglichkeiten die ich probiert habe ist rausgefallen weil sie beim Skalieren ganz komische Artefakte erzeugt hat (seltsame Farbränder).

    Das dürfte eigentlich letztendlich durchs selbe Silizium laufen.

    Möglich. Aber muss nicht sein. Und vor allem: selbst wenn es durch's selbe Silizium läuft ist nicht gesagt dass die selben Algorithmen zum Einsatz kommen.

    Und DrawDibDraw hat noch einen Vorteil: es hat den DrawDib DC in dem es alle Möglichen Dinge cachen kann die es eventuell benötigt um die Frames zu malen. Also sowas wie DirectX Surfaces, Shader etc. Theoretisch könnte man die Implementierung da sogar soweit treiben dass man dynamisch optimierten Code generiert für genau die Konvertierung die nötig ist. Wobei ich nicht davon ausgehe dass das gemacht wird 🙂

    Bei den anderen Funktionen hat man natürlich auch den DC - da könnte man auch Dinge drin cachen. Nur sind die anderen Funktionen nicht darauf ausgelegt einen Video-Stream zu rendern. Und das heisst man kann da nicht bei jedem GDI Call davon ausgehen dass genau dieser der primär wichtige Aufruf ist auf den alles optimiert werden soll. Der DrawDib DC kann allerdings sehrwohl davon ausgehen, da er halt dafür da ist ein Video zu rendern. In der Doku wird sogar explizit erwähnt dass man pro Video-Stream einen eigenen DrawDib DC machen soll. (Und bei komprimierten Streams ist das auch nötig, sofern man sie nicht selbst vorher dekomprimiert.)

    Das alles heisst natürlich nicht dass DrawDibDraw schneller sein muss. Aber es deutet schon darauf hin dass die Idee es könnte schneller sein nicht ganz so irre ist 😉



  • @hustbaer sagte in Endlich Pixelkontrolle Visual Studio 22:

    Das alles heisst natürlich nicht dass DrawDibDraw schneller sein muss. Aber es deutet schon darauf hin dass die Idee es könnte schneller sein nicht ganz so irre ist 😉

    Vielleicht. Ich kannte die Funktion halt noch nicht und bin bisher immer davon ausgegangen dass BitBlt die Funktion schlechthin dafür ist.

    Es stimmt allerdings, dass gerade Video-Rendering im Grafiktreiber teilweise speziell implementiert ist, wenn man die entsprechenden Funktionen verwendet. Da zeichnet dann soweit ich weiss der Treiber den Frame direkt auf den Bildschirm, anstatt dass das ganze erst noch durch den Desktop-Compositor gejagt wird.

    Das würde aber m.E. eher Sinn machen, wenn der Grafikchip auch das Video decodiert. Der lpBits-Parameter (RAM-Pointer auf Pixeldaten) von DrawDibDraw spricht aber eher dagegen, denke ich. Da würde ich mehr vertrauen haben, wenn das z.B. ein Handle eines DXVA-Surface oder sowas wäre.

    VfW ist allerdings auch schon steinalt - wie auch BitBlt, es kann gut sein, das all unsere Spekulationen hier alle nicht mehr wirklich relevant sind 😉 ... das Demo-Programm wirkt jedenfalls flott genug, auch wenn es bei jedem MouseMove-Event den Buffer einmal komplett kopiert. Sieht nach 60fps aus bei grad mal um die 3% CPU-Last. Für CPU-Zeichnen ganz okay (bis auf Buffer kopieren, das macht wohl definitiv die GPU). Vielleicht unterschätze ich aber auch wie schnell Computer über die Jahre mittlerweile geworden sind. CPU-getriebene Grafik hab ich sogar noch mit DOS gemacht 😁



  • ... Womit man sich SFML-Gefummel einhandelt, keine Ahnung, was weniger schlimm ist. Momentan will ich
    SendMessage( ... WM_PRINT ... ) probieren, der muß irgendwie meine Eingabe verdauen, nur leider kommt die Nachricht nicht an.

    ich hab nicht alles gelesen aber dein Versuch SendMessage mit WM_PRINT, was soll das bringen? Oder sollte das WM-PAINT heißen was genau so sinnlos ist, denn zum neuzeichnen kannst du nicht einfach WM_PAINT aufrufen, das macht die GDI du kannst nur deinen Zeichenbereich für ungültig erklären (Repaint) und dann wird WM_PAINT vom System angeschoben.


Anmelden zum Antworten