MFC实现以不规则PNG图片作为窗口背景

时间:2024-10-26 07:08:21
#include "stdafx.h" #include "CShowBack.h" #include "afxdialogex.h" #include "resource.h" // CShowBack 对话框 IMPLEMENT_DYNAMIC(CShowBack, CDialogEx) CShowBack::CShowBack(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_MY_DIALOG, pParent) { } CShowBack::~CShowBack() { } void CShowBack::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CShowBack, CDialogEx) ON_WM_CREATE() ON_WM_DRAWITEM() ON_WM_PAINT() END_MESSAGE_MAP() // CShowBack 消息处理程序 using namespace Gdiplus; // 名称空间 int CShowBack::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDialogEx::OnCreate(lpCreateStruct) == -1) return -1; GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; // Initialize GDI+. GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); m_Blend.BlendOp = 0; //theonlyBlendOpdefinedinWindows2000 m_Blend.BlendFlags = 0; //nothingelseisspecial... m_Blend.AlphaFormat = 1; //... m_Blend.SourceConstantAlpha = 255;//AC_SRC_ALPHA // 透明度 m_pImageBack = Gdiplus::Image::FromFile(L"backimage.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; } void CShowBack::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { // TODO: 在此添加消息处理程序代码和/或调用默认值 CDialogEx::OnDrawItem(nIDCtl, lpDrawItemStruct); } //从资源中加载 BOOL ImageFormResource(UINT nID, LPCTSTR str, Image*& pImage) { HINSTANCE hIns = AfxGetResourceHandle(); HRSRC hRsrc = ::FindResource(hIns, MAKEINTRESOURCE(nID), str); if (!hRsrc) return FALSE; DWORD dwLen = SizeofResource(hIns, hRsrc); BYTE* lpRsrc = (BYTE*)LoadResource(hIns, hRsrc); if (!lpRsrc) return FALSE; HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, dwLen); BYTE* pMem = (BYTE*)GlobalLock(m_hMem); memcpy(pMem, lpRsrc, dwLen); GlobalUnlock(m_hMem); IStream* pStream; CreateStreamOnHGlobal(m_hMem, FALSE, &pStream); pImage = Image::FromStream(pStream);//如果pImage加载成功,需要释放,不然会有内存泄漏 pStream->Release(); FreeResource(lpRsrc); GlobalFree(m_hMem); return TRUE; } void CShowBack::OnDestroy() { CDialog::OnDestroy(); // TODO: 在此处添加消息处理程序代码 delete m_pImageBack; m_pImageBack = NULL; } void CShowBack::OnPaint() { 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; }