• 用PNG透明图片和GDI+做不规则透明窗体"异形窗口"


    一、准备工作(PNG图片透空窗体)

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

    2、下面开始做好展开此项工作的基本准备工作。
    创建一个对话框应用程序,名称为Gdi+PNG
    在VC6.0下的设置:
    (1)、下载gdiplus forVC6.0的SDK,(总共两兆多)
    (2)、在C盘建立文件夹“GDI+”将开发包拷贝在里面,亦即建立如下路径,以便例子代码顺利编译(当然你可以放到任意你喜欢的地方,只要在你的Project中正确包含路径即可!)。
    (也可以将gdiplus.h放在你的VC6.0的include路径,gdiplus.lib放在你的lib路径,将gdiplus.dll放到你的system32目路下,windows2000以前的版本需要gdiplus.dll文件)

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

    (3)在stdAfx.h中添加对GDI+环境的设置 #define UNICODE
    #ifndef ULONG_PTR // 在VC2003上可无
    #define ULONG_PTR unsigned long* // 在VC2003上可无(实为无附号4字节)
    #endif // 在VC2003上可无
    #include <comdef.h> //初始化COM口
    #include "c:\gdi+\includes\gdiplus.h" // 请修改为你的头文件路径
    using namespace Gdiplus; // 名称空间
    #pragma comment(lib, "c:\\gdi+\\lib\\gdiplus.lib") // 请修改为你的.lib文件路径

    在VC2003中如下设置:
    (1)VS2003.net中打开“项目”---“属性”---“链接器”---“输入”---“附加依赖项”,输入“gdiplus.lib”。
    (2)在“stdafx.h”文件中输入
    #include <comdef.h> //初始化COM口
    #include <gdiplus.h> // GDI+头文件
    using namespace Gdiplus; // 命名空间
    (3)VS2003中已经带有GDI+库了。

    在应用程序的主头文件(Gdi+PNG.h)里面,在应用程序项目的应用类中,添加一个成员变量,如下列代码:
    ULONG_PTR m_pGdiToken; // 其中,ULONG_PTR是一个DWORD数据类型,
    // 该成员变量用来保存GDI+被初始化后在应用程序中的GDI+标识,
    // 以便能在应用程序退出后,引用该标识来调用Gdiplus:: GdiplusShutdown来关闭GDI+
    在应用程序的类行为(Gdi+PNG.cpp)InitInstance()初始化函数里加入如下代码:
    CWinApp::InitInstance(); // 这个函数后面
    GdiplusStartupInput m_gdiplusStartupInput;
    GdiplusStartup(&m_pGdiToken,&m_gdiplusStartupInput,NULL);

    //在对话框程序结束后,在应用类中添加ExitInstance的重载,并添加下列代码用来关闭GDI+,
    //关闭gdiplus的环境
    应用程序的类行为的ExitInstance()函数里加入:
    GdiplusShutdown(m_pGdiToken);
    return CWinApp::ExitInstance(); // 这个语句前

    二、程序的实现过程
    1、在Gdi+PNGDlg.h中定义所有类成员变量,包括所有图片的指针和图片的长宽尺寸信息。

    // 自定义数据
    Image *m_pImageBack; // 背景图像指针,Image是一个图像类。
    HDC m_hdcMemory;
    int m_BakWidth; // 背景图像宽
    int m_BakHeight; // 背景图像高
    BLENDFUNCTION m_Blend;

    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”中调用。以上定义中后三项就是为此作准备的。
    UpdateLayeredWindow(hwnd:HWND; // 窗口句柄
    hdcDst:HDC; // 目标 DC
    ptDst:pPoint; // 目标的 TopLeft
    Size:pSize; // 显示 Size
    hdcSrc:HDC; // 源 DC
    ptSrc:pPoint; // 源 DC 的 TopLeft
    crKey:COLORREF; // 透明颜色值
    Blend:pBlendFunction; // Alpha 混合函数
    dwFlags:DWord // 一组标志位常量
    );

    2、在对话框的OnCreate()中添加如下代码:对函数和成员变量进行初始化!(其中ImageFromIDResource()函数为从资源中载入Png图像的一个方法!)
    int CGDIPClockDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CDialog::OnCreate(lpCreateStruct) == -1)
    return -1;
    // TODO: 在此添加您专用的创建代码
    hFuncInst = LoadLibrary("User32.DLL");
    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 // 透明度

    using namespace Gdiplus; // 名称空间
    m_pImageBack = Gdiplus::Image::FromFile(L"F:\\abc.png"); // 直接读取文件,注意是双“\\”斜杠
    // ImageFromIDResource(IDR_PNG2, "PNG", m_pImageBack); // 读取资源中的PNG图片, 为自订义类形“PNG”
    // 这里Image没有提供字节调用资源中图像的函数,
    // ImageFromIDResource()是通过资源名称"PNG"和资源ID号将图像的Image指针传递给指针应用。来完成的。
    // 这个函数是摘自网上
    // ImageFileMe("F:\\abc.png", m_pImageBack); // 读取二进制文件
    m_BakWidth = m_pImageBack->GetWidth(); // 返回图片宽度
    m_BakHeight = m_pImageBack->GetHeight(); // 返回图片高度

    // 以下是实现窗口在最上面。
    ::SetWindowPos(m_hWnd, HWND_TOPMOST,0,0,m_BakWidth,m_BakHeight,SWP_NOSIZE|SWP_NOMOVE);

    return 0;
    }

    3、在OnDestroy()里输入删除图像的代码
    void CMfcGdi1Dlg::OnDestroy()
    {
    CDialog::OnDestroy();

    // TODO: 在此处添加消息处理程序代码
    delete m_pImageBack;
    m_pImageBack = NULL;
    }

    5、在OnPaint() 中输入以下代码, m_Blend.SourceConstantAlpha表示整个窗体的透明度

    HDC hdcTemp = GetDC()->m_hDC;
    m_hdcMemory = CreateCompatibleDC(hdcTemp);
    HBITMAP hBitMap = CreateCompatibleBitmap(hdcTemp, m_BakWidth, m_BakHeight);
    SelectObject(m_hdcMemory, hBitMap);

    // m_Blend.SourceConstantAlpha=100; // 窗口透明度最大为255,最小为0
    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;
    graph.DrawImage(m_pImageBack, points,3);

    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);
    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;

    以下为自订义的读取资源函数,如果图片不在资源里可以不用输入。
    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);
    }

    BOOL CMfcGdi1Dlg::ImageFileMe(LPCTSTR filename, Image * &pImg) //我自已加入的用来读二进制文件的。可以不用输
    {
    // Allocate global memory on which to create stream
    HFILE filehwnd;
    OFSTRUCT fileopenbuff;
    filehwnd = OpenFile(filename, &fileopenbuff, OF_READ);
    if (filehwnd == HFILE_ERROR)
    return FALSE;
    int len = GetFileSize((HANDLE)filehwnd, 0);

    HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
    BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
    _lread(filehwnd, m_hMem, len);
    IStream* pstm;
    CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
    // load from stream
    pImg=Gdiplus::Image::FromStream(pstm);
    // free/release stuff
    GlobalUnlock(m_hMem);
    pstm->Release();
    _lclose(filehwnd);
    }
    以下为可以拖动窗口。
    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);
    }

  • 相关阅读:
    HDU 1063 Exponentiation
    HDU 1261 字串数
    HDU 1715 大菲波数
    HDU 1002 A + B Problem II
    csharp 復制DataTable修改某列的值
    解决IE6下透明PNG图片有灰底的解决方案
    webform TextBox以一条横线显示 兼容各主流瀏覽器 .
    SQL 工齡計算
    csharp Format CultureInfo
    Csharp Winform TextBox 樣式以一條橫線顯示
  • 原文地址:https://www.cnblogs.com/buffer/p/1410326.html
Copyright © 2020-2023  润新知