2015-11-27 2 views
0

Я пишу приложение mfc. У меня есть простой CWnd с OnEraseBkgnd и OnPaint. Я испытываю некоторые проблемы, когда другое окно частично покрывает мое окно.Обрезная область для OnEraseBkgnd отличается от области отсечения для OnPaint

Таким образом, когда покрытие закрывается, мой CWnd получает WM_ERASEBKGND. Я очищаю грязную область, и я возвращаю TRUE. Что я вижу здесь, так это то, что CDC У меня есть набор обрезков, и я использую его, так что только покрытая часть стирается. Это хорошо.

Но тогда приходит WM_PAINT. CDC Я получаю с GetDCне имеют любую отсечную коробку, поэтому вся область окна перекрашивается. Это проблема, потому что в моем событии рисования я использую CDC::DrawText с прозрачным фоном (CDC::SetBkMode(TRANSPARENT)) и покраска того же текста в том же не стертом месте, что и текст становится «полужирным». Просто рисовать текст снова и снова в одном и том же месте без вытирания фона делает его выглядеть уродливым.

Это нормальное поведение? Мой подход одобрен?

EDIT:

Здесь я придаю больше о выпуске Информацию по.

SSCCE:

class Foo : public CFrameWnd 
{ 
public: 
    BOOL OnEraseBkgnd(CDC* pDC) 
    { 
     CRect rect; 
     pDC->GetClipBox(rect); 

     HBRUSH brush = ::GetSysColorBrush(COLOR_WINDOW); 
     HGDIOBJ pOld = pDC->SelectObject(brush); 

     const BOOL result = pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); 

     pDC->SelectObject(pOld); 

     return result; 
    } 

    void OnPaint() 
    { 
     CWnd::OnPaint(); 

     CDC *dc = GetDC(); 

     CRect clipBox; 
     dc->GetClipBox(clipBox); 

     CRect rect; 
     GetClientRect(rect); 

     CFont *font = &globalFont;     // in my app here is the font I use but it doesn't matter 
     HFONT hFont = static_cast<HFONT>(font->GetSafeHandle()); 

     auto oldFont = dc->SelectObject(hFont); 
     const int bkMode = dc->SetBkMode(TRANSPARENT);    
     dc->DrawText("AAAAAAAAA", -1, rect, 0); 
     dc->SetBkMode(bkMode); 
     dc->SelectObject(oldFont); 
    } 

    DECLARE_MESSAGE_MAP() 
}; 

Создание:

Foo* f = new Foo; 
f->Create(0, "test", WS_VISIBLE| WS_OVERLAPPEDWINDOW); 

Ниже, как делает окно выглядеть нормально:

normal

И ниже после перемещения окна так, половину текста был вне монитора, а затем вернулся:

not quite normal

Так часть окна, которая была невидима была стерта, а затем текст был помещен снова. Для видимой части окна текст не стирался, а в OnPaint был снова перерисован, вызывая «жирный».

+1

Это может помочь, если вы дадите больше информации. Каковы флаги создания этого окна и другого окна (всплывающее, дочернее и т. Д.)? Каковы родители этого окна, а другое окно и каково отношение? ---- Что касается изменения текста, выделенного полужирным шрифтом, возможно, это связано с форматированием четкого типа, оно не становится жирным, но текст становится немного тяжелее, потому что вы пишете его, не стирая прежний текст. –

+0

@BarmakShemirani Я добавил код и скриншоты –

ответ

0

Это несвязанная проблема, но GetDC вызывает утечку ресурса GDI в код выше. ReleaseDC должна вызываться перед выходом из функции:

void OnPaint() 
{ 
    CWnd::OnPaint(); 
    CDC *dc = GetDC(); 
    dc.DrawText(...); 
    ... 
    ReleaseDC(dc); 
} 

еще лучше, MFC имеет автоматическую очистку с CClientDC

void myWnd::foo() 
{ 
    CClientDC dc(this); 
    dc.DrawText(...); 
} 

OnPaint можно использовать специальный CPaintDC класс, который соответствует PAINTSTRUCT:

void myWnd::OnPaint() 
{ 
    CPaintDC dc(this); //don't call CWnd::OnPaint 
    dc.DrawText(...); 
} 

Обратно к проблеме:

Похоже, что часть фона не перекрашена, но часть текста перекрашена.Это заставляет его выглядеть уродливым специально с четкими шрифтами шрифта (он выглядит жирным, но это не так).

Вы можете решить эту проблему с этим:

dc.SetBkMode(OPAQUE); 
dc.SetBkColor(GetSysColor(COLOR_WINDOW)); 
dc.DrawText(L"AAAAAAAAA", -1, rect, 0); 

Другой вариант: переопределить OnEraseBkgnd и заставить его не делать ничего:

BOOL OnEraseBkgnd(CDC*) 
{ 
    return TRUE; 
} 

ли все картины в OnPaint()

void myWnd::OnPaint() 
{ 
    CPaintDC dc(this); 

    CRect rect; 
    GetClientRect(rect); 
    dc.FillSolidRect(rect, ::GetSysColor(COLOR_WINDOW)); 

    CFont *font = &globalFont; 
    auto oldFont = dc.SelectObject(font->GetSafeHandle()); 
    dc.SetBkMode(TRANSPARENT); 
    dc.DrawText(L"AAAAAAAAA", -1, rect, 0); 

    dc.SelectObject(oldFont); 
} 
+0

Thx для ответа, однако я до сих пор не понимаю, почему он не работает должным образом. У меня могут быть обходные пути, но я не думаю, что это не так. –

1

Вы должны использовать CPaintDC, а не только потому, что он контролирует ресурсы, как указал Бармак, но также потому, что он извлекает данные об отсечении. GetDC не делает. (Бармак также упомянул PAINTSTRUCT, но может быть неясно, что является ключом к проблеме отсечения.)

Смежные вопросы