透明控件的通用解决方案

介绍 在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

posted @ 2020-08-11 09:00  Dincat  阅读(260)  评论(0编辑  收藏  举报