Static에 글씨가 겹쳐서 보일 때 조치법
CStatic 을 상속받은 재정의 클래스를 선언하고, OnPaint 함수에서 배경을 투명화하고 DrawText 하도록 해주었다.
그랬더니 Invalidate 함수를 호출할때마다 글자가 한겹씩 점점 더 진해지는게 아닌가!
이런 경우는 아래 URL 을 참고하여 해결하는 방법이 있다.
필자는 우선 이런 방식으로 해결은 하였다만, 또 다른 방법도 있어 소개하려고 한다.
1. 글씨를 출력하는 SetWindowsText 호출 전에 Invalidate(FALSE)를 호출하는 방법
2. CStatic을 상속받은 재정의 클래스를 선언한 경우
- BOOL 형식의 m_bDrawText 를 선언, 이 멤버변수를 이용해 text 가 변경되지 않는 이상 DrawText를 재호출하지 않는다.
class ColorStatic : public CStatic
{
...
public :
BOOL m_bDrawText;
CString m_strText;
...
}
OnPaint 에서 DrawText 를 호출하면 멤버 변수인 m_bDrawText 를 TRUE 로 셋팅
void ColorStatic::OnPaint()
{
CPaintDC dc(this);
...
SetBkMode(TRANSPARENT);
...
if(FALSE == m_bDrawText)
{
if( 0!=DrawText(m_strText, m_strText.size(), ...))
m_bDrawText = TRUE;
}
}
...
void ColorStatic::SetText(CString strText)
{
m_strText = strText;
if(NULL != m_pWnd->hwnd) // 변수명 정확하지 않음
{
Invalidate(FALSE);
}
}
Invalidate 함수
윈도우 화면을 갱신할때는 두가지의 메시지를 이용할수 있습니다.
WM_PAINT와 WM_ERASEBKGND 메시지입니다.
이 메시지를 발생하기 위해 사용하는게 바로 Invalidate 함수입니다. 인자만 다르게 설정하면 되는데요.
WM_PAINT 메시지만 발생하고 싶으시다면 Invalidate(FALSE); WM_PAINT와 WM_ERASEBKGND 메시지 둘다 발생하고 싶다면 Invalidate(); 또는 Invalidate(TRUE); 라고 호출하면 됩니다.
Invalidate(FALSE) : WM_PAINT
Invalidate(TRUE) : WM_PAINT -> WM_ERASEBKGND
즉, FALSE 인자는 백그라운드(현재 그려저 있는 거 포함)를 지우지 않고 그냥 그리고 TRUE는 백그라운드를 다 지우고 그린다는 의미인데, 여기서 백그라운드는 단순히 배경 색만 의미하는게 아니라 이미 영역 내에 그려진 것을 포함합니다.
Invalidate(TRUE); 로 화면을 갱신할때는 WM_PAINT 메시지가 일단 발생하고 WM_PAINT 메시지 핸들러에서 아래와 같이 DC 변수를 할당할때, WM_ERASEBKGND 메시지가 발생합니다.
CPaintDC dc(this);
호출 순서를 살펴보면 다음과 같습니다.
void CMyWnd::OnPaint()
{
m_event_list.InsertString(-1, "Paint1");
CPaintDC dc(this); // device context for painting
m_event_list.InsertString(-1, "Paint2");
}
BOOL CMyWnd::OnEraseBkgnd(CDC* pDC)
{
m_event_list.InsertString(-1, "Bk");
return CWnd::OnEraseBkgnd(pDC);
}
위와 같이 코드를 구성하고 Invalidate(TRUE); 라고 호출하면 출력되는 순서가 아래와 같습니다.
Paint1 -> Bk -> Paint2
따라서 호출순서를 잘 생각하시고 프로그램하시는것이 좋습니다.
예외적으로, 윈도우가 처음 생성될때는 위 호출이 아래와 같습니다.
Bk -> Paint1 -> Paint2
즉, OnInitDialog 호출 시에는 OnEraseBkgnd() -> OnPaint 호출되고 OnPaint 중간에 CPaintDC dc(this); 호출부가 있어도 다시 OnEraseBkgnd( ) 가 호출되지 않는다는 말입니다.
[Reference]
1. https://taessing.tistory.com/86 [Taessing]
2. http://www.tipssoft.com/bulletin/board.php?bo_table=FAQ&wr_id=48
'Windows > Windows API (설명&함수 사용 실수..)' 카테고리의 다른 글
[리스트 컨트롤] CListCtrl 예제 (0) | 2020.08.08 |
---|