問題 提出:
最近在項目中將CStatic控件設置爲背景透明且在一個定時器函數改變其文本,結果CStatic的文字重疊了。解決該問題的方案是:從CStatic類派生自己的靜態文本控件。
其實設置背景透明,也就是在CStatic重畫時,返回一個空刷子而已,所以改變文本並沒有改變上次殘留的背景,從而導致重疊現象。
爲了解決這個問題,我們可以讓父窗口重繪該區域,以下是我的解決方法:
1: 從CStatic繼承一個類CStaticEx
2: 增加WM_CTLCOLOR消息反射(把很多事情留給父窗口窗口處理不是一件很好的事,就讓CStaticEx自己處理,這樣還可以不影響到其他的Static)
3:處理WM_SETTEXT,當文本改變時,重繪父窗口的該控件所在的區域。
代碼如下:
// StaticEx.h
class CStaticEx : public CStatic
{
DECLARE_DYNAMIC(CStaticEx)
public:
CStaticEx();
virtual ~CStaticEx();
protected:
DECLARE_MESSAGE_MAP()
afx_msg HBRUSH CtlColor(CDC* pDC, UINT );
virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};
//
#include "StaticEx.h"
// StaticEx.cpp
IMPLEMENT_DYNAMIC(CStaticEx, CStatic)
CStaticEx::CStaticEx()
{
}
CStaticEx::~CStaticEx()
{
}
BEGIN_MESSAGE_MAP(CStaticEx, CStatic)
ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()
// CStaticEx 消息處理程序
HBRUSH CStaticEx::CtlColor(CDC* pDC, UINT )
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255, 0, 0));
return (HBRUSH)GetStockObject(HOLLOW_BRUSH);
}
LRESULT CStaticEx::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if(WM_SETTEXT == message)
{
CRect rect;
GetWindowRect(&rect);
CWnd *pParentWnd = GetParent();
if(pParentWnd)
{
pParentWnd->ScreenToClient(&rect);
pParentWnd->InvalidateRect(&rect);
}
}
return CStatic::DefWindowProc(message, wParam, lParam);
}
注意:上述方法在在Winxp、win7、Wince下測試通過,但在Wince平臺下不起作用, 在Wince平臺下,在文字動態改變時除了上面自定義CStatic代碼外,還必須在文字動態改變處加入如下代碼:
m_static.ShowWindow(SW_HIDE); // 先隱藏下
m_static.SetWindowText(strNum);
m_static.ShowWindow(SW_SHOW); // 再顯示出來。通過隱藏顯示從而刷新父窗口
上面只通過隱藏顯示的方法而不需要自定義CStatic在Winxp、win7也可以,請看下文:
下面再介紹一種方法,在Winxp、win7下測試通過:
設置了透明後,應該是不刷新父窗口的該區域,所以直接就畫出來而沒有清除之前的.解決方法很簡單
將控件先影藏再顯示,之前使用控件的Invalidate函數,不行,因爲那只是重畫了控件的區域,而不是重畫控件父窗體的該區域
而直接重畫父窗體對效率肯定有影響,所以最簡單的方法就是控件ShowWindow(SW_HIDE);然後ShowWindow(SW_SHOW);,這樣父窗體就會重畫該區域,就會清除之前的圖像了,然後想到了這樣
m_static.ShowWindow(SW_HIDE);
m_static.SetWindowText(strNum);
m_static.ShowWindow(SW_SHOW);
先影藏,然後改變內容,再顯示,好了,完美解決了
轉自:http://blog.163.com/danshiming@126/blog/static/109412748201331662656796/