es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Dibuja una matriz de píxeles sin procesar en una ventana (C++ WinAPI)

Tengo dos búferes, ambos del mismo tamaño y tipo (uint32_t*). Estos búferes se supone que representan los búferes frontal y posterior de un sistema de renderización/dibujo. Almacenan datos de píxeles de 32 bits.

Declaro e inicializo estos búferes utilizando:

private:
    ...
    uint32_t* frontBuf;
    uint32_t* backBuf;
    size_t    gbufSize;
    ...
public:
    void Initialize() {
        ...
        // preparar para la renderización
        gbufSize = sizeof(uint32_t) * w * h;
        backBuf  = (uint32_t*)malloc(gbufSize);
        frontBuf = (uint32_t*)malloc(gbufSize);
        ...
    }

También obtengo la salida, las ventanas y los identificadores de dispositivo para la consola en el método Initialize() utilizando:

        // obtener identificadores
        cwd = GetDC(GetConsoleWindow());
        chd = GetStdHandle(STD_OUTPUT_HANDLE);
        cwn = GetConsoleWindow();

Luego tengo algunos métodos de dibujo, como un método SetPixel:

    size_t GFlatten(int x, int y) {
        return y * h + x;
    }

    void GSetPixel(int x, int y, uint32_t color) {
        backBuf[GFlatten(x, y)] = color;
    }

Y finalmente, tengo un método GSwap. Este método se supone que intercambia los punteros de los búferes, borra el nuevo búfer posterior y copia el búfer frontal en la pantalla.

Los dos primeros funcionan bien (creo), pero no tengo idea de cómo implementar el tercero (la copia en la pantalla). Preferiría no usar bibliotecas externas.

Código para el método GSwap:

    void GSwap() {
        // intercambiar punteros
        uint32_t* frontTmp = frontBuf;
        frontBuf = backBuf;
        backBuf = frontTmp;

        // borrar nuevo búfer posterior
        memset(backBuf, 0, gbufSize);

        // dibujar en la pantalla
        /* ??? */
    }

El código completo se encuentra en: Pastebin

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para copiar el búfer frontal en la pantalla, puedes utilizar la función BitBlt proporcionada por WinAPI.

    Aquí tienes cómo puedes modificar tu método GSwap para copiar el búfer frontal en la pantalla:

    void GSwap() {
        // intercambiar punteros
        uint32_t* frontTmp = frontBuf;
        frontBuf = backBuf;
        backBuf = frontTmp;
    
        // borrar el nuevo búfer trasero
        memset(backBuf, 0, gbufSize);
    
        // dibujar en la pantalla
        // obtener dimensiones de la ventana
        RECT rc;
        GetClientRect(cwn, &rc);
        int winW = rc.right - rc.left;
        int winH = rc.bottom - rc.top;
    
        // crear contexto de dispositivo compatible y mapa de bits
        HDC hdc = CreateCompatibleDC(cwd);
        HBITMAP hbm = CreateBitmap(winW, winH, 1, 32, frontBuf);
        SelectObject(hdc, hbm);
    
        // copiar mapa de bits a la pantalla
        BitBlt(cwd, 0, 0, winW, winH, hdc, 0, 0, SRCCOPY);
    
        // liberar recursos
        DeleteObject(hbm);
        DeleteDC(hdc);
    }
    

    Explicación:

    1. Obtener las dimensiones de la ventana llamando a GetClientRect con el identificador de la ventana de consola.

    2. Crear un contexto de dispositivo compatible y un mapa de bits con CreateCompatibleDC y CreateBitmap.

    3. Seleccionar el mapa de bits en el contexto de dispositivo con SelectObject.

    4. Copiar el mapa de bits en la pantalla con BitBlt. Los parámetros especifican el contexto de dispositivo y el identificador de la ventana donde se copiará el mapa de bits, las dimensiones del mapa de bits y el punto de inicio, y el modo de copia (que se establece en SRCCOPY).

    5. Finalmente, eliminar el mapa de bits y el contexto de dispositivo con DeleteObject y DeleteDC.

Comments are closed.