¿Por qué mi código produce un color de área de cliente de ventana completamente negro sin ninguna visualización al usar doble almacenamiento en búfer para evitar el parpadeo?

programación


Estoy usando el método de doble almacenamiento en búfer en la ventana principal de mi programa para evitar el parpadeo, pero en su lugar obtengo un área de cliente de ventana completamente negra. Cual podría ser el problema.

Los códigos relevantes se muestran a continuación:
Tenga en cuenta que la función WriteDatah no es una parte real de la aplicación real. Creé un nuevo proyecto y le llevé el código problemático para descubrir que estaba mal. WriteData representa el código real en funcionalidad. Con esta nueva aplicación de prueba, pude reducir el problema y determinar que el doble almacenamiento en búfer no se realiza correctamente o que el modo de mapeo entra en conflicto. Qué opinas.

C++
case WM_CREATE:
    {
        HDC hdc = GetDC(hWnd);

        std::tuple<double, double, int, int> Tuple = GetAppDocumentSize(hWnd, hdc, iPageWidth, iPageHeight);
        iOneMMX = static_cast<int>(Approximate(get<0>(Tuple), 0));
        iOneMMY = static_cast<int>(Approximate(get<1>(Tuple), 0));
        int iWidth = GetSystemMetrics(SM_CXSCREEN);
        int iHeight = GetSystemMetrics(SM_CYSCREEN);
        hMemDC = CreateCompatibleDC(hdc);
        hBitmap = CreateCompatibleBitmap(hdc, iWidth, iHeight);
        hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
        HBRUSH hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
        hOldBrush = (HBRUSH)SelectObject(hMemDC, hBrush);

        ReleaseDC(hWnd,hdc);


        break;
    }
C++
case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            std::tuple<double,double,int,int> Tuple = GetAppDocumentSize(hWnd, hdc, iPageWidth, iPageHeight);
          
            BitBlt(hdc, 0, 0, iPageWidth, iPageHeight, hMemDC, 0, 0, SRCCOPY);

            EndPaint(hWnd, &ps);
        }
        break;

El siguiente código lo incluye el elemento del menú con el ID ID_DRAW_DRAW_TEXT. Entonces, lo maneja WM_COMMAND.

C++
case ID_DRAW_DRAWTEXT:
            {
                Rectangle(hMemDC, 0, 0, iPageWidth, iPageHeight);
                WriteDatah(hMemDC,iOneMMX,iOneMMY,iPageWidth,iPageHeight);

                InvalidateRect(hWnd, NULL, FALSE);

                break;
            }

C++
HFONT CreateAppFont(int cHeight, int cWeight, DWORD bItalic, int cEscapement, DWORD bUnderline, LPCWSTR pszFaceName)
{
    return CreateFont(cHeight, 0, cEscapement, cEscapement, cWeight, bItalic, bUnderline, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS,
        CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH, pszFaceName);


}
C++
double Approximate(double dNumber, int iDecimalPlaces)
{
    int iMultipier = static_cast<int>(pow(10, iDecimalPlaces));
    dNumber *= iMultipier;

    double dInteger = 0.0;
    double dDecimal = modf(dNumber, &dInteger);

    int Integer = static_cast<int>(dInteger);

    if (dDecimal >= 0.5)
    {
        Integer++;
    }

    double dResult = Integer / iMultipier;

    return dResult;
}
C++
void WriteDatah(HDC hdc,int iOneMMX,int iOneMMY,int iPageWidth,int iPageHeight)
{
    UNREFERENCED_PARAMETER(iPageHeight);

    std::wstring wstData = L"Jesus is Lord of the Nations";
    
    int iOneINCHY = GetDeviceCaps(hdc, LOGPIXELSY);
    double dOneFontPOINT = (double)iOneINCHY / 72.0;
    int iOneFontPOINT = static_cast<int>(Approximate(dOneFontPOINT, 0));

    int iFontSize = 10 * iOneFontPOINT;

    HFONT hFont = CreateAppFont(iFontSize, FW_BOLD);
    HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);

    int iLeft = 10 * iOneMMX;
    int iTop = 10 * iOneMMY;

    SIZE size;
    GetTextExtentPoint32(hdc, wstData.c_str(), lstrlen(wstData.c_str()), &size);
    TEXTMETRIC tm;
    GetTextMetrics(hdc, &tm);

    for (int i = 0; i < 100; i++)
    {
        TextOut(hdc, iLeft, iTop, wstData.c_str(), lstrlen(wstData.c_str()));

        iTop += tm.tmHeight + tm.tmExternalLeading;

    }
      
       


    SelectObject(hdc, hOldFont);
    
}

Lo que he probado:

He estado depurando todo el día. También tengo bastante búsqueda en Google.

Solución 1

Desde el primer vistazo: no especificas los colores de lápiz y pincel para el dibujo.

Solución 2

He usado esta clase: Dibujo sin parpadeo en MFC[^] desde hace muchos años y funciona muy bien. También escribí una versión que no es MFC y que he usado varias veces. Su código no parece utilizar MFC pero los principios son los mismos. Se trata de manejar mensajes, principalmente WM_PAINT. Sin embargo, WM_ERASEBACKGND También debe manejarse simplemente devolviendo verdadero. Te recomiendo que leas atentamente el artículo para ver si estás haciendo algo mal.

Déjame saber si quieres ver la versión que no es MFC y la publicaré aquí. Es esencialmente lo mismo que la versión MFC excepto que usa llamadas GDI en lugar de métodos CDC.

コメント

タイトルとURLをコピーしました