首页 > 代码库 > [ATL/WTL]_[中级]_[原生的复选框(checkbox button)和单选按钮(radio button)实现透明背景效果解决方案]

[ATL/WTL]_[中级]_[原生的复选框(checkbox button)和单选按钮(radio button)实现透明背景效果解决方案]


场景:

1. mfc,wtl的原生控件都是通过父窗口拦截 WM_CTLCOLORSTATIC 事件来修改子控件的颜色和背景色,CStatic可以通过返回HOLLOW_BRUSH来绘制透明背景:

m_HollowBrush = AtlGetStockBrush(HOLLOW_BRUSH);

但是如果使用manifest文件使用最新 外观样式的话,返回HOLLOW_BRUSH对checkbox和radio button没有任何效果,原背景还是存在。虽然通过自绘一个checkbox和radio button 并不是什么难事,但是使用原生的button话在新系统(WIN8)下会得到一致的体验-- 使用最新的windows原生的样式或外观. 其实我的原则就是原生能做到的,就不需要重复造轮子.


” 邓学斌 “ 大牛也做过这方面的解释: http://blog.csdn.net/cometnet/article/details/38080449


最开始学习控件背景透明 参考的是 “吹泡泡的小猫” 的文章  创建有个性的对话框之ATL/WTL篇    

但是这个demo也是出现我刚说的问题,就是radio button, checkbox 没效果.


解决方案:

1. 使用这个函数返回一个BITMAP BRUSH来绘制背景,注意并不是透明BRUSH.

CreatePatternBrush

但这样会产生一个问题,每个控件都需要一个特定区域的背景图片作为背景,如果界面上控件多的话为每个控件绘制背景这是一个浩大的工作量。所以这里我写了一个helper类帮我们做这些事情.

dh_window_bg_brush_helper.h

#ifndef __DH_WINDOW_BG_BRUSH_HELPER
#define __DH_WINDOW_BG_BRUSH_HELPER

#include <Windows.h>
#include <map>

class DhWindowBgBrushHelper
{
public:
	DhWindowBgBrushHelper();
	~DhWindowBgBrushHelper();

	void AddSubWindow(HWND hwnd,HBITMAP parent_background);
	HBRUSH GetHBRUSH(HWND hwnd);
private:
	std::map<HWND,HBRUSH> hbrush;
};

#endif

dh_window_bg_brush_helper.cpp

#include "stdafx.h"
#include "dh_window_bg_brush_helper.h"

DhWindowBgBrushHelper::DhWindowBgBrushHelper()
{
	
}

DhWindowBgBrushHelper::~DhWindowBgBrushHelper()
{
	std::map<HWND,HBRUSH>::iterator ite =  hbrush.begin();
	for(; ite != hbrush.end(); ++ite) 
	{
		ATLASSERT(ite->second != NULL);
		::DeleteObject(ite->second);
	}
	hbrush.clear();
}


void DhWindowBgBrushHelper::AddSubWindow(HWND hwnd,HBITMAP parent_background)
{
	CWindow child(hwnd);
	CWindow parent = child.GetParent();

	RECT rect;
	RECT parent_window_rect;
	RECT parent_client_rect;
	parent.GetWindowRect(&parent_window_rect);
	parent.GetClientRect(&parent_client_rect);

	child.GetWindowRect(&rect);
	parent.ScreenToClient(&rect);

	long width = rect.right - rect.left;
	long height = rect.bottom - rect.top;

	CDC sdc; 
	CDC ddc;
	sdc.CreateCompatibleDC(NULL);
	ddc.CreateCompatibleDC(NULL);
	CBitmap destBmp;
	destBmp.CreateCompatibleBitmap(CClientDC(NULL),width,height);
	sdc.SelectBitmap(parent_background);
	ddc.SelectBitmap(destBmp);
	ddc.BitBlt(0, 0, width, height, sdc, rect.left, rect.top, SRCCOPY );

	CBrush bs ;
	bs.CreatePatternBrush(destBmp);
	hbrush[hwnd] = bs;

	bs.Detach();
}

HBRUSH DhWindowBgBrushHelper::GetHBRUSH(HWND hwnd)
{
	ATLASSERT(hwnd);

	if(hbrush.find(hwnd) != hbrush.end())
	{
		return hbrush[hwnd];
	}
	return NULL;
}

调用方式:

1.在父控件Dialog里定义一个成员函数:

DhWindowBgBrushHelper brush_helper_;
2. 在 初始化 OnInitDialog 里调用helper.

brush_helper_.AddSubWindow(GetDlgItem(1014),m_Bitmap);
brush_helper_.AddSubWindow(GetDlgItem(1015),m_Bitmap);

3.同样的在onCtlColor处理函数里根据hWnd获取对应的BRUSH来绘制背景.

LRESULT CBmpDlg::OnCtlColor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
		HDC hDC = (HDC)wParam;
		HWND hWnd = (HWND)lParam;

		int style = GetStyle();
		if(uMsg == WM_CTLCOLORSTATIC)
		{
			SetTextColor(hDC,t_crTextColor);
			SetBkMode(hDC,TRANSPARENT);
			bHandled = TRUE;
			HBRUSH brush = brush_helper_.GetHBRUSH(hWnd);
			if(brush)
			{
				return (LRESULT)brush;
			}
			return (LRESULT)m_HollowBrush;
		}
		
		SetTextColor(hDC,t_crTextColor);
		SetBkMode(hDC,TRANSPARENT);
		return 0;
}


效果图, 这里是在“吹泡泡的小猫” 的原程序上改的效果:



程序下载地址:

http://download.csdn.net/detail/infoworld/7952165



[ATL/WTL]_[中级]_[原生的复选框(checkbox button)和单选按钮(radio button)实现透明背景效果解决方案]