问题 提出:
最近在项目中将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/