场景:
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