Rich Edit Control окрашивает все приложение в черный цвет после минимизации - PullRequest
1 голос
/ 30 октября 2019

РЕШЕНО: Я отправил свое решение в качестве ответа.

Вот моя проблема: (gif) (В некоторой степени решается, если я перезагружаю растровые изображения для рисования фонового изображения при минимизацииперед любым сообщением WM_PAINT.)

background disappearing

Это происходит всякий раз, когда я минимизирую приложение, время, когда приложение впервые отображает OK (в течение короткой доли секунды, если вы непереходят в режим отладчика) и внезапно становятся черными (или любой другой цвет, установленный как hbrBackground в классах окна приложения). Я могу предотвратить это поведение, перезагрузив HBITMAP, используемые в WM_PAINT, которые являются глобальными переменными и инициализируются с их соответствующими значениями при запуске приложения.

GIF начинает показывать приложение, вновь открытое после свертывания, с отладчиком, проходящим черезродительское окно цикла сообщений Rich Edit Control, моменты перед и после фона всех окон становятся черными, а затем переходят в цикл сообщений подкласса Rich Edit Control в WM_PAINT.

  • Это никогдапроизойдет, если я переключаюсь между приложениями без того приложения, о котором идет речь, которое никогда не было свернуто ранее.
  • Это никогда не происходит, если элемент управления Rich Edit (RICHEDIT50W) не отображал никакого текста раньше, т.е. приложение работает нормально, если текст никогда не отображается.
  • Это дерево окон:
    • Главное окно
      • Некоторые дочерние окна
      • Дочернее окно 1
        • Элемент управления Rich Edit

Шагает из дочернего окна 1 WndProc;в WM_PAINT элемента управления Rich Edit внутри WndSubclassProcWh независимо от обратного вызова.

Некоторые вещи, которые я сделал до того, как осознали, что вызов LoadImage () сразу после минимизации может решить проблему с фоном:

  • Перехватывать цикл сообщений элемента управления Rich Edit с подклассом и обрабатывать (как и в любом другом окне) сообщения как: WM_COMMAND, WM_IME_NOTIFY, WM_NCPAINT, WM_WINDOWPOSCHANGED, WM_WINDOWPOSCHANGING, WM_ERASEBKGND ... в основном, возвращая что-то отличное от возврата в основном ... DefSubclassProc / DefWindowProcW.
  • Вызов ValidateRect (), как только приложение открывается снова ...

    До этого вместо того, чтобы все приложение становилось черным, только текст«выделение» или родительский элемент Rich Edit Control стал черным, а все приложение стало черным после следующего цикла минимизации свертывания.

Я использую сообщество Visual Studio 2019 с настройками по умолчанию в обновленномWindows 10 и видя эту проблему как в гВыпускать и отлаживать сборки.

Теперь я с нетерпением жду, чтобы предотвратить «выгрузку» растровых изображений, тем самым сохраняя многие, казалось бы, ненужные вызовы LoadImage (). решено

Я пытался загрузить минимальную версию кода, но поведение оказалось не таким, как надо, поэтому спасибо за ответ, который был дан ранее!

Ответы [ 2 ]

3 голосов
/ 30 октября 2019

Это не имеет ничего общего с Rich Edit Control, даже если вы удалите все элементы управления, это произойдет.

Все, что вам нужно сделать, это добавить цвет по умолчанию для фона окна при регистрацииwindow.

Здесь:

ATOM MyRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEXW wcex;

        wcex.cbSize = sizeof(WNDCLASSEX);

        wcex.style = CS_DBLCLKS;
        wcex.lpfnWndProc = WndProc;
        wcex.cbClsExtra = 0;
        wcex.cbWndExtra = 0;
        wcex.hInstance = hInstance;
        wcex.hIcon = NULL; // Procesás WM_GETICON
        wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
        wcex.hbrBackground = NULL;
        wcex.lpszMenuName = NULL;
        wcex.lpszClassName = L"mainWindowClass";
        wcex.hIconSm = NULL; // Procesás WM_GETICON

        return RegisterClassExW(&wcex);
    }

Повторный щелчок после сворачивания окна приведет к его перерисовке с использованием цвета фона по умолчанию, но здесь для цвета фона установлено значение NULL. Поэтому попробуйте изменить wcex.hbrBackground = NULL на wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1)

Обновлено:

Похоже, у вас возникла та же проблема, с которой я столкнулся ранее.

Вот мой предыдущий код:

 case WM_PAINT:
        {
            PAINTSTRUCT ps;
           HDC hdc =  BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code that uses hdc here... 
           hdcMem = CreateCompatibleDC(hdc);
           HGDIOBJ previousbit = SelectObject(hdcMem, hBmp);
           AlphaBlend(hdc, 0, 0, width_1, height_1, hdcMem, 0, 0, width_1, height_1, bf);
           DeleteDC(hdcMem);
           EndPaint(hWnd, &ps);
        }
        break;
case WM_MOUSEWHEEL:
    {
        if (GET_WHEEL_DELTA_WPARAM(wParam) > 0 && bTrans <= 234)
        {
            bTrans += 20;
            bf.SourceConstantAlpha = bTrans;
            InvalidateRect(hWnd, NULL, TRUE);
        }
        if (GET_WHEEL_DELTA_WPARAM(wParam) < 0 && bTrans >= 20)
        {
            bTrans -= 20;
            bf.SourceConstantAlpha = bTrans;
            InvalidateRect(hWnd, NULL, TRUE);
        }
        return 0;
    }

Я сдвигаю колесо мыши, оно вызовет InvalidateRect(hWnd, NULL, TRUE);

Но если я удалю DeleteDC(hdcMem), оно вернет главное окно безкартинка.

Снимок отладки:

enter image description here

Да, вы можете найти previousbit == NULL.

Как сказал @ Реми Лебо, вы пропускаете HBITMAP, который возвращается SelectObject(), и даете HDC разрешение потенциально уничтожить ваш bitmapBackgroundMainWindow за вашей спиной.

Это основная причина.

1 голос
/ 30 октября 2019

Вызов функции DeleteObject () устранил проблему.

Это код из одного сообщения WM_PAINT окна растрового фона, исправленного соответствующим вызовом DeleteObject ():

    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hWnd, &ps);
    HDC temporaryDC = CreateCompatibleDC(hdc);
    BITMAP bitmapToBitBlt;
    HGDIOBJ hgdiobjToBitBlt = SelectObject(temporaryDC, bitmapBackgroundMainWindow);
    GetObjectW(bitmapBackgroundMainWindow, sizeof(BITMAP), &bitmapToBitBlt);
    BitBlt(hdc, 0, 0, bitmapToBitBlt.bmWidth, bitmapToBitBlt.bmHeight, temporaryDC, 0, 0, SRCCOPY);
    DeleteObject(temporaryDC); // This fixes the app.
    EndPaint(hWnd, &ps);
    return 0;

При состоянии Windows Docs после вызова CreateCompatibleDC ():

Если вам больше не нужен DC памяти, вызовите функцию DeleteDC. Мы рекомендуем вам вызвать DeleteDC для удаления DC. Однако вы также можете вызвать DeleteObject с HDC, чтобы удалить DC.

Как это может привести к неожиданному поведению моего приложения, я не знаю, не стесняйтесь разъяснять в комментариях!

...