透明static控件花屏

dahaiI0 2010-12-27 10:46:53
对话框A有个button,点击后domodal产生对话框B,B上有几个自绘的透明static控件,开始能正常显示,退出B对话框,再点 Button产生B对话框,如此循环几次后static控件开始花屏,自绘static的代码如下

#include "stdafx.h"
#include "StaticEx.h"

#define _X(x) (x.left)
#define _Y(x) (x.top)
#define _W(x) (x.right - x.left)
#define _H(x) (x.bottom - x.top)
// CStaticEx

IMPLEMENT_DYNAMIC(CStaticEx, CStatic)

CStaticEx::CStaticEx()
{
m_clrText = 0;//RGB( 255, 0, 0 );
m_clrBkgnd = 0;//RGB( 255, 255, 0 );
m_hbrBkgnd = NULL;

m_bTransparent = FALSE;
m_unIDBmpBkGnd = 0;
}

CStaticEx::~CStaticEx()
{
}

BEGIN_MESSAGE_MAP(CStaticEx, CStatic)
//{{AFX_MSG_MAP(CTransparentStatic)
ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()

// CStaticEx message handlers

BOOL CStaticEx::SetTransparent(UINT unIDBmpBkGnd, HWND hWnd/* = NULL*/)
{
m_hbrBkgnd = GetBkBrush(unIDBmpBkGnd, hWnd);
if (m_hbrBkgnd != NULL)
{
m_bTransparent = TRUE;
Invalidate();
return TRUE;
}
m_bTransparent = FALSE;
return FALSE;
}


HBRUSH CStaticEx::CtlColor(CDC* pDC, UINT nCtlColor)
{
HBRUSH hBr = NULL;

// 文本颜色
if (0 == m_clrText) // 没有自定义文本颜色
{
pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
}
else
{
pDC->SetTextColor(m_clrText);
}

// 背景颜色 绘制背景的刷子
if (m_bTransparent) // 透明模式
{
pDC->SetBkMode(TRANSPARENT);
hBr = m_hbrBkgnd;
}
else
{
if (0 == m_clrBkgnd) // 没有自定义文本颜色
{
pDC->SetBkColor((RGB(255, 255, 255)));
hBr = (HBRUSH)GetStockObject(WHITE_BRUSH);
}
else
{
pDC->SetBkColor(m_clrBkgnd);
hBr = ::CreateSolidBrush(m_clrBkgnd);;
}
}

return hBr;
}

void CStaticEx::SetClrText(COLORREF clrText)
{
m_clrText = clrText;
Invalidate();
}

void CStaticEx::SetClrBkgnd(COLORREF clrBkgnd)
{
m_clrBkgnd = clrBkgnd;
Invalidate();
}

void CStaticEx::MoveWindowEx(LPCRECT lpRect, BOOL bRepaint/* = TRUE*/)
{
if (m_bTransparent)
{
MoveWindow(lpRect, FALSE);
m_hbrBkgnd = GetBkBrush(m_unIDBmpBkGnd);
Invalidate();
}
else
{
MoveWindow(lpRect, bRepaint);
}
}
HBRUSH CStaticEx::GetBkBrush(UINT unIDBmpBkGnd, HWND hWnd/* = NULL*/)
{
ASSERT(0 != unIDBmpBkGnd);
m_unIDBmpBkGnd = unIDBmpBkGnd;

if (NULL == hWnd)
{
hWnd = GetParent()->m_hWnd;
}
ASSERT(NULL != hWnd);

HWND hWndCtrl = this->m_hWnd;
ASSERT(NULL != hWndCtrl);

HBITMAP hBmpBk = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(unIDBmpBkGnd));
ASSERT(NULL != hBmpBk);

HBRUSH hbrCtrlBk = NULL;

CRect rcScr;
::GetClientRect(hWnd, &rcScr);

CRect rcCtrl;
::GetWindowRect(hWndCtrl, &rcCtrl);
::ScreenToClient(hWnd, (LPPOINT)&rcCtrl);
::ScreenToClient(hWnd, ((LPPOINT)&rcCtrl) + 1);

CBitmap bitmap;
bitmap.Attach(hBmpBk);

BITMAP bi = {0};
GetObject(bitmap, sizeof(BITMAP), &bi);

HDC hDC = ::GetDC(hWnd);

HDC hMemDCBk = CreateCompatibleDC(hDC);
HDC hMemDCScr = CreateCompatibleDC(hDC);
HDC hMemDCCtrl = CreateCompatibleDC(hDC);

HBITMAP hBmScr = CreateCompatibleBitmap(hDC, rcScr.Width(), rcScr.Height());
HBITMAP hBmCtrl = CreateCompatibleBitmap(hDC, rcCtrl.Width(), rcCtrl.Height());

HBITMAP hBmOldBk = (HBITMAP)::SelectObject(hMemDCBk, hBmpBk);
HBITMAP hBmOldScr = (HBITMAP)::SelectObject(hMemDCScr, hBmScr);
HBITMAP hBmOldCtrl = (HBITMAP)::SelectObject(hMemDCCtrl, hBmCtrl);

::StretchBlt(hMemDCScr, 0, 0, rcScr.Width(), rcScr.Height(), hMemDCBk, 0, 0, bi.bmWidth, bi.bmHeight, SRCCOPY);

::BitBlt(hMemDCCtrl, 0, 0, rcCtrl.Width(), rcCtrl.Height(), hMemDCScr, rcCtrl.left, rcCtrl.top, SRCCOPY);

::SelectObject(hMemDCCtrl, hBmOldCtrl);
::SelectObject(hMemDCBk, hBmOldBk);
::SelectObject(hMemDCScr, hBmScr);

hbrCtrlBk = ::CreatePatternBrush(hBmCtrl);

DeleteObject(hBmCtrl);
DeleteObject(hBmScr);

::DeleteDC(hMemDCBk);
::DeleteDC(hMemDCScr);
::DeleteDC(hMemDCCtrl);
::ReleaseDC(hWnd, hDC);
return hbrCtrlBk;
}


B对话框OnInitDialog()调用,m_user为cstaticex对象
m_user.SubclassDlgItem(IDC_STATIC_USER1, this);
m_user.SetTransparent(7172);
m_user.SetClrText(RGB(255,255,255));
...全文
151 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
足球中国 2010-12-27
  • 打赏
  • 举报
回复
可能是背景擦除的不对吧。
Torch009 2010-12-27
  • 打赏
  • 举报
回复
你可以顶一个成员变量来保持它们的值,而不是在CtlColor频繁的创建
dahaiI0 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 visualeleven 的回复:]
CtlColor函数中的后面的函数调用
GetStockObject和CreateSolidBrush有DeleteObject调用吗?
你可以顶一个成员变量来保持它们的值,而不是在CtlColor频繁的创建
[/Quote]
多谢指导,我把该释放的都释放了,可是还是有花屏,我再仔细找找看
Eleven 2010-12-27
  • 打赏
  • 举报
回复
CtlColor函数中的后面的函数调用
GetStockObject和CreateSolidBrush有DeleteObject调用吗?
你可以顶一个成员变量来保持它们的值,而不是在CtlColor频繁的创建
Eleven 2010-12-27
  • 打赏
  • 举报
回复
花屏?你的GDI资源没有及时释放吧。。。
dahaiI0 2010-12-27
  • 打赏
  • 举报
回复
感谢楼上2位的回答,部长很给力,第一时间给我解答,让我受宠若惊啊。。
::SelectObject(hMemDCCtrl, hBmOldCtrl);
::SelectObject(hMemDCBk, hBmOldBk);
::SelectObject(hMemDCScr, hBmScr);
最后1句代码写错了,总算解决了,同时也学到了一些新知识,深刻感受到资源使用释放的严谨
shenyi0106 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 dahaii0 的回复:]
引用 10 楼 shenyi0106 的回复:
Invalidate或者InvalidateRect就可以了

不太懂,我在调用SetTransparent里有Invalidate。放错地方了?
[/Quote]
你的透明Static控件花屏以后,你把你的床底最小化一下,在恢复,看看是否继续花屏?
dahaiI0 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 shenyi0106 的回复:]
Invalidate或者InvalidateRect就可以了
[/Quote]
不太懂,我在调用SetTransparent里有Invalidate。放错地方了?
Eleven 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 dahaii0 的回复:]
引用 9 楼 visualeleven 的回复:
运行你的程序,把任务管理器打开,看看你的GDI资源和内存资源是否是只增不减。。。

WM程序,好像看不到。。另外虽然在CtlColor函数中::CreateSolidBrush,可是有在析构里释放,是不是释放的地方不对?
[/Quote]
你Debug下看看你的CtlColor函数是否只执行了一次不就清楚了
dahaiI0 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 visualeleven 的回复:]
运行你的程序,把任务管理器打开,看看你的GDI资源和内存资源是否是只增不减。。。
[/Quote]
WM程序,好像看不到。。另外虽然在CtlColor函数中::CreateSolidBrush,可是有在析构里释放,是不是释放的地方不对?
shenyi0106 2010-12-27
  • 打赏
  • 举报
回复
Invalidate或者InvalidateRect就可以了
Eleven 2010-12-27
  • 打赏
  • 举报
回复
运行你的程序,把任务管理器打开,看看你的GDI资源和内存资源是否是只增不减。。。
Eleven 2010-12-27
  • 打赏
  • 举报
回复
CtlColor函数中的
m_SolidBrush = ::CreateSolidBrush(m_clrBkgnd);
你还不是一直在Create创建
When you no longer need the HBRUSH object call the DeleteObject function to delete it.
dahaiI0 2010-12-27
  • 打赏
  • 举报
回复
今天任务比较多,怕没时间完成了
dahaiI0 2010-12-27
  • 打赏
  • 举报
回复
麻烦大家有空帮看下,找了个多小时没结果,知道要求有点过分


CStaticEx::CStaticEx()
{
m_clrText = 0;//RGB( 255, 0, 0 );
m_clrBkgnd = 0;//RGB( 255, 255, 0 );
m_hbrBkgnd = NULL;
hbrCtrlBk = NULL;
m_bTransparent = FALSE;
m_unIDBmpBkGnd = 0;

m_WhiteBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
//m_SolidBrush = ::CreateSolidBrush(m_clrBkgnd);
}

CStaticEx::~CStaticEx()
{
if(m_WhiteBrush)
::DeleteObject(m_WhiteBrush);

if(m_SolidBrush)
::DeleteObject(m_SolidBrush);

if(hbrCtrlBk)
::DeleteObject(m_SolidBrush);
}

BEGIN_MESSAGE_MAP(CStaticEx, CStatic)
//{{AFX_MSG_MAP(CTransparentStatic)
ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()

// CStaticEx message handlers

BOOL CStaticEx::SetTransparent( UINT unIDBmpBkGnd, HINSTANCE hResourceInstance /*= NULL*/,HWND hWnd /*= NULL*/ )
{
m_hbrBkgnd = GetBkBrush(unIDBmpBkGnd, hResourceInstance, hWnd);
if (m_hbrBkgnd != NULL)
{
m_bTransparent = TRUE;
Invalidate();
return TRUE;
}
m_bTransparent = FALSE;
return FALSE;
}


HBRUSH CStaticEx::CtlColor(CDC* pDC, UINT nCtlColor)
{
HBRUSH hBr = NULL;

// 文本颜色
if (0 == m_clrText) // 没有自定义文本颜色
{
pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
}
else
{
pDC->SetTextColor(m_clrText);
}

// 背景颜色 绘制背景的刷子
if (m_bTransparent) // 透明模式
{
pDC->SetBkMode(TRANSPARENT);
hBr = m_hbrBkgnd;
}
else
{
if (0 == m_clrBkgnd) // 没有自定义文本颜色
{
pDC->SetBkColor((RGB(255, 255, 255)));
hBr = m_WhiteBrush;
}
else
{
pDC->SetBkColor(m_clrBkgnd);
m_SolidBrush = ::CreateSolidBrush(m_clrBkgnd);
return m_SolidBrush;
}
}

return hBr;
}

void CStaticEx::SetClrText(COLORREF clrText)
{
m_clrText = clrText;
Invalidate();
}

void CStaticEx::SetClrBkgnd(COLORREF clrBkgnd)
{
m_clrBkgnd = clrBkgnd;
Invalidate();
}

void CStaticEx::MoveWindowEx( LPCRECT lpRect, HINSTANCE hResourceInstance /*= NULL*/, BOOL bRepaint /*= TRUE*/ )
{
if (m_bTransparent)
{
MoveWindow(lpRect, FALSE);
m_hbrBkgnd = GetBkBrush(m_unIDBmpBkGnd, hResourceInstance);
Invalidate();
}
else
{
MoveWindow(lpRect, bRepaint);
}
}

HBRUSH CStaticEx::GetBkBrush( UINT unIDBmpBkGnd, HINSTANCE hResourceInstance /*= NULL*/, HWND hWnd /*= NULL*/ )
{
ASSERT(0 != unIDBmpBkGnd);
m_unIDBmpBkGnd = unIDBmpBkGnd;

if (NULL == hWnd)
{
hWnd = GetParent()->m_hWnd;
}
ASSERT(NULL != hWnd);

HWND hWndCtrl = this->m_hWnd;
ASSERT(NULL != hWndCtrl);

if (hResourceInstance == NULL)
{
hResourceInstance = AfxGetResourceHandle();
}

HBITMAP hBmpBk = ::LoadBitmap(hResourceInstance, MAKEINTRESOURCE(unIDBmpBkGnd));
ASSERT(NULL != hBmpBk);

hbrCtrlBk = NULL;

CRect rcScr;
::GetClientRect(hWnd, &rcScr);

CRect rcCtrl;
::GetWindowRect(hWndCtrl, &rcCtrl);
::ScreenToClient(hWnd, (LPPOINT)&rcCtrl);
::ScreenToClient(hWnd, ((LPPOINT)&rcCtrl) + 1);

CBitmap bitmap;
bitmap.Attach(hBmpBk);

BITMAP bi = {0};
GetObject(bitmap, sizeof(BITMAP), &bi);

HDC hDC = ::GetDC(hWnd);

HDC hMemDCBk = CreateCompatibleDC(hDC);
HDC hMemDCScr = CreateCompatibleDC(hDC);
HDC hMemDCCtrl = CreateCompatibleDC(hDC);

HBITMAP hBmScr = CreateCompatibleBitmap(hDC, rcScr.Width(), rcScr.Height());
HBITMAP hBmCtrl = CreateCompatibleBitmap(hDC, rcCtrl.Width(), rcCtrl.Height());

HBITMAP hBmOldBk = (HBITMAP)::SelectObject(hMemDCBk, hBmpBk);
HBITMAP hBmOldScr = (HBITMAP)::SelectObject(hMemDCScr, hBmScr);
HBITMAP hBmOldCtrl = (HBITMAP)::SelectObject(hMemDCCtrl, hBmCtrl);

::StretchBlt(hMemDCScr, 0, 0, rcScr.Width(), rcScr.Height(), hMemDCBk, 0, 0, bi.bmWidth, bi.bmHeight, SRCCOPY);

::BitBlt(hMemDCCtrl, 0, 0, rcCtrl.Width(), rcCtrl.Height(), hMemDCScr, rcCtrl.left, rcCtrl.top, SRCCOPY);

::SelectObject(hMemDCCtrl, hBmOldCtrl);
::SelectObject(hMemDCBk, hBmOldBk);
::SelectObject(hMemDCScr, hBmScr);

hbrCtrlBk = ::CreatePatternBrush(hBmCtrl);

::DeleteObject(hBmCtrl);
::DeleteObject(hBmScr);

::DeleteObject(hBmpBk);
::DeleteDC(hMemDCBk);
::DeleteDC(hMemDCScr);
::DeleteDC(hMemDCCtrl);
::ReleaseDC(hWnd, hDC);
return hbrCtrlBk;
}


头文件里定义

COLORREF m_clrText; // 记录文本颜色
COLORREF m_clrBkgnd; // 记录背景颜色

HBRUSH m_hbrBkgnd; // 用于绘制背景的刷子
HBRUSH m_WhiteBrush;
HBRUSH m_SolidBrush;
HBRUSH hbrCtrlBk;

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧