问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

在GDI+ 中如何的到PNG图片非透明部分的Region。

发布网友 发布时间:2022-04-11 22:07

我来回答

2个回答

懂视网 时间:2022-04-12 02:29

平时我们经常可以看到很多应用程序启动过程很酷,什么百叶窗,渐变,各种效果,今天我们看一下如何在程序中增加这种效果。 一、示例展示: 二、示例思路: 1.首先介绍两个知识,一个是函数MoveWindow(),一个是定时器。 函数MoveWindow():改变指定窗口的位置

平时我们经常可以看到很多应用程序启动过程很酷,什么百叶窗,渐变,各种效果,今天我们看一下如何在程序中增加这种效果。

一、示例展示:







二、示例思路:


1.首先介绍两个知识,一个是函数MoveWindow(),一个是定时器。

  •  函数MoveWindow():改变指定窗口的位置和大小.对顶窗口来说,位置和大小取决于屏幕的左上角;对子窗口来 说,位置和大小取决于父窗口客户区的左上角。函数原形如下:
  • BOOL MoveWindow(
    HWND hWnd,
    int X,
    int Y,
    int nWidth,
    int nHeight,
    BOOL bRepaint
    );
  • 定时器:VisualC++自带的一个组件,可以按照一定的时间间隔周期性执行。具体的相关函数如下:
  • SetTimer() :设置并启动定时器
    KillTimer() :关闭定时器
    OnTimer() :定时器消息WM_TIMER相应函数


    2.主要思路是,就是在窗口启动时,设置定时器,在定时器WM_TIMER相应函数中,不断地更新窗口,直到更新到我们预期的样子。



    三、示例步骤:


    1.在窗口初始化函数OnInitDialog()中,初始化窗口状态,设置定时器。

    // CDynamicStartDlg メッセージ ハンドラー
    
    BOOL CDynamicStartDlg::OnInitDialog()
    {
    	CDialogEx::OnInitDialog();
    
    	// "バージョン情報..." メニューをシステム メニューに追加します。
    
    	// IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		BOOL bNameValid;
    		CString strAboutMenu;
    		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    		ASSERT(bNameValid);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、
    	// Framework は、この設定を自動的に行います。
    	SetIcon(m_hIcon, TRUE);			// 大きいアイコンの設定
    	SetIcon(m_hIcon, FALSE);		// 小さいアイコンの設定
    
    	// TODO: 初期化をここに追加します。
    	
    	//获取对话框窗口的大小
    	this->GetWindowRect(&m_dlgRect);
    
    	//获取桌面窗口的大小
    	CWnd* pDestopWnd = GetDesktopWindow();
    	pDestopWnd->GetWindowRect(&m_destopRect);
    
    	//初始化对话框的位置和大小(位置:桌面中心,大小:0)
    	MoveWindow(
    		(m_destopRect.Width()-m_dlgRect.Width())/2, 
    		(m_destopRect.Height()-m_dlgRect.Height())/2,
    		0,
    		0);
    
    	//设置定时器,并启动(5s)
    	this->SetTimer(1, 5, NULL);
    
    	return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
    }


    2.添加WM_TIMER的相应函数OnTimer(),在OnTimer()中更新窗口的状态,达到预期的样子时,就关闭定时器。

    void CDynamicStartDlg::OnTimer(UINT_PTR nIDEvent)
    {
    	// TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。
    
    	CRect dlgRect;  //保存对话框窗口当前大小
    	static int offsetX = 2;//更新对话框窗口状态时的X增量
    	static int offsetY = 2;//更新对话框窗口状态时的Y增量
    
    	switch (nIDEvent)
    	{
    	case 1:
    		//获取对话框窗口当前的大小
    		this->GetWindowRect(&dlgRect);
    		//更新对话框的位置和大小(利用:offsetX,offsetY)
    		MoveWindow(
    		(-offsetX + m_destopRect.Width() - dlgRect.Width())/2, 
    		(-offsetY + m_destopRect.Height() - dlgRect.Height())/2,
    		dlgRect.Width() + offsetX,
    		dlgRect.Height() + offsetY);
    
    		//X方向达到对话框窗口预期值,停止增加
    		if (dlgRect.Width() >= m_dlgRect.Width()) offsetX = 0;
    		//Y方向达到对话框窗口预期值,停止增加
    		if (dlgRect.Height() >= m_dlgRect.Height()) offsetY = 0;
    		//X,Y都达到对话框窗口预期值,关闭定时器
    		if (dlgRect.Width() >= m_dlgRect.Width() && dlgRect.Height() >= m_dlgRect.Height())
    		{
    			this->KillTimer(nIDEvent);
    		}
    	default:
    		break;
    	}
    	CDialogEx::OnTimer(nIDEvent);
    }
    

    P.S提供文章示例代码:http://download.csdn.net/detail/chenjintaoxp/7639411

    热心网友 时间:2022-04-11 23:37

    [ 原创文档 本文适合中级读者 已阅读19544次 ] 文档 代码 工具

    在VC6.0中用GDI+调用png图片实现半透明渐变的特效窗口

    作者:邵凯锋

    下载源代码

    一、概述

    GDI+的应用使得平面图形图象编程变的更加容易,本文以一个基于对话框的时钟程序为例,在VC6.0中调用*.png图片实现半透明渐变窗口,该程序实现了指针式和数字式两种时钟显示方式。窗口实现了半透明渐变窗口、窗口拖动无移动矩形框、隐藏了任务栏窗体按钮等。
    效果图如下:

    图一 程序执行后与WindowXP桌面背景效果图

    二、准备工作

    1、图片资源准备工作。首先在Photoshop中编辑好时钟的背景、时针、分针以及数字时钟显示方式的所有图片,如下图:将这些图片保存成为带透明通道的.png格式(GDI+调用显示时能够透明调背景)。这样程序中图片资源就准备好了。

    2、下面开始做好在VC6.0下展开此项工作的基本准备工作。

    (1)、下载gdiplus forVC6.0的SDK,(总共两兆多)
    (2)、在C盘建立文件夹“GDI+”将开发包拷贝在里面,亦即建立如下路径,以便例子代码顺利编译(当然你可以放到任意你喜欢的地方,只要在你的Project中正确包含路径即可!)。

    C:\GDI+\Includes
    C:\GDI+\Lib
    C:\GDI+\gdiplus.dll

    (3)在stdAfx.h中添加对GDI+环境的设置 #define UNICODE
    #ifndef ULONG_PTR
    #define ULONG_PTR unsigned long*
    #endif
    #include "c:\gdi+\includes\gdiplus.h" ////请修改为你的头文件路径
    using namespace Gdiplus;
    #pragma comment(lib, "c:\\gdi+\\lib\\gdiplus.lib") ////请修改为你的.lib文件路径

    (4)在GDIPClock.cpp中编辑app的InitInstance()中添加如下代码进行GDI+的初始化工作 GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    ......
    //在对话框程序结束后
    //关闭gdiplus的环境
    GdiplusShutdown(gdiplusToken);

    三、程序的实现全过程
    1、建立一个基于对话框的Project,这里的名称为GDIPClock
    2、在GDIPClockDlg.h中定义所有类成员变量,包括所有图片的指针和图片的长宽尺寸信息。

    Image *m_pImageClock;
    Image *m_pImageClock1;
    Image *m_pImageHHour;
    Image *m_pImageHMinu;
    Image *m_pImageHSec;
    Image *m_pImageNum;
    int m_BakWidth , m_BakHeight ;
    int m_HourWidth, m_HourHeight;
    int m_MinuWidth , m_MinuHeight;
    int m_SecWidth , m_SecHeight ;
    HINSTANCE hFuncInst ;
    Typedef BOOL (WINAPI*MYFUNC)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,
    COLORREF,BLENDFUNCTION*,DWORD);
    MYFUNC UpdateLayeredWindow;

    在这一步中需要特别说明的是,在创建透明窗口式需要调用一个Windows API函数UpdateLayeredWindow(),该函数在.net以上的版本的SDK中有申明,但是在VC6.0下要调用要么下载200多兆的高版本SDK,要么从动态链接库“User32.dll”中调用,这里选择从“User32.dll”中调用。以上定义中后三项就是为此作准备的。
    3、在对话框的OnCreate()中添加如下代码:对2的函数和成员变量进行初始化!(其中ImageFromIDResource()函数为从资源中载入Png图像的一个方法!)
    int CGDIPClockDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CDialog::OnCreate(lpCreateStruct) == -1)
    return -1;
    hFuncInst = LoadLibrary("User32.DLL");
    BOOL bRet=FALSE;
    if(hFuncInst)
    UpdateLayeredWindow=(MYFUNC)GetProcAddress(hFuncInst, "UpdateLayeredWindow");
    else
    {
    AfxMessageBox("User32.dll ERROR!");
    exit(0);
    }
    //初始化gdiplus的环境
    // Initialize GDI+.
    m_Blend.BlendOp=0; //theonlyBlendOpdefinedinWindows2000
    m_Blend.BlendFlags=0; //nothingelseisspecial...
    m_Blend.AlphaFormat=1; //...
    m_Blend.SourceConstantAlpha=255;//AC_SRC_ALPHA

    // png图片添加到资源中了在"PNG"下:所以这里可以从资源中调用,
    // 这里Image没有提供字节调用资源中图像的函数,
    // ImageFromIDResource()是通过资源名称"PNG"和资源ID号将图像
    // 的Image指针传递给指针应用。来完成的。

    ImageFromIDResource(IDR_PNGBAK1,"PNG",m_pImageClock1);
    ImageFromIDResource(IDR_PNGNUM,"PNG",m_pImageNum);
    ImageFromIDResource(IDR_PNGBAK,"PNG",m_pImageClock);
    ImageFromIDResource(IDR_PNGHOUR,"PNG",m_pImageHHour);
    ImageFromIDResource(IDR_PNGMIN,"PNG",m_pImageHMinu);
    ImageFromIDResource(IDR_PNGSEC,"PNG",m_pImageHSec);
    m_BakWidth =m_pImageClock->GetWidth();
    m_BakHeight =m_pImageClock->GetHeight();
    m_HourWidth =m_pImageHHour->GetWidth();
    m_HourHeight=m_pImageHHour->GetHeight();
    m_MinuWidth =m_pImageHMinu->GetWidth();
    m_MinuHeight=m_pImageHMinu->GetHeight();
    m_SecWidth =m_pImageHSec->GetWidth();
    m_SecHeight =m_pImageHSec->GetHeight();
    ::SetWindowPos(m_hWnd, HWND_TOPMOST,0,0,m_BakWidth,m_BakHeight,SWP_NOSIZE|SWP_NOMOVE);
    return 0;
    }

    4.在OnInitDialog()种添加如下代码对调用透明窗体初始化和设置时钟进行刷新,代码意义有注解: //启动后立刻更新窗口样式为透明窗体
    UpdateClockDisplay();
    SetTimer(1,500,NULL);
    //去除任务栏窗口对应按钮
    ModifyStyleEx (WS_EX_APPWINDOW,WS_EX_TOOLWINDOW );
    void CGDIPClockDlg::OnTimer(UINT nIDEvent)
    {
    // TODO: Add your message handler code here and/or call default
    UpdateClockDisplay();
    CDialog::OnTimer(nIDEvent);
    }

    5、透明窗体创建于刷新,均调用以下函数完成,函数的参数表示整个窗体的透明度
    在该函数中包括了GDI+中对Image.DrawImage()函数的集中重载方式的使用,还有在GDI+中图像变换矩阵的使用初步研究。

    BOOL CGDIPClockDlg::UpdateClockDisplay(int Transparent)
    {
    HDC hdcTemp=GetDC()->m_hDC;
    m_hdcMemory=CreateCompatibleDC(hdcTemp);
    HBITMAP hBitMap=CreateCompatibleBitmap(hdcTemp,m_BakWidth,m_BakHeight);
    SelectObject(m_hdcMemory,hBitMap);
    if(Transparent<0||Transparent>100) Transparent=100;

    m_Blend.SourceConstantAlpha=int(Transparent*2.55);
    HDC hdcScreen=::GetDC (m_hWnd);
    RECT rct;
    GetWindowRect(&rct);
    POINT ptWinPos={rct.left,rct.top};
    Graphics graph(m_hdcMemory);

    Point points[] = { Point(0, 0),
    Point(m_BakWidth, 0),
    Point(0, m_BakHeight)
    };
    static bool bFly=false;
    bFly?graph.DrawImage(m_pImageClock, points, 3): graph.DrawImage(m_pImageClock1, points, 3);
    bFly=!bFly;
    int OxyX=140;//m_BakWidth/2+8;
    int OxyY=90;//m_BakHeight/2+10;
    SYSTEMTIME SystemTime; // address of system time structure
    GetLocalTime(&SystemTime);

    // 定义一个单位矩阵,坐标原点在表盘*
    Matrix matrixH(1,0,0,1,OxyX,OxyY);
    // 时针旋转的角度度
    matrixH.Rotate(SystemTime.wHour*30+SystemTime.wMinute/2.0-180);
    Point pointsH[] = { Point(0, 0),Point(m_HourWidth, 0),Point(0, m_HourHeight)};
    matrixH.Translate(-m_HourWidth/2,-m_HourHeight/6);
    // 用该矩阵转换points
    matrixH.TransformPoints( pointsH, 3);
    graph.DrawImage (m_pImageHHour,pointsH, 3);

    // 定义一个单位矩阵,坐标原点在表盘*
    Matrix matrixM(1,0,0,1,OxyX,OxyY);
    // 分针旋转的角度度
    matrixM.Rotate(SystemTime.wMinute*6-180);
    Point pointsM[] = { Point(0, 0),Point(m_MinuWidth, 0),Point(0, m_MinuHeight)};
    matrixM.Translate(-m_MinuWidth/2,-m_MinuHeight/6);
    // 用该矩阵转换pointsM
    matrixM.TransformPoints( pointsM, 3);
    graph.DrawImage (m_pImageHMinu,pointsM, 3);

    // 定义一个单位矩阵,坐标原点在表盘*
    Matrix matrix(1,0,0,1,OxyX,OxyY);
    // 秒针旋转的角度度
    matrix.Rotate(SystemTime.wSecond*6-180);
    Point pointsS[] = { Point(0, 0),Point( m_SecWidth,0),Point(0,m_SecHeight )};
    matrix.Translate(-m_SecWidth/2,-m_SecHeight/7);
    // 用该矩阵转换pointsS
    matrix.TransformPoints( pointsS, 3);
    graph.DrawImage (m_pImageHSec,pointsS, 3);
    //HH:MM:SS

    //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    graph.DrawImage(m_pImageNum,0, 0, 14*(SystemTime.wHour/10), 0,14,23,UnitPixel);
    //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    graph.DrawImage(m_pImageNum,20,0, 14*(SystemTime.wHour%10), 0,14,23,UnitPixel);
    //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    graph.DrawImage(m_pImageNum,20*2,0, 140, 0,14,23,UnitPixel);
    //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    graph.DrawImage(m_pImageNum,20*3, 0, 14*(SystemTime.wMinute/10), 0,14,23,UnitPixel);
    //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    graph.DrawImage(m_pImageNum,20*4,0, 14*(SystemTime.wMinute%10), 0,14,23,UnitPixel);
    //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    graph.DrawImage(m_pImageNum,20*5,0, 140, 0,14,23,UnitPixel);
    //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    graph.DrawImage(m_pImageNum,20*6, 0, 14*(SystemTime.wSecond/10), 0,14,23,UnitPixel);
    //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置
    graph.DrawImage(m_pImageNum,20*7,0, 14*(SystemTime.wSecond%10), 0,14,23,UnitPixel);

    SIZE sizeWindow={m_BakWidth,m_BakHeight};
    POINT ptSrc={0,0};
    DWORD dwExStyle=GetWindowLong(m_hWnd,GWL_EXSTYLE);
    if((dwExStyle&0x80000)!=0x80000)
    SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle^0x80000);

    BOOL bRet=FALSE;
    bRet= UpdateLayeredWindow( m_hWnd,hdcScreen,&ptWinPos,
    &sizeWindow,m_hdcMemory,&ptSrc,0,&m_Blend,2);
    graph.ReleaseHDC(m_hdcMemory);
    ::ReleaseDC(m_hWnd,hdcScreen);
    hdcScreen=NULL;
    ::ReleaseDC(m_hWnd,hdcTemp);
    hdcTemp=NULL;
    DeleteObject(hBitMap);
    DeleteDC(m_hdcMemory);
    m_hdcMemory=NULL;
    return bRet;
    }
    BOOL CGDIPClockDlg::ImageFromIDResource(UINT nID, LPCTSTR sTR,Image * &pImg)
    {
    HINSTANCE hInst = AfxGetResourceHandle();
    HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type
    if (!hRsrc)
    return FALSE;
    // load resource into memory
    DWORD len = SizeofResource(hInst, hRsrc);
    BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
    if (!lpRsrc)
    return FALSE;
    // Allocate global memory on which to create stream
    HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
    BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
    memcpy(pmem,lpRsrc,len);
    IStream* pstm;
    CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
    // load from stream
    pImg=Gdiplus::Image::FromStream(pstm);
    // free/release stuff
    GlobalUnlock(m_hMem);
    pstm->Release();
    FreeResource(lpRsrc);
    }
    void CGDIPClockDlg::OnLButtonDown(UINT nFlags, CPoint point)
    {
    //禁止显示移动矩形窗体框
    ::SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,TRUE,NULL,0);
    //非标题栏移动整个窗口
    SendMessage(WM_SYSCOMMAND,0xF012,0);
    // PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));
    CDialog::OnLButtonDown(nFlags, point);
    }

    详细实现过程请参考源代码!
    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    苹果电脑电池充不进电苹果电脑充不进去电是怎么回事 苹果电脑不充电没反应苹果电脑充电指示灯不亮充不了电怎么办 狗狗更加忠诚护家、善解人意,养一只宠物陪伴自己,泰迪能长多大... 描写泰迪狗的外形和特点的句子 国外留学有用吗 花钱出国留学有用吗 !这叫什么号 百万医疗赔付后是否可以续保 前一年理赔过医疗险还能续保吗? 医疗住院险理赔后还能购买吗? vc编程的问题,我想实现当鼠标进入对话框时,只弹出一次非模态对话框 vc编程:在主界面加载之前创建一个模式对话框 在VC++界面编程里怎样在一个菜单项下添加一个对话框? VC++对话框的颜色渐变问题 C++从一个文件读取字符串,把多空格改成单空格,并写入另一个文件 怎么将空格符号读入到字符串中 Java问题:从字符串中提取用空格隔开的数字 JS 怎么替换字符串里所有的加号 查询字符串中用到竖杠即%7,还有加号有何用意 数据库读取的是字符串怎么加1 SQL 数据库读取字符串问题 ASP中如何显示数据库中的所有空格 从数据库读取到的数据,有空格,赋值给字符串是也是有空格的怎么取出空格~? 将字符串中的所有空格改为一个“-” C# 在数据库中提取了字符串,但串中有空格,如何去除? 从数据库读取字符串,这样保留输入时的换行,空格等格式 如何提高程序员的编程速度,(详细点)? 如何提高编程效率 vim中的折叠问题? 如果想让他折叠的是两个大括号之间的内容怎么设定啊 真正做到使用vim提高效率,花了多长时间学习和练习 VC/MFC关于父对话框与子窗体之间消息的传递? VC++单文档编程,如何给一个对话框的多个按钮添加图片? VC++编程,ActiveX控件嵌入 VC6.0 怎么释放资源 火狐 浏览器怎样安装firebug 怎么在火狐浏览器安装firebug 如何在火狐浏览器上安装firebug工具进行调试 火狐浏览器的fire bugger怎么使用 火狐 浏览器的firebug一直出现下载错误,都有想吧苹果砸了的心了,请问怎么解决啊 如何使用Mac远程调试iPhone/iPad 中的网页 火狐浏览器怎样显示网页的代码,下载一个什么插件 火狐浏览器的插件firepath怎么用啊 如何在Mac里调试网页在 iPhone 的显示效果 1. 用SQL语句创建满足下列要求的数据库, jxl导入excel到数据库的问题 java用jxl将Excel里的数据导入到sqlserver数据库 JAVA中,JXL获取excel中的数据。我已经用for循环取到了excel中的数据,如何把取到的数据添加到数据库呢? jxl读取excel导入到数据库,报错java.lang.NoClassDefFoundError: jxl&#47;read&#47;biff&#47;BiffException java中如果使用jxl实现从excel导入大量的数据到数据库? 如何使用MYSQL数据库或MSSQL数据库