介绍 在UI开发中,我们通常需要实现一些不错的效果,使一些控件透明是我们经常遇到的问题。在本文中,我将介绍一种实现控件透明性的方法。源代码包括基于Win32 API的类CTransparentHelper,它可以用于MFC、ATL、WTL、Win32应用程序,或者其他一些框架。我开发了一个新的版本,因为我在工作中使用了它,所以如果你有任何建议,bug报告,或问题,请发送给我。你也可以访问我的技术博客来获得更多的信息。 背景 我写这段代码是因为我需要一些透明的控件,如按钮、滑块控件和进度控件。我发现当父窗口移动或控件移动时,在线可用的一些方法并不有效;当我们想在可调整大小的对话框中使用透明控件时,这就会出现问题。所以我写了CTransparentHelper;当MoveWindow被调用时,你可以有一个平滑的透明效果,并且这个类适合所有的控件。 特性 没有框架的依赖。可用于不同类型的控件。可用于多层透明。在当前代码中易于使用。 使用的代码 在介绍如何使用源代码之前,我建议使用内存DC来存储父对话框的背景DC。这样便于子控件的透明化,也提高了绘制的效率。详细信息,请参考源代码。 包括“TransparentHelper.h” 包括“TransparentHelper。h”在控件的文件中需要透明。并且,添加一个CTransparentHelper类型的对象。 隐藏,复制Code
#pragma once #include "TransparentHelper.h" // CSliderCtrlEx class CSliderCtrlEx : public CSliderCtrl { ……… CTransparentHelper m_objTrans; }
初始化CTransparentHelper的对象 隐藏,复制Code
void CSliderCtrlEx::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class ……. CSliderCtrl::PreSubclassWindow(); m_objTrans.Install( GetSafeHwnd()); …… }
在需要时调用ctransparencythelper的函数TransparentBk 隐藏,复制Code
BOOL CSliderCtrlEx::OnSliderDrawChannel( CDC* pDC, CRect& rect, UINT nState) { …… if ( m_objTrans.IsValid() ) { m_objTrans.TransparentBk( pDC->GetSafeHdc(), GetSafeHwnd()); } ……… return TRUE; }
向控件的父窗口添加代码 有时,父窗口是一个对话框。我需要处理消息WM_TRANSPARENT_BK,这是发送从透明控制为了得到回DC。 隐藏,复制Code
LRESULT CTransparentControlDlg::OnTransaprentBk( WPARAM wParam, LPARAM lParam) { HDC hdc = ( HDC)wParam; HWND hwnd = ( HWND)lParam; CTransparentHelper::OnTranparentControl( m_pMemDC->GetSafeHdc(), (WPARAM)hdc, (LPARAM)hwnd); return TRUE; }
备注:m_pMemDC是对话框的内存DC,它会随着对话框大小的变化而变化。 当背景改变时,孩子们就不会快乐 当对话框的内存DC发生变化时,它必须通知具有透明标签的子组件。 隐藏,复制Code
void CTransparentControlDlg::BuildBkDC() { //rebuild the background dc ........ //when the parent dialog's background is rebuild, //notify the child which has an transparent tag. CTransparentHelper::NotifyTransparentChild( GetSafeHwnd()); }
消息WM_NOTIFY_TRANSPARENT 当背景发生变化时,透明控件需要处理父控件发送的WM_NOTIFY_TRANSPARENT消息。 隐藏,复制Code
LRESULT CSliderCtrlEx::OnNotifyTransparent( WPARAM wParam, LPARAM lParam) { if ( ::IsWindowEnabled( GetSafeHwnd())) { ::EnableWindow( GetSafeHwnd(),FALSE); ::EnableWindow( GetSafeHwnd(),TRUE); } else { ::EnableWindow( GetSafeHwnd(),TRUE); ::EnableWindow( GetSafeHwnd(),FALSE); } //This operation is for the repaint of slider control, //because Invalidate cann't bring the NM_CUSTOMDRAW message. //M..., this may not the best method to solve the problem. //If you have other method, please tell me. return TRUE; }
备注:对于某些绘图方法下的一些控件(例如,NM_CUSTOMDRAW), Invalidate不会导致真正的重绘。因此,我添加了WM_NOTIFY_TRANSAPRENT消息使其兼容。如果透明控件将在调用Invalidate后重新绘制自己,则不需要处理该消息。 本文转载于:http://www.diyabc.com/frontweb/news12092.html