主程序// KissMe.h : main header file for the KISSME application //#if !defined(AFX_KISSME_H__8748CF84_5673_11D3_9001_DBE596190CF8__INCLUDED_) #define AFX_KISSME_H__8748CF84_5673_11D3_9001_DBE596190CF8__INCLUDED_#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000#ifndef __AFXWIN_H__ #error include 'stdafx.h' before including this file for PCH #endif#include "resource.h" // main symbols///////////////////////////////////////////////////////////////////////////// // CKissMe: // See KissMe.cpp for the implementation of this class //class CKissMe : public CWinApp { public: CKissMe();// Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CKissMe) public: virtual BOOL InitInstance(); //}}AFX_VIRTUAL// Implementation //{{AFX_MSG(CKissMe) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_KISSME_H__8748CF84_5673_11D3_9001_DBE596190CF8__INCLUDED_)
// KissMe.cpp : Defines the class behaviors for the application. // // 软件名称:KissMe // 作者:徐景周 // 功能:透明动态位图显示
#include "stdafx.h" #include "KissMe.h" #include "KissMeDlg.h" #include "TransparentWnd.h"#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif///////////////////////////////////////////////////////////////////////////// // CKissMeBEGIN_MESSAGE_MAP(CKissMe, CWinApp) //{{AFX_MSG_MAP(CKissMe) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CKissMe constructionCKissMe::CKissMe() { // TODO: add construction code here, // Place all significant initialization in InitInstance }///////////////////////////////////////////////////////////////////////////// // The one and only CKissMe objectCKissMe theApp;///////////////////////////////////////////////////////////////////////////// // CKissMe initializationBOOL CKissMe::InitInstance() { srand(time(NULL));
// create and load the frame with its resources CRect rect(0, 0, 100, 100); pFrame->CreateTransparent("KissMe,Darling!", rect);//IDB_MASK, IDB_BACK); pFrame->CenterWindow(); //初始显示窗体位置 pFrame->ShowWindow(SW_SHOW);
例2:多个区域叠加(布尔运算)1、HRGN hRGN1=CreateRoundRectRgn(0,0,200,200,20,20);//创建圆角矩形区域2、HRGN hRGN2=CreateRectRgn(10,10,20,20);//创建矩形区域3、HRGN hRGN; CombineRgn(hRGN,hRGN1,hRGN2,RGN_DIFF); //使用区域1减区域2,生成新区域hRGN(可选的参数有加,减,交等,详见MSDN)4、SetWindowRgn(hRGN,TRUE);//将创建的区域设定为窗口区域 B.位图区域方式创建不规则窗口 点击此处下载BitmapToRegion函数代码rgn.zip:1.95 KB (2,002 字节) 1、HBITMAP hBmp=(HBITMAP)LoadImage(应用程序句柄, 位图文件名, IMAGE_BITMAP, 宽度, 高度, LR_LOADFROMFILE); //载入一个位图,该位图中的某个特定颜色将被作为透明区域处理2、HRGN hRGN=BitmapToRegion(hBmp,RGB(255,0,0),0);//调用位图转换为区域的函数,透明色为红色,第三个参数为公差,为0即只将红色设定为透明色。如果公差为1,意味着与给定透明色的红绿蓝三色数值的差距在1范围内的颜色也将被作为透明色处理。3、SetWindowRgn(hRGN,TRUE);//将创建的区域设定为窗口区域
说明:关于BitmapToRegion函数,它的功能就是将位图转换为区域,原理来自API: ExtCreateRegion,该函数使用RGNDATA结构中的数据创建RGN,本函数就是分析位图的各个像素点数,根据它们填充RGNDATA结构,然后创建RGN的。
y<=cRect.Height() - m_FrameWidth-m_MaskBottomOff; y++){ //取得坐标处象素的颜色值 cl = memDC.GetPixel(x - m_FrameWidth-m_MaskLeftOff, y - m_CaptionHeight-m_MaskTopOff); if(col == TransColor) { //象素颜色为指定的透明色,创建透明“微区域” rgnTemp.CreateRectRgn(x, y, x+1, y+1); //“扣像”,从完整的区域中“扣除”透明的“微区域” wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_XOR); //删除刚创建的透明“微区域”,释放系统资源 rgnTemp.DeleteObject(); } } } if (pOldMemBmp) memDC.SelectObject(pOldMemBmp); //用设定窗口为指定的区域 SetWindowRgn((HRGN)wndRgn, TRUE);}重置系统默认的背景擦除操作,即添加WM_ERASEBKGND消息处理过程,这一步可以借助ClassWizard来简化操作。BOOL CTransDlg::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default CRect rect; CDC memDC; CBitmap cBitmap; CBitmap* pOldMemBmp = NULL; GetWindowRect(&rect); //装载背景位图 cBitmap.LoadBitmap(m_BackBitmapID); memDC.CreateCompatibleDC(pDC); pOldMemBmp = memDC.SelectObject(&cBitmap); //将背景位图复制到窗口客户区 pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY); if (pOldMemBmp) memDC.SelectObject( pOldMemBmp ); //删除系统却省的OnEraseBkgnd功能 //return CDialog::OnEraseBkgnd(pDC); return TRUE;}接下来是在WM_PAINT的消息处理函数OnPaint()中添加代码。由于当背景位图比较大时,进行区域处理比较耗时,所以只在启动时进行一次处理。一种方法是OnInitDialog()处理,但这样会在从启动程序到窗口出现有相当的延迟,易引起程序尚未启动的误解。再一种方法就是在OnPaint()处理,但为了避免重复处理,可以加上一个判断标志。以下是OnPaint()的代码,正体为AppWizard生成,粗体为自己添加内容。void CTransDlg::OnPaint() { if (IsIconic()) { …… } else { if(m_nFirstRun){ //首次运行标志 //修改鼠标光标为等待方式 BeginWaitCursor(); //设置背景区域 SetupRegion(GetWindowDC(),
IDB_BACKBMP,
IDB_BACKBMP,
0x00FFFFFF /*白色*/); //恢复鼠标光标为正常模式 EndWaitCursor(); m_nFirstRun = 0; } CDialog::OnPaint(); }}
#if !defined(AFX_TRANSPARENTWND_H__6508F000_5685_11D3_9001_CBBD225E6BC4__INCLUDED_)
#define AFX_TRANSPARENTWND_H__6508F000_5685_11D3_9001_CBBD225E6BC4__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// TransparentWnd.h : header file
///////////////////////////////////////////////////////////////////////////////
// TransparentWnd windowclass TransparentWnd : public CWnd
{
// Construction
public:
TransparentWnd(); void CreateTransparent(LPCTSTR pTitle, RECT &rect);
void SetupRegion(CDC *pDC);
void DoChange(void); CBitmap m_bmpDraw;
int m_iAniSeq;// Attributes
public:// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(TransparentWnd)
//}}AFX_VIRTUAL// Implementation
public:
virtual ~TransparentWnd(); // Generated message map functions
protected:
//{{AFX_MSG(TransparentWnd)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnHelp();
afx_msg void OnExit();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_TRANSPARENTWND_H__6508F000_5685_11D3_9001_CBBD225E6BC4__INCLUDED_)
//
// Modified by jingzhou xu. 2000.12#include "stdafx.h"
#include "KissMe.h"
#include "TransparentWnd.h"
#include "BCMenu.h" //添加位图菜单
#include "KissMeDlg.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endifBCMenu popmenu; //定义位图菜单变量
/////////////////////////////////////////////////////////////////////////////
// TransparentWndTransparentWnd::TransparentWnd()
{
m_iAniSeq=0; //图像变化初始值
}TransparentWnd::~TransparentWnd()
{
}BEGIN_MESSAGE_MAP(TransparentWnd, CWnd)
//{{AFX_MSG_MAP(TransparentWnd)
ON_WM_LBUTTONDOWN()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_TIMER()
ON_WM_RBUTTONDOWN()
ON_COMMAND(IDR_HELP, OnHelp)
ON_COMMAND(IDR_EXIT, OnExit)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()//********************************************************************************
//* CreateTransparent()
//*
//* Creates the main application window transparent
//********************************************************************************
void TransparentWnd::CreateTransparent(LPCTSTR pTitle, RECT &rect)
{
// 创建一个隐藏窗口
CreateEx( 0,
AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
pTitle,
WS_POPUP ,
rect,
NULL,
NULL,
NULL);
DoChange();
}//********************************************************************************
//* SetupRegion()
//*
//* Set the Window Region for transparancy outside the mask region
//********************************************************************************
void TransparentWnd::SetupRegion(CDC *pDC)
{
CDC memDC;
CBitmap &cBitmap=m_bmpDraw;
CBitmap* pOldMemBmp = NULL;
COLORREF col,colMask;
CRect cRect;
int x, y;
CRgn wndRgn, rgnTemp; GetWindowRect(&cRect);
CPoint ptOrg=cRect.TopLeft(); BITMAP bmInfo;
cBitmap.GetObject(sizeof(bmInfo),&bmInfo);
CRect rcNewWnd=CRect(ptOrg,CSize(bmInfo.bmWidth,bmInfo.bmHeight)); memDC.CreateCompatibleDC(pDC);
pOldMemBmp = memDC.SelectObject(&cBitmap);
colMask=memDC.GetPixel(0,0); wndRgn.CreateRectRgn(0, 0, rcNewWnd.Width(), rcNewWnd.Height());
for(x=0; x<=rcNewWnd.Width(); x++)
{
for(y=0; y<=rcNewWnd.Height(); y++)
{
col = memDC.GetPixel(x, y);
if(col == colMask)
{
rgnTemp.CreateRectRgn(x, y, x+1, y+1);
wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_XOR);
rgnTemp.DeleteObject();
}
}
}
if (pOldMemBmp) memDC.SelectObject(pOldMemBmp);
SetWindowRgn((HRGN)wndRgn, TRUE);
MoveWindow(rcNewWnd);
}void TransparentWnd::DoChange(void)
{
char szBmp[20];
//不断替换图像
sprintf(szBmp,"IDB_KISSME%d",m_iAniSeq%6+1); m_bmpDraw.DeleteObject();
m_bmpDraw.LoadBitmap(szBmp);
CWindowDC dc(this);
SetupRegion(&dc);
Invalidate();
}void TransparentWnd::OnLButtonDown(UINT nFlags, CPoint point)
{ CWnd::OnLButtonDown(nFlags, point); //实现无标题拖动
PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x,point.y));
}int TransparentWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
SetTimer(1,300,NULL); //开始时的图像显示时间
SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); //窗体总在总前面
return 0;
}BOOL TransparentWnd::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetWindowRect(&rect); CDC memDC;
CBitmap &cBitmap=m_bmpDraw;;
CBitmap* pOldMemBmp = NULL;
CFont* pOldMemFont=NULL; memDC.CreateCompatibleDC(pDC);
pOldMemBmp = memDC.SelectObject(&cBitmap);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY); if (pOldMemBmp) memDC.SelectObject( pOldMemBmp ); return TRUE;
// return CWnd::OnEraseBkgnd(pDC);
}void TransparentWnd::OnTimer(UINT nIDEvent)
{
switch(nIDEvent)
{
case(1)://变换图像
DoChange();
break;
default:
break;
}
m_iAniSeq++;
CWnd::OnTimer(nIDEvent);
}void TransparentWnd::OnRButtonDown(UINT nFlags, CPoint point)
{
CWnd::OnRButtonDown(nFlags, point); //添加右键快捷图标菜单(用于下拉式菜单)
popmenu.LoadMenu(IDR_MENU);
popmenu.ModifyODMenu(NULL, IDR_HELP,IDB_HELP);
popmenu.ModifyODMenu(NULL,IDR_EXIT,IDB_EXIT);
ClientToScreen(&point);
BCMenu *psub = (BCMenu *)popmenu.GetSubMenu(0);
psub->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);
popmenu.DestroyMenu();
}void TransparentWnd::OnHelp()
{
CKissMeDlg dlg; //此对话框只显示一次
if( !FindWindow(NULL,"帮助"))
dlg.DoModal();
}void TransparentWnd::OnExit()
{
DestroyWindow();
}
//#if !defined(AFX_KISSME_H__8748CF84_5673_11D3_9001_DBE596190CF8__INCLUDED_)
#define AFX_KISSME_H__8748CF84_5673_11D3_9001_DBE596190CF8__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif#include "resource.h" // main symbols/////////////////////////////////////////////////////////////////////////////
// CKissMe:
// See KissMe.cpp for the implementation of this class
//class CKissMe : public CWinApp
{
public:
CKissMe();// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CKissMe)
public:
virtual BOOL InitInstance();
//}}AFX_VIRTUAL// Implementation //{{AFX_MSG(CKissMe)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_KISSME_H__8748CF84_5673_11D3_9001_DBE596190CF8__INCLUDED_)
//
// 软件名称:KissMe
// 作者:徐景周
// 功能:透明动态位图显示
#include "stdafx.h"
#include "KissMe.h"
#include "KissMeDlg.h"
#include "TransparentWnd.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CKissMeBEGIN_MESSAGE_MAP(CKissMe, CWinApp)
//{{AFX_MSG_MAP(CKissMe)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CKissMe constructionCKissMe::CKissMe()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}/////////////////////////////////////////////////////////////////////////////
// The one and only CKissMe objectCKissMe theApp;/////////////////////////////////////////////////////////////////////////////
// CKissMe initializationBOOL CKissMe::InitInstance()
{
srand(time(NULL));
//一次只运行一个程序实例,如果已运行则退出
if( FindWindow(NULL,"KissMe,Darling!")) exit(0); TransparentWnd* pFrame = new TransparentWnd;
m_pMainWnd = pFrame;
// create and load the frame with its resources
CRect rect(0, 0, 100, 100);
pFrame->CreateTransparent("KissMe,Darling!", rect);//IDB_MASK, IDB_BACK);
pFrame->CenterWindow(); //初始显示窗体位置
pFrame->ShowWindow(SW_SHOW);
return TRUE;
}