Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1362628
  • 博文数量: 118
  • 博客积分: 3888
  • 博客等级: 中校
  • 技术积分: 2940
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-10 18:15
个人简介

一看二做三总结

文章分类

全部博文(118)

分类: C/C++

2007-02-19 20:09:15

本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,并注明原作者及原链接,严禁用于任何商业用途。
作者:fireaxe_hq@hotmail.com
博客:fireaxe.blog.chinaunix.net
   背景图片的载入是通过BitBlt函数实现的。为了实现图片的渐变效果,利用背景图片与黑色图片的融合得到。通过对透明程度的设置,可以达到背景图片的渐变。

一、需要的头文件与库文件

AlphaBlend函数需要msimg32.lib库的支持

#pragma comment (lib,"msimg32.lib")//透明显示库

二、一个结构体和两个重要函数

    结构体BLENDFUNCTION用于指定两个DC的融合方式。通常情况下,只有SourceConstantAlpha是可以任意设定的,它决定了透明程度,取值范围为0~254。当取255时,表示利用源图像的每个象素点自带的Alpha值融合(前提是每个象素自带Alpha值,故一般不使用)

typedef struct _BLENDFUNCTION
{
    BYTE BlendOp;
//Default: AC_SRC_OVERAC_SRC_ALPHA
    BYTE BlendFlags;
//Must be zero
    BYTE SourceConstantAlpha;
    BYTE AlphaFormat;
//Default: AC_SRC_ALPHA
}BLENDFUNCTION, *PBLENDFUNCTION, *LPBLENDFUNCTION;

    BitBlt函数用于从源DC拷贝位图到当前DC,最后一个参数通常为SRCCOPY:从原始位图拷贝到目标位图

BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop );

    AlphaBlend函数用于两个DC的位图的融合。融合方式如下:

Dst.Red   = Src.Red * ConstantAlpha   + (1 - ConstantAlpha) * Dst.Red

Dst.Green = Src.Green * ConstantAlpha + (1 - ConstantAlpha) * Dst.Green

Dst.Blue  = Src.Blue * ConstantAlpha  + (1 - ConstantAlpha) * Dst.Blue

当源DC为需要显示的背景图案,目标DC为某种纯色(即图案隐去后的背景)时,通过Alpha值的逐渐增大,就可以实现。

AlphaBlend(
  HDC hdcDest,
//目标DC
  int nXOriginDest,
  int nYOriginDest,
  int nWidthDest,
  int hHeightDest,
  HDC hdcSrc,
//源DC
  int nXOriginSrc,
  int nYOriginSrc,
  int nWidthSrc,
  int nHeightSrc,
  BLENDFUNCTION blendFunction
//融合方式
);

三、环境上下文DC的建立

    环境的建立是通过下面两个几个函数实现的:

BOOL CreateCompatibleBitmap(CDC* pDC,int nWidth, int nHeight); //建立兼容位图
BOOL LoadBitmap(UINT nIDResource ); //载入位图
virtual BOOL CreateCompatibleDC(CDC* pDC); //建立兼容DC
CBitmap* SelectObject(CBitmap* pBitmap); //把位图选如环境

    利用第一个函数可以建立一个背景色为黑色的兼容位图,第二个函数可以载入背景位图。第三个函数是建立兼容DC。第四个函数可以把前面已经建立或载入的位图选入建立好的兼容DC中。这样可以建立一个纯黑色DC环境DCScr,与一个背景图案DC环境DCDst。通过AlphaBlend函数的融合,可以创造出一个所需明暗程度的DC环境,最后通过BitBlt函数可以把这个环境放入当前显示DC环境中。

    注意:设备环境上下文要先创建再选入位图,然后才能使用BitBlt函数。因为BitBlt函数是用来使两个环境上下文叠加的函数。

三、源码:

    为了实现渐变的效果,建立了定时器1,时间设定为100ms。所需的两个DC环境与透明度作为全局变量,因为透明度的类型为byte型只能表示0~255,为了实现透明度越界后定时器1停止的功能,定义个一个int型变量m_show来同步反映透明度的取值。位图的建立与载入、环境的建立、位图的选入和定时器1的设定等初始化代码放在了一个初始化函数里实现。

    进入定时器1后,每次进入定时器m_show与透明度都会同步增加,当m_show超过255时,透明度就不会再增加了,这时会显示一些欢迎文字,并关闭定时器1

//******* load head file and lib files *****

#include
#pragma comment (lib,"gdi32.lib")
#pragma comment (lib,"msimg32.lib")//透明显示库

 

//******* Global Variables *****
CDC myDCSrc,myDCDst;
int m_show; //透明度
BLENDFUNCTION bfn;

//******* Initial Function *****
void CTestDlg::myInitial()
{

    myDCSrc.CreateCompatibleDC(0);
    myDCDst.CreateCompatibleDC(0);//创建DC环境

    CBitmap bitSrc,bitDst;
    bitSrc.LoadBitmap(IDB_BITMAP_START);
    bitDst.CreateCompatibleBitmap(&myDCDst, 800,600);//创建与载入位图

    myDCSrc.SelectObject(bitSrc);
    myDCDst.SelectObject(bitDst);//把位图选入DC环境
   
    bfn.BlendOp = AC_SRC_OVER;
    bfn.BlendFlags = 0;
    bfn.SourceConstantAlpha = 0;
    bfn.AlphaFormat = 0;//设置BLENDFUNCTION结构体

    m_show = 0;//设置透明度

    SetTimer(1,100,NULL);//打开定时器1
}


//******* OnTimer Function *****
void CTestDlg::OnTimer(UINT nIDEvent)
{
    // TODO: Add your message handler code here and/or call default
    if (nIDEvent==1)
    {
        CClientDC dc(this);
        AlphaBlend(myDCDst, 0, 0, 800, 600,

               myDCSrc, 0, 0, 800, 600, bfn); //半透明处理
        dc.BitBlt(0, 0, 800, 600, &myDCDst, 0, 0, SRCCOPY);
        bfn.SourceConstantAlpha += 50;
        m_show += 50;
        if (255 < m_show)
        {
             dc.SetTextColor(RGB(255, 0, 0)); //设置字体颜色为红色
             dc.SetBkMode(TRANSPARENT); //设定背景色显示方式为无色
             dc.TextOut(300, 200, "Hello World!!");

            KillTimer(1);
        }
    }
    CDialog::OnTimer(nIDEvent);
} 

 

本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,并注明原作者及原链接,严禁用于任何商业用途。
作者:fireaxe_hq@hotmail.com
博客:fireaxe.blog.chinaunix.net

阅读(4765) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~