⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdipclockdlg.cpp

📁 功能——在VC6.0中用GDI+调用png图片实现半透明渐变的特效窗口
💻 CPP
字号:
// GDIPClockDlg.cpp : implementation file
//

#include "stdafx.h"
#include "GDIPClock.h"
#include "GDIPClockDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGDIPClockDlg dialog

CGDIPClockDlg::CGDIPClockDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CGDIPClockDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CGDIPClockDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CGDIPClockDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGDIPClockDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CGDIPClockDlg, CDialog)
	ON_WM_CONTEXTMENU()
	//{{AFX_MSG_MAP(CGDIPClockDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_CREATE()
	ON_WM_TIMER()
	ON_WM_RBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_DESTROY()
	ON_COMMAND(IDM_EXIT, OnExit)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGDIPClockDlg message handlers

BOOL CGDIPClockDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

//启动后立刻更新窗口样式为透明窗体
	UpdateClockDisplay();
	SetTimer(1,500,NULL);
//去除任务栏窗口对应按钮
	ModifyStyleEx (WS_EX_APPWINDOW,WS_EX_TOOLWINDOW );

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CGDIPClockDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CGDIPClockDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CGDIPClockDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


void CGDIPClockDlg::OnDestroy() 
{
	// TODO: Add your message handler code here and/or call default
	delete m_pImageClock;
	delete m_pImageHHour;
	delete m_pImageHMinu;
	delete m_pImageHSec;
	FreeLibrary(hFuncInst); 
	CDialog::OnDestroy();
	
}


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

    ImageFromIDResource(IDR_PNGNUM,"PNG",m_pImageNum);
    ImageFromIDResource(IDR_PNGBAK1,"PNG",m_pImageClock1);
    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;
}

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);//1~255
	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);
	matrixH.TransformPoints( pointsH, 3); // 用该矩阵转换points
	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);
	matrixM.TransformPoints( pointsM, 3); // 用该矩阵转换pointsM
	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);
	matrix.TransformPoints( pointsS, 3); // 用该矩阵转换pointsS
	graph.DrawImage (m_pImageHSec,pointsS, 3);
//H
	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到指定位置
//M
	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到指定位置
//S
	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); //该函数从m_pImageClock中剪切指定rect中的像素draw到指定位置

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

void CGDIPClockDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	UpdateClockDisplay();
	CDialog::OnTimer(nIDEvent);
}

void CGDIPClockDlg::OnRButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	CDialog::OnRButtonUp(nFlags, point);
}

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




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::OnContextMenu(CWnd*, CPoint point)
{
	if (point.x == -1 && point.y == -1){
		//keystroke invocation
		CRect rect;
		GetClientRect(rect);
		ClientToScreen(rect);

		point = rect.TopLeft();
		point.Offset(5, 5);
	}

	CMenu menu;
	VERIFY(menu.LoadMenu(IDR_MENU1));

	CMenu* pPopup = menu.GetSubMenu(0);
	ASSERT(pPopup != NULL);
	CWnd* pWndPopupOwner = this;

	while (pWndPopupOwner->GetStyle() & WS_CHILD)
		pWndPopupOwner = pWndPopupOwner->GetParent();

	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
		pWndPopupOwner);
}

void CGDIPClockDlg::OnExit() 
{
	// TODO: Add your command handler code here
	SendMessage(WM_CLOSE,1,0);	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -