Нужно ли выбирать HBRUSH при замене фона в редакторе?

Моя цель - заменить фон для элемента управления редактирования общего элемента управления. Мой текущий код делает это:

HBITMAP hBmp = ::LoadBitmap(hInstance, MAKEINTRESOURCE(BKGND_ID));
HBRUSH hBkgndBrush = ::CreatePatternBrush(hBmp);
::DeleteObject(hBmp);


HBRUSH CDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

    // TODO:  Change any attributes of the DC here

    if(pWnd->GetDlgCtrlID() == MY_CTRL_ID && hBkgndBrush)
    {
        hbr = hBkgndBrush;

        //Do I need to select it?
        //pDC->SelectObject(hbr);   //This line?

        pDC->SetBkMode(TRANSPARENT);
    }

    // TODO:  Return a different brush if the default is not desired
    return hbr;
}

Вопрос в том, нужно ли мне выбирать hbr прежде чем вернуть его? (См. Закомментированную строку выше.) Кажется, я вижу, что в разных примерах онлайн это делается в обоих направлениях.

РЕДАКТИРОВАТЬ: Также забыл упомянуть, я переопределить WM_ERASEBKGND как таковой:

HDC hDc = ::GetDC(hWnd);
if(hDc)
{
    RECT rc = {0};
    ::GetClientRect(hWnd, &rc);

    ::FillRect(hDc, &rc, hBkgndBrush);

    ::ReleaseDC(hWnd, hDc);
}

РЕДАКТИРОВАТЬ 2: Я сделал небольшой пример проекта MFC, чтобы проиллюстрировать проблему. По сути, когда я быстро убираю приложение с экрана и затем возвращаюсь, оно создает этот визуальный "сбой", но только если элемент управления не имеет стиля ES_MULTILINE:

1 ответ

Решение

Когда кисть фона создается из растрового изображения с помощью CreatePatternBrushНекоторые "повторяющиеся артефакты" могут возникать при изменении размера или перемещении диалога.

Чтобы удалить эти артефакты, принудительно перекрашивайте дочерние элементы управления в ответ на ON_WM_WINDOWPOSCHANGED сообщение:

void CMyDialog::OnWindowPosChanged(WINDOWPOS *wndpos)
{
    CDialog::OnWindowPosChanged(wndpos);

    CWnd *wnd = GetWindow(GW_CHILD);
    while (wnd)
    {
        wnd->Invalidate(TRUE);
        wnd = wnd->GetWindow(GW_HWNDNEXT);
    }
}

или же

void CMyDialog::OnWindowPosChanged(WINDOWPOS *wndpos)
{
    CDialog::OnWindowPosChanged(wndpos);
    edit1.Invalidate(FALSE);
    edit2.Invalidate(FALSE);
    ...
}

OnCtlColor переопределение будет следующим:

HBRUSH CMyDialog::OnCtlColor(CDC* pDC, CWnd* wnd, UINT nCtlColor)
{
    if (nCtlColor == CTLCOLOR_DLG)
        return CDialogEx::OnCtlColor(pDC, wnd, nCtlColor); 
    pDC->SetBkMode(TRANSPARENT);
    return hBkgndBrush;
}

Вы можете добавить другие условия на основе wnd или же nCtlColor изменить фон только для редактирования элемента управления.

Другие вопросы по тегам