创建一个带透明度的异形对话框模板 SetLayeredWindowAttributes

一、先说使用方法:

1,如下,先建按常规方式一对话框,生成对话框类,

2,将继承类直接改为CLS_DlgBaseLayered如:

class CLS_DLGTool : public CLS_DlgBaseLayered

3,修改构造及消息宏的继承类,如:

IMPLEMENT_DYNAMIC(CLS_DLGTool, CLS_DlgBaseLayered)

CLS_DLGTool::CLS_DLGTool(CWnd* pParent /*=NULL*/)
    : CLS_DlgBaseLayered(CLS_DLGTool::IDD, pParent)

BEGIN_MESSAGE_MAP(CLS_DLGTool, CLS_DlgBaseLayered)

4,OnInitDialog中添加继承:

BOOL CLS_DLGTool::OnInitDialog()
{
    CLS_DlgBaseLayered::OnInitDialog();

-----

 

5,调用方法:

    m_dlgTool.SetFlagName("d:\\pic\\transparent22.jpg");
    m_dlgTool.Create(IDD_DIALOG_SYSTEM_TOOL, this);
    CRect rcTool;
    m_dlgTool.GetClientRect(&rcTool);
    int iToolW = rcTool.Width();
    int iToolH = rcTool.Height();
    rcTool.left = rc.right - rcTool.Width();
    rcTool.right = rc.right;
    rcTool.top = rc.top + (rc.Height() - rcTool.Height())/2;
    rcTool.bottom = rcTool.top + iToolH;
    ScreenToClient(&rcTool);
    m_dlgTool.MoveWindow(&rcTool);
    m_dlgTool.ShowWindow(SW_SHOW);

二,类定义如下:

对话框模板类:CLS_DlgBaseLayered.h头文件

#pragma once

/*
层对话框基类,可带关键色,有透明度,可依指定透明色的图形生成异形层。
注意此对话框如为子对话框则失去透明度功能。分层不支持子控件,可为弹出或非模态。
Create创建前调用:SetTransparentParam  否则使用默认
如需要异形窗口或图形窗口也须创建前调用:SetFlagName加载图形
*/
// CLS_DlgBaseLayered dialog
const COLORREF CONST_crDefault = RGB(1,0,0);
const int CONST_iTransparentLevelDefault = 150;//0--255
const int CONST_iTransparentMaskDefault = LWA_COLORKEY|LWA_ALPHA;
class CLS_DlgBaseLayered : public CDialog
{
    DECLARE_DYNAMIC(CLS_DlgBaseLayered)

public:
    CLS_DlgBaseLayered(UINT nIDTemplate,CWnd* pParent = NULL);   // standard constructor
    virtual ~CLS_DlgBaseLayered();

// Dialog Data
    //enum { IDD = IDD_LS_DLGBASELAYERED };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

    DECLARE_MESSAGE_MAP()

    //SetLayeredWindowAttributes(m_hWnd,RGB(1,0,0),150,LWA_COLORKEY|LWA_ALPHA); 
    //后三个参数对应以下三个变量。
    COLORREF m_crMark;//关键色 也即透明色
    int m_iTransparentLevel;//透明度
    int m_iLayerMask;//层透明模式  关键色还是透明度或二者都有。

    CString m_cstrFlagFile;//图片文件,主要是决定窗口形状。
    CImage *m_pImage;//图片对象指针。
    void RefreshFlag(CDC* pDC);
    void RefreshFlag();


    void CreateRgnFromPicEx( CString _cstrPic );//此接口只取非透明区域
    void CreateRgnFromPic( CString _cstrPic );//此接口只取透明区域 暂未使用

    HCURSOR m_hCursor;//移动时的鼠标形状。
    bool m_blCanMove; //是否可移动

public:
    void SetMovable(bool _blCanMove = true);
    //可以使用异型窗口,取自图形。
    void SetFlagName(CString _cstrFlagName);
    virtual BOOL OnInitDialog();
    void SetTransparentParam(COLORREF _crMark,int _iTransparentLevel,int _iLayerMask);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);

    //以下按钮响应纯是为了防止回车,ESC等造成窗口退出,继承对话框可自行实现其它。
    afx_msg void OnBnClickedOk();
    afx_msg void OnBnClickedCancel();
};
 

实现文件:CLS_DlgBaseLayered.cpp

// CLS_DlgBaseLayered.cpp : implementation file
//

#include "stdafx.h"
#include "CLS_DlgBaseLayered.h"

// CLS_DlgBaseLayered dialog

IMPLEMENT_DYNAMIC(CLS_DlgBaseLayered, CDialog)

CLS_DlgBaseLayered::CLS_DlgBaseLayered(UINT nIDTemplate,CWnd* pParent /*=NULL*/)
: CDialog(nIDTemplate, pParent)
{

    m_crMark = CONST_crDefault;
    m_iTransparentLevel = CONST_iTransparentLevelDefault;
    m_iLayerMask = CONST_iTransparentMaskDefault;

    m_cstrFlagFile = "";
    m_pImage = NULL;

    m_blCanMove = false;
    m_hCursor = LoadCursor(NULL,IDC_SIZEALL);
}

CLS_DlgBaseLayered::~CLS_DlgBaseLayered()
{
    if (m_pImage)
    {
        m_pImage->Destroy();
        delete m_pImage;
        m_pImage = NULL;
    }
    DeleteObject(m_hCursor);
    m_hCursor = NULL;
}

void CLS_DlgBaseLayered::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CLS_DlgBaseLayered, CDialog)
    ON_WM_ERASEBKGND()
    ON_WM_LBUTTONDOWN()
    ON_WM_SETCURSOR()
    ON_BN_CLICKED(IDOK, &CLS_DlgBaseLayered::OnBnClickedOk)
    ON_BN_CLICKED(IDCANCEL, &CLS_DlgBaseLayered::OnBnClickedCancel)
END_MESSAGE_MAP()

// CLS_DlgBaseLayered message handlers
BOOL CLS_DlgBaseLayered::OnInitDialog()
{
    CDialog::OnInitDialog();

    SetWindowLong(m_hWnd,GWL_EXSTYLE,
        GetWindowLong(m_hWnd,GWL_EXSTYLE)^WS_EX_LAYERED);

    ::SetLayeredWindowAttributes(m_hWnd,m_crMark,m_iTransparentLevel,m_iLayerMask);

    if(m_cstrFlagFile.GetLength() > 0)
    {
        CreateRgnFromPicEx(m_cstrFlagFile);
        //RefreshFlag();
    }
    return TRUE;  
}

void CLS_DlgBaseLayered::SetTransparentParam( COLORREF _crMark,int _iTransparentLevel,int _iLayerMask )
{
    m_crMark = _crMark;
    m_iTransparentLevel = _iLayerMask;
    m_iLayerMask = _iLayerMask;
}

BOOL CLS_DlgBaseLayered::OnEraseBkgnd(CDC* pDC)
{
    RefreshFlag(pDC);
    return TRUE;
}

void CLS_DlgBaseLayered::RefreshFlag(CDC* pDC)
{
    CRect rc;
    GetClientRect(&rc);
    if (m_pImage)
    {
        CDC memDc;
        memDc.CreateCompatibleDC(pDC);
        HBITMAP hOldBmp = (HBITMAP)memDc.SelectObject(m_pImage->operator HBITMAP());

        pDC->StretchBlt(0,0, rc.Width(),rc.Height(), &memDc, 0,0, m_pImage->GetWidth(),m_pImage->GetHeight(), SRCCOPY);
        memDc.SelectObject(hOldBmp);
        memDc.DeleteDC();
    }
    else
    {
        pDC->FillSolidRect(&rc,m_crMark);
    }
}

void CLS_DlgBaseLayered::RefreshFlag()
{
    CDC* pDC = CDC::FromHandle(::GetDC(GetSafeHwnd()));
    RefreshFlag(pDC);
    ::ReleaseDC(GetSafeHwnd(), pDC->GetSafeHdc());
}


void CLS_DlgBaseLayered::SetFlagName( CString _cstrFlagName )
{
    m_cstrFlagFile = _cstrFlagName;
}

void CLS_DlgBaseLayered::CreateRgnFromPicEx( CString _cstrPic )
{
    if (!m_pImage)
    {
        m_pImage = new CImage;
    }
    else
    {
        m_pImage->Destroy();
    }
    m_pImage->Load(_cstrPic);
    if (m_pImage->IsNull())
    {
        AfxMessageBox("请正确选择图象文件");
        return ;
    }

    CBitmap cBitmap;
    cBitmap.Attach(m_pImage->operator HBITMAP());//加载描述窗口形状的BMP图片

    CRect rc;
    GetWindowRect(&rc);//获得窗体区域
    rc.right = rc.left+m_pImage->GetWidth();
    rc.bottom = rc.top +m_pImage->GetHeight();
    //MoveWindow(&rc,TRUE);//窗口大小等同图片大小。


    int x, y;
    CRgn mainRgn, currentRgn;
    CDC* pDC = GetDC();//获得设备上下文
    CDC memDC;
    CBitmap bitmap;//声明位图对象
    CBitmap* pOldMemBmp = NULL;
    COLORREF currentColor;//当前像素颜色


    memDC.CreateCompatibleDC(pDC);//创建与内存兼容的设备上下文
    pOldMemBmp = memDC.SelectObject(&cBitmap);
    mainRgn.CreateRectRgn(0, 0, rc.Width(), rc.Height());//初始化区域
    COLORREF TransColor=memDC.GetPixel(0,0);//透明色取第一象素色。
    int minX=0,MaxX=rc.Width(),minY=0,MaxY=rc.Height();
    for (x = 0; x <= rc.Width(); x++)
    {
        for (y = 0; y <= rc.Height(); y++)
        {
            //将透明部分去掉
            currentColor = memDC.GetPixel(x, y);//得到当前象素颜色
            //如果当前色是透明颜色,就将该像素所在位置从窗体区域中去除
            if (currentColor == TransColor)
            {
                currentRgn.CreateRectRgn(x, y, x + 1, y + 1);//创建区域
                mainRgn.CombineRgn(&mainRgn, &currentRgn, RGN_XOR);//去除相互重叠的区域
                currentRgn.DeleteObject();//删除区域对象
            }
            else
            {
                //非透明色,想取最适合区域大小,还未实现
                /*    if (minX == 0 || minX > x)
                {
                minX = x;
                }

                if (minY == 0 || minY > y)
                {
                minY = y;
                }

                if (MaxX == rc.Width() || MaxX < x)
                {
                MaxX = x;
                }

                if (MaxY == rc.Height() || MaxY < y)
                {
                MaxY = y;
                }
                */
            }
        }
    }

    MoveWindow(minX,minY,MaxX - minX,MaxY - minY,TRUE);
    //     mainRgn.OffsetRgn(-minX,-minY);
    SetWindowRgn((HRGN)mainRgn, TRUE);//设置窗体为区域的形状

    GetClientRect(&rc);
    memDC.SelectObject(pOldMemBmp);
    cBitmap.Detach();
    memDC.DeleteDC();
    ReleaseDC(pDC);
    mainRgn.DeleteObject();
    currentRgn.DeleteObject();//删除区域对象
}
void CLS_DlgBaseLayered::CreateRgnFromPic( CString _cstrPic )
{
    if (!m_pImage)
    {
        m_pImage = new CImage;
    }
    else
    {
        m_pImage->Destroy();
    }
    m_pImage->Load(_cstrPic);
    if (m_pImage->IsNull())
    {
        AfxMessageBox("请正确选择图象文件");
        return;
    }

    COLORREF TransColor=RGB(1,0,0);//透明色
    CBitmap cBitmap;
    cBitmap.Attach(m_pImage->operator HBITMAP());//加载描述窗口形状的BMP图片
    CDC* pDC=this->GetDC();
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);//创建与传入DC兼容的临时DC
    CBitmap *pOldMemBmp=NULL;
    pOldMemBmp=memDC.SelectObject(&cBitmap);//将位图选入临时DC,方便对图片在控件环境中进行操作
    CRgn wndRgn;
    wndRgn.CreateRectRgn(0,0,0,0);//创建总的窗体区域,初始region为0
    BITMAP bit;
    cBitmap.GetBitmap (&bit);//取得位图参数,这里要用到位图的长和宽
    int y;

    TransColor=memDC.GetPixel(0,0);
    CRgn rgnTemp; //保存临时region
    for(y=0;y<=bit.bmHeight ;y++)
    {
        int iX = 0;
        do
        {
            //跳过透明色找到下一个非透明色的点.
            while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) != TransColor)
                iX++;
            //记住这个起始点
            int iLeftX = iX;
            //寻找下个透明色的点
            while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) == TransColor)
                ++iX;
            //创建一个包含起点与重点间高为1像素的临时“region”
            rgnTemp.CreateRectRgn(iLeftX, y, iX, y+1);
            //合并到主"region".
            wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR);
            //删除临时"region",否则下次创建时和出错
            rgnTemp.DeleteObject();
        }while(iX<bit.bmWidth);
    }
    SetWindowRgn(wndRgn,TRUE);
    memDC.SelectObject(pOldMemBmp);
    memDC.DeleteDC();
    cBitmap.Detach();
    ReleaseDC(pDC);
    wndRgn.DeleteObject();
    rgnTemp.DeleteObject();

}

void CLS_DlgBaseLayered::SetMovable( bool _blCanMove /*= true*/ )
{
    m_blCanMove = _blCanMove;
}

void CLS_DlgBaseLayered::OnLButtonDown(UINT nFlags, CPoint point)
{
    if (m_blCanMove)
    {
        PostMessage( WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0); 
        return;
    }

    CDialog::OnLButtonDown(nFlags, point);
}
BOOL CLS_DlgBaseLayered::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if (m_blCanMove && m_hCursor != NULL)
    {
        ::SetCursor(m_hCursor);
        return TRUE;
    } 
    return CDialog::OnSetCursor(pWnd, nHitTest, message);
}
void CLS_DlgBaseLayered::OnBnClickedOk(){}
void CLS_DlgBaseLayered::OnBnClickedCancel(){}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值