📄 canvas.cpp
字号:
#include "StdAfx.h"
#include "Canvas.h"
#include "resourcesp.h"
CCanvas::CCanvas(void)
{
m_pAnimation=NULL;
m_CurrentLoop=0;
m_CurrentImage=0;
m_bAnimationPlaying=false;
m_vecSM.clear();
InitializeCriticalSection(&m_CriticalSection);
m_arrVisibleBmp.clear();
memset( m_arrItemRect,0,CANVAS_LINE*CANVAS_ROW*sizeof(RECT));
m_hDefaultBitmap = NULL;
}
CCanvas::~CCanvas(void)
{
std::vector<CShortcutManager*>::iterator it;
for(it = m_vecSM.begin();it!=m_vecSM.end();it++)
{
delete (*it);
*it = NULL;
}
m_vecSM.clear();
std::vector<HBITMAP>::iterator itt;
for(itt = m_arrVisibleBmp.begin();itt!=m_arrVisibleBmp.end();itt++)
{
DeleteObject(*itt);
*itt = NULL;
}
m_arrVisibleBmp.clear();
Stop();
}
BEGIN_MESSAGE_MAP(CCanvas, CStatic)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CCanvas::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
m_pMemDC = &dc;
CDC memDC;
CBitmap bmpCanvas;
CBitmap*pOldBitmap;
// bmpCanvas.CreateCompatibleBitmap(&dc,m_rcCanvas.Width(),m_rcCanvas.Height());
//画背景图
memDC.CreateCompatibleDC(&dc);
HBITMAP hBmpBk = (HBITMAP)SHLoadDIBitmap(m_sBkBmpPath);
bmpCanvas.Attach(hBmpBk);
pOldBitmap = memDC.SelectObject(&bmpCanvas);
DrawShortcutItem(memDC);
dc.BitBlt(m_rcCanvas.left,m_rcCanvas.top,m_rcCanvas.Width(),m_rcCanvas.Height(),&memDC,0,0,SRCCOPY);
memDC.SelectObject(pOldBitmap);
memDC.DeleteDC();
bmpCanvas.Detach();
DeleteObject(hBmpBk);
CString ss = m_smCurrent->GetSelected()->GetTitle();
if(ss.GetLength()>0)
AfxGetMainWnd()->SetWindowText(ss);
// dc.DrawText(_T("good morning!"),20,&rc,DT_CENTER | DT_VCENTER | DT_SINGLELINE);
// Do not call CStatic::OnPaint() for painting messages
}
void CCanvas::DrawShortcutItem(CDC &dc)
{
CShortcutItem *pItem = NULL;
for(int i =0;i<CANVAS_LINE;i++)
{
for(int j = 0;j<CANVAS_ROW;j++)
{
pItem = m_smCurrent->GetFromVisibleAt(i*CANVAS_ROW+j);
if(pItem)
{
HBITMAP hBmp = NULL;
BITMAP bm;
if(i*CANVAS_ROW+j == m_smCurrent->GetSelectedNumber()-1)
{
EnterCriticalSection(&m_CriticalSection);
C_Image* & current = m_pAnimation->img[m_CurrentImage];
LeaveCriticalSection(&m_CriticalSection);
CDC SrcDC;
SrcDC.CreateCompatibleDC(&dc);
void *ppvbits;
hBmp=CreateDIBSection(dc.GetSafeHdc(),current->pbmi,DIB_RGB_COLORS,(void**)&ppvbits,NULL,NULL);
if(hBmp!=NULL)
{
HBITMAP hOld = (HBITMAP)SrcDC.SelectObject(hBmp);
// ::GetObject(hBmp,sizeof(BITMAP),&bm);
int iItemW = m_arrItemRect[i][j].right - m_arrItemRect[i][j].left;
int iItemH = m_arrItemRect[i][j].bottom - m_arrItemRect[i][j].top;
// int iLeft = m_arrItemRect[i][j].left+(iItemW - current->Width)/2;
// int iTop = m_arrItemRect[i][j].top+(iItemH - current->Height)/2;
// int iWidth = current->Width<iItemW?current->Width:iItemW;
// int iHeight = current->Height<iItemH?current->Height:iItemH;
SetDIBitsToDevice (SrcDC.GetSafeHdc(),0,0,
current->Width,current->Height,0,0,0,current->Height,
(LPVOID)current->Raster,current->pbmi,0);
//定义源、掩码、透明绘制环境
CDC MaskDC,TransDC;
//定义掩码、透明位图
HBITMAP hMaskBmp,hTransBmp;
// BITMAP bm;
//创建源、掩码、透明绘制环境
MaskDC.CreateCompatibleDC(&dc);
TransDC.CreateCompatibleDC(&dc);
//创建透明位图
hTransBmp = CreateCompatibleBitmap(dc.GetSafeHdc(),current->Width,current->Height);
//创建掩码位图
hMaskBmp=CreateBitmap(current->Width,current->Height,1,1,NULL);
//将透明位图对象选入到透明绘图环境
HBITMAP hOldTransBmp = (HBITMAP)TransDC.SelectObject(hTransBmp);
//将目标位图绘制到透明位图中
TransDC.BitBlt(0,0,current->Width,current->Height,&dc,
m_arrItemRect[i][j].left+current->xPos,
m_arrItemRect[i][j].top+current->yPos,SRCCOPY);
//设置背景为透明模式
SrcDC.SetBkMode(TRANSPARENT);
//设置背景色
if (current->Transparent)
SrcDC.SetBkColor(current->Transparent);
else
{
COLORREF col = SrcDC.GetPixel(0,current->Height-1);
SrcDC.SetBkColor(col);
}
HBITMAP hOldMaskBmp = (HBITMAP)MaskDC.SelectObject(hMaskBmp);
//将源绘图环境绘制到掩码绘图环境中
MaskDC.BitBlt(0,0,current->Width,current->Height,&SrcDC,0,0,SRCCOPY);
//将源位图和透明位图进行异或操作融合
TransDC.BitBlt(0,0,current->Width,current->Height,&SrcDC,0,0,SRCINVERT);
//将透明位图和掩码位图进行与操作
TransDC.BitBlt(0,0,current->Width,current->Height,&MaskDC,0,0,SRCAND);
//再将源位图和透明位图进行异或操作
TransDC.BitBlt(0,0,current->Width,current->Height,&SrcDC,0,0,SRCINVERT);
//此时将透明位图绘制到目标设备上
dc.BitBlt(m_arrItemRect[i][j].left+current->xPos,
m_arrItemRect[i][j].top+current->yPos,
current->Width,current->Height,&TransDC,
0,
0,SRCCOPY);
//绘制绘图对象,并释放相应绘图环境和位图对象
SrcDC.SelectObject(hOld);
SrcDC.DeleteDC();
DeleteObject(hBmp);
TransDC.SelectObject(hOldTransBmp);
DeleteObject(hTransBmp);
TransDC.DeleteDC();
MaskDC.SelectObject(hOldMaskBmp);
MaskDC.DeleteDC();
DeleteObject(hMaskBmp);
}
}
else
{
hBmp = m_arrVisibleBmp[i*CANVAS_ROW+j];
CBitmap bmp;
bmp.Attach(hBmp);
bmp.GetBitmap(&bm);
bmp.Detach();
int iItemW = m_arrItemRect[i][j].right - m_arrItemRect[i][j].left;
int iItemH = m_arrItemRect[i][j].bottom - m_arrItemRect[i][j].top;
int iLeft = m_arrItemRect[i][j].left+(iItemW - bm.bmWidth)/2;
int iTop = m_arrItemRect[i][j].top+(iItemH - bm.bmHeight)/2;
int iWidth = bm.bmWidth<iItemW?bm.bmWidth:iItemW;
int iHeight = bm.bmHeight<iItemH?bm.bmHeight:iItemH;
TransparentImage(dc.m_hDC,iLeft,iTop,iWidth,iHeight,hBmp,0,0,bm.bmWidth,bm.bmHeight,0xD4D0C8);/*0xBGR*/
}
}
else
break;
}
}
}
//画透明图片
void CCanvas::DrawTransParent(HBITMAP hBmp,int const x,int const y,int const cx,int const cy,
int const srcx,int const srcy,CDC *pDC,COLORREF TransparentColor)
{
//定义源、掩码、透明绘制环境
CDC SrcDC,MaskDC,TransDC;
//定义掩码、透明位图
HBITMAP hMaskBmp,hTransBmp;
BITMAP bm;
//创建源、掩码、透明绘制环境
SrcDC.CreateCompatibleDC(pDC);
MaskDC.CreateCompatibleDC(pDC);
TransDC.CreateCompatibleDC(pDC);
//得到位图结构
CBitmap bmp;
bmp.Attach(hBmp);
bmp.GetBitmap(&bm);
bmp.Detach();
//创建透明位图
hTransBmp = CreateCompatibleBitmap(pDC->m_hDC,cx,cy);
//创建掩码位图
hMaskBmp=CreateBitmap(cx,cy,1,1,NULL);
//将透明位图对象选入到透明绘图环境
HBITMAP hOldTransBmp = (HBITMAP)TransDC.SelectObject(hTransBmp);
//将目标位图绘制到透明位图中
TransDC.BitBlt(0,0,cx,cy,pDC,srcx,srcy,SRCCOPY);
//将实际位图对象选入源绘图环境
HBITMAP hSrcBmp = (HBITMAP)SrcDC.SelectObject(hBmp);
//设置背景为透明模式
SrcDC.SetBkMode(TRANSPARENT);
//设置背景色
if (TransparentColor)
SrcDC.SetBkColor(TransparentColor);
else
{
COLORREF col = SrcDC.GetPixel(0,bm.bmHeight-1);
SrcDC.SetBkColor(col);
}
HBITMAP hOldMaskBmp = (HBITMAP)MaskDC.SelectObject(hMaskBmp);
//将源绘图环境绘制到掩码绘图环境中
MaskDC.BitBlt(0,0,cx,cy,&SrcDC,0,0,SRCCOPY);
//将源位图和透明位图进行异或操作融合
TransDC.BitBlt(0,0,cx,cy,&SrcDC,0,0,SRCINVERT);
//将透明位图和掩码位图进行与操作
TransDC.BitBlt(0,0,cx,cy,&MaskDC,0,0,SRCAND);
//再将源位图和透明位图进行异或操作
TransDC.BitBlt(0,0,cx,cy,&SrcDC,0,0,SRCINVERT);
//此时将透明位图绘制到目标设备上
BOOL bRet = pDC->BitBlt(x,y,cx,cy,&TransDC,0,0,SRCCOPY);
//绘制绘图对象,并释放相应绘图环境和位图对象
SrcDC.SelectObject(hSrcBmp);
SrcDC.DeleteDC();
TransDC.SelectObject(hOldTransBmp);
DeleteObject(hTransBmp);
TransDC.DeleteDC();
MaskDC.SelectObject(hOldMaskBmp);
MaskDC.DeleteDC();
DeleteObject(hMaskBmp);
}
int CCanvas::LoadAnimatedGif(LPTSTR FileName)
{
Stop();
EnterCriticalSection(&m_CriticalSection);
m_AnimGif.Reset();
m_pAnimation = NULL;
#ifdef _UNICODE
char szTemp[MAX_PATH] = {0};
WideCharToMultiByte(CP_ACP,0,FileName,_tcslen(FileName),szTemp,_tcslen(FileName),NULL,false);
int Result=m_AnimGif.LoadGIF(szTemp);
#else
int Result=m_AnimGif.LoadGIF(FileName);
#endif
m_pAnimation=&m_AnimGif;
LeaveCriticalSection(&m_CriticalSection);
Play();
return Result;
}
// fnThread: Thread function in charge of looping animation frames.
DWORD WINAPI CCanvas::fnThread (LPVOID lpParameter)
{
do
{
Sleep(10);
CCanvas* window;
C_ImageSet* anim;
window=(CCanvas*) lpParameter;
if(window->m_pAnimation==NULL)
{
continue;
}
anim=window->m_pAnimation;
window->m_bAnimationPlaying=TRUE;
while ( anim->nLoops ? window->m_CurrentLoop < anim->nLoops : true )
{
while (1)
{
//window->DrawGif();
::InvalidateRect(window->m_hWnd,NULL,FALSE);
window->EnterCriticalSec();
C_Image* & image = anim->img[window->m_CurrentImage];
int iDelay = image->Delay?image->Delay:100;
window->LeaveCriticalSec();
if (window->m_CurrentImage < anim->nImages-1)
++window->m_CurrentImage;
else
{
window->Rewind();
// window->m_CurrentImage=0;
// break;
}
Sleep (iDelay);
// CurrentImage must always be valid!
}
++window->m_CurrentLoop;
}
window->Rewind();
window->m_bAnimationPlaying=FALSE;
}while(1);
return 0;
}
// Play: Start/Resume animation loop
void CCanvas::Play ()
{
if (!m_bAnimationPlaying)
if (m_pAnimation->nImages > 1)
m_hThreadAnim = CreateThread(NULL,0,fnThread,this,0,&m_dwThreadIdAnim);
}
// Stop: Stop animation loop
void CCanvas::Stop ()
{
if (m_bAnimationPlaying)
{
TerminateThread(m_hThreadAnim,0);
Rewind();
m_bAnimationPlaying=FALSE;
}
}
// Rewind: Reset animation loop to its initial values
void CCanvas::Rewind ()
{
m_CurrentLoop=0;
m_CurrentImage=0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -