www.gusucode.com > VC++指定区域抓图、截屏小程序-源码程序 > VC++指定区域抓图、截屏小程序-源码程序/code/ImageView.cpp

    //Download by http://www.NewXing.com
/*
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	文件:ImageView.cpp	类CImageView的执行文件

	版权:Firebird Software Workroom 保留

	声明:本源程序的版权受《中华人民共和国著作权法》以及其
		  它相关法律和条约的保护。任何有机会得到本源程序的
		  个人和机构,未经作者明确授权,不得将本源程序用于
		  任何商业目的(直接的或间接的)。对于非商业目的的使
		  用 (包括复制、传播、编译和修改), 原则上没有特别
		  的限制条款,但请在相关文档中说明其来源,并尊重原
		  作者的署名权。

	编写:秦传安(chings)	2000.5

	联络:Tel:(0792)6323086	E_mail:chings@163.net
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
#include "fclstd.h"
#include "resource.h"
#include "ScreenCap.h"
#include "stdio.h"
#include "ImageView.h"
//#####################################################################
#define DIBSCANLINE_WIDTHBYTES(bits)    (((bits)+31)/32*4)
//#####################################################################
HCURSOR CImageView::m_hDownCur = NULL;
HCURSOR CImageView::m_hUpCur = NULL;
HCURSOR CImageView::m_hSelCur = LoadCursor(NULL,IDC_CROSS);
//#####################################################################
CImageView::CImageView()
{
	m_bMouseDown	= FALSE;
	m_bCanMove		= FALSE;
	m_bCanSel		= FALSE;

	SetRectEmpty(&m_rcSel);

	if(!m_hDownCur)
		m_hDownCur = LoadCursor(GetApp()->m_hInstance,MAKEINTRESOURCE(IDC_MOVE_DOWN));
	if(!m_hUpCur)
		m_hUpCur = LoadCursor(GetApp()->m_hInstance,MAKEINTRESOURCE(IDC_MOVE_UP));

	memset(&m_ImgInfo,0,sizeof(IMAGE_INFO));
}

CImageView::~CImageView()
{
	if(m_ImgInfo.hBmp)
		DeleteObject(m_ImgInfo.hBmp);
}
//####################################################################
LRESULT CImageView::WindowProc(UINT msg,WPARAM wParam,LPARAM lParam)
{
	LRESULT lResult = 0;

	switch(msg)
	{
	case WM_LBUTTONDOWN:
		{
			POINT pt;
			pt.x = LOWORD(lParam);
			pt.y = HIWORD(lParam);
			OnLButtonDown(pt,(UINT)wParam);
		}
		break;
	case WM_LBUTTONUP:
		if(m_bCanSel)
		{
			ReleaseCapture();
			if(!IsRectEmpty(&m_rcSel))
				SendMessage(m_pOwner->m_hWnd,FBWM_NOTIFY,MAKEWPARAM(GetWndID(),FB_IVN_SELECTED),0);
		}
		if(m_bCanMove)
		{
			m_bMouseDown = FALSE;
			OnSetCursor();
		}
		break;
	case WM_MOUSEMOVE:
		{
			POINT pt;
			pt.x = LOWORD(lParam);
			pt.y = HIWORD(lParam);
			OnMouseMove(pt,(UINT)wParam);
		}
		break;
	case WM_SIZE:
		CalcSize();
		Invalidate(TRUE);
		break;
	case WM_SETCURSOR:
		if(!OnSetCursor())
			lResult = DefWindowProc(m_hWnd,msg,wParam,lParam);
		break;
	case WM_RBUTTONUP:
		{
			HMENU hMenu = LoadMenu(GetInstance(),MAKEINTRESOURCE(IDR_CONTEXT));
			HMENU hSub = GetSubMenu(hMenu,0);
			POINT pt;
			pt.x = LOWORD(lParam);
			pt.y = HIWORD(lParam);
			ClientToScreen(m_hWnd,&pt);
			TrackPopupMenu(hSub,TPM_LEFTALIGN|TPM_LEFTBUTTON
						   |TPM_RIGHTBUTTON,pt.x,pt.y,
						   0,m_pOwner->m_hWnd,NULL);
		}
		break;
    default:
		lResult = CFBView::WindowProc(msg,wParam,lParam);
		break;
	}

	return lResult;
}
//#####################################################################
BOOL CImageView::LoadFromHandle(HBITMAP hBmp)
{
	if(!hBmp)return FALSE;

	if(m_ImgInfo.hBmp)
	{
		DeleteObject(m_ImgInfo.hBmp);
		m_ImgInfo.hBmp = NULL;
	}

	m_ImgInfo.hBmp = hBmp;

	BITMAP bmp;
	GetObject(m_ImgInfo.hBmp,sizeof(BITMAP),&bmp);
	m_ImgInfo.cx = bmp.bmWidth;
	m_ImgInfo.cy = bmp.bmHeight;
	m_ImgInfo.nPixelFmt = bmp.bmBitsPixel;

	m_xSrc = m_ySrc = 0;
	CalcSize();

	return TRUE;
}
//#####################################################################
BOOL CImageView::LoadFormBMPFile(LPTSTR szFileName)
{
	HBITMAP hBmp = (HBITMAP)LoadImage(NULL,szFileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
	return LoadFromHandle(hBmp);
}
//#####################################################################
void CImageView::SetEmpty()
{
	if(m_ImgInfo.hBmp)
		DeleteObject(m_ImgInfo.hBmp);

	memset(&m_ImgInfo,0,sizeof(IMAGE_INFO));
	SetRectEmpty(&m_rcDest);
	Invalidate();
}
//#####################################################################
BOOL CImageView::Draw()
{
	if(m_ImgInfo.hBmp == NULL)
		return FALSE;

	HDC hdc = GetDC(m_hWnd);
	HDC hBmpDC = CreateCompatibleDC(hdc);
	SelectObject(hBmpDC,m_ImgInfo.hBmp);

	BitBlt(hdc,m_rcDest.left,m_rcDest.top,m_rcDest.right - m_rcDest.left,
		   m_rcDest.bottom - m_rcDest.top,hBmpDC,m_xSrc,m_ySrc,SRCCOPY);

	if(m_bCanSel && !IsRectEmpty(&m_rcSel))
		DrawFocusRect(hdc,&m_rcSel);

	DeleteDC(hBmpDC);
	ReleaseDC(m_hWnd,hdc);

	return TRUE;
}
//#####################################################################
BOOL CImageView::Crop()
{
	if(!m_ImgInfo.hBmp || IsRectEmpty(&m_rcSel))
		return FALSE;

	HDC hDC = GetDC(m_hWnd);
	HDC hBmpDC = CreateCompatibleDC(hDC);
	HDC hImgDC = CreateCompatibleDC(hDC);
	if(!hBmpDC || !hImgDC)
		return FALSE;

	HBITMAP hBmp = CreateCompatibleBitmap(hDC,m_rcSel.right - m_rcSel.left,
										  m_rcSel.bottom - m_rcSel.top);
	if(!hBmp)
	{
		DeleteDC(hBmpDC);
		DeleteDC(hImgDC);
		return FALSE;
	}

	SelectObject(hBmpDC,hBmp);
	SelectObject(hImgDC,m_ImgInfo.hBmp);

	int x = m_rcSel.left + m_xSrc - m_rcDest.left;
	int y = m_rcSel.top + m_ySrc - m_rcDest.top;
	BitBlt(hBmpDC,0,0,m_rcSel.right - m_rcSel.left,
		   m_rcSel.bottom - m_rcSel.top,hImgDC,x,
		   y,SRCCOPY);

	LoadFromHandle(hBmp);
	DeleteDC(hBmpDC);
	DeleteDC(hImgDC);
	ReleaseDC(m_hWnd,hDC);

	SetRectEmpty(&m_rcSel);
	CalcSize();
	Invalidate();

	return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
void CImageView::CalcSize()
{
	if(m_ImgInfo.hBmp == NULL)return;

	RECT rc;
	GetClientRect(m_hWnd,&rc);
	int cx = rc.right - rc.left;
	int cy = rc.bottom - rc.top;

	if(cx == 0 || cy == 0)return;

	if(m_ImgInfo.cx < cx)
	{
		m_rcDest.left = (int)(cx - m_ImgInfo.cx)/2;
		m_rcDest.right = m_rcDest.left + m_ImgInfo.cx;
		m_xFlag = FALSE;
	}
	else
	{
		m_rcDest.left = rc.left;
		m_rcDest.right = rc.right;
		if(m_ImgInfo.cx == cx)
			m_xFlag = FALSE;
		else
			m_xFlag = TRUE;
	}

	if(m_ImgInfo.cy < cy)
	{
		m_rcDest.top = (int)(cy - m_ImgInfo.cy)/2;
		m_rcDest.bottom = m_rcDest.top + m_ImgInfo.cy;
		m_yFlag = FALSE;
	}
	else
	{
		m_rcDest.top = rc.top;
		m_rcDest.bottom = rc.bottom;
		if(m_ImgInfo.cy == cy)
			m_yFlag = FALSE;
		else
			m_yFlag = TRUE;
	}

	if(m_xFlag)
	{
		if(m_xSrc < 0)
			m_xSrc = 0;
		if(m_xSrc > (m_ImgInfo.cx - m_rcDest.right))
			m_xSrc = m_ImgInfo.cx - m_rcDest.right;
	}
	if(m_yFlag)
	{
		if(m_ySrc < 0)
			m_ySrc = 0;
		if(m_ySrc > (m_ImgInfo.cy - m_rcDest.bottom))
			m_ySrc = m_ImgInfo.cy - m_rcDest.bottom;
	}

	if(m_xFlag || m_yFlag)
		m_bCanMove = TRUE;
	else
		m_bCanMove = FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
void CImageView::OnDraw(HDC hDC)
{
	CalcSize();
	Draw();
}
//####################################################################
BOOL CImageView::DrawBackground(HDC hDC)
{
	if(m_ImgInfo.hBmp)
		ExcludeClipRect(hDC,m_rcDest.left,m_rcDest.top,m_rcDest.right,m_rcDest.bottom);

	return CFBView::DrawBackground(hDC);
}
//####################################################################
BOOL CImageView::OnSetCursor()
{
	POINT pt;
	GetCursorPos(&pt);
	ScreenToClient(m_hWnd,&pt);

	if(!PtInRect(&m_rcDest,pt))
		return FALSE;

	if(m_bCanSel)
	{
		SetCursor(m_hSelCur);
		return TRUE;
	}

	if(m_bCanMove)
	{
		if(m_bMouseDown)
			SetCursor(m_hDownCur);
		else
			SetCursor(m_hUpCur);

		return TRUE;
	}

	return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////
void CImageView::OnLButtonDown(POINT &pt,UINT key)
{
	if(m_bCanSel && !IsRectEmpty(&m_rcSel))
	{
		HDC hdc = GetDC(m_hWnd);
		DrawFocusRect(hdc,&m_rcSel);
		ReleaseDC(m_hWnd,hdc);
		SetRectEmpty(&m_rcSel);
	}

	if(PtInRect(&m_rcDest,pt))
	{
		m_bMouseDown = TRUE;
		m_ptBegin.x = pt.x;
		m_ptBegin.y = pt.y;

		if(m_bCanSel)
		{
			m_rcSel.left = m_rcSel.right = pt.x;
			m_rcSel.top = m_rcSel.bottom = pt.y;
			SetCapture(m_hWnd);
		}
		else
			OnSetCursor();
	}
}
////////////////////////////////////////////////////////////////////////////////////
void CImageView::OnMouseMove(POINT &pt,UINT key)
{
	BOOL bxMove,byMove;

	if(key == MK_LBUTTON && m_bCanSel)
	{
		HDC hdc = GetDC(m_hWnd);

		DrawFocusRect(hdc,&m_rcSel);

		m_rcSel.left = max(min(m_ptBegin.x,pt.x),m_rcDest.left);
		m_rcSel.top = max(min(m_ptBegin.y,pt.y),m_rcDest.top);
		m_rcSel.right = min(max(m_ptBegin.x,pt.x),m_rcDest.right);
		m_rcSel.bottom = min(max(m_ptBegin.y,pt.y),m_rcDest.bottom);

		DrawFocusRect(hdc,&m_rcSel);
		ReleaseDC(m_hWnd,hdc);
	}

	else if(key == MK_LBUTTON && m_bCanMove)
	{

		if(m_xFlag)
		{
			m_xSrc -= pt.x - m_ptBegin.x;
			m_ptBegin.x = pt.x;

			if(m_xSrc <0 )
			{
				m_xSrc = 0;
				bxMove = FALSE;
			}
			else if((m_xSrc + m_rcDest.right) > m_ImgInfo.cx)
			{
				m_xSrc =m_ImgInfo.cx - m_rcDest.right;
				bxMove = FALSE;
			}
			else
				bxMove = TRUE;
		}

		if(m_yFlag)
		{
			m_ySrc -= pt.y - m_ptBegin.y;
			m_ptBegin.y = pt.y;

			if(m_ySrc < 0)
			{
				m_ySrc = 0;
				byMove = FALSE;
			}
			else if((m_ySrc + m_rcDest.bottom) > m_ImgInfo.cy)
			{
				m_ySrc = m_ImgInfo.cy - m_rcDest.bottom;
				byMove = FALSE;
			}
			else
				byMove = FALSE;
		}

		if(bxMove || byMove)
			Draw();
	}
}
//####################################################################
BOOL CImageView::SaveToBMPFile(LPTSTR szFileName)
{
	if(!m_ImgInfo.hBmp || !szFileName)return FALSE;

    FILE*					pFile;	//文件指针
    BITMAPFILEHEADER		hdr;	//文件头
    LPBITMAPINFOHEADER		pbih;	//位图信息头
    LPBYTE					lpBits;	//内存指针 

	LPBITMAPINFO pbi = GetBitmapInfo(m_ImgInfo.hBmp);
	HDC hDC = GetDC(NULL);

    pbih = (LPBITMAPINFOHEADER) pbi;//从BITMAPINFO指针取得BITMAPINFOHEADER指针

	lpBits = new BYTE[pbih->biSizeImage];
    if (!lpBits)
		return FALSE;

    //得到DIB色彩表
    if (!GetDIBits(hDC, m_ImgInfo.hBmp, 0, (WORD) pbih->biHeight, 
                   lpBits, pbi, DIB_RGB_COLORS))
	{
		delete lpBits;
		delete pbih;
		return FALSE;
	}

	pFile = fopen(szFileName, "w+b");

	if(!pFile)
	{
		delete lpBits;
		delete pbih;
		return FALSE;
	}

    hdr.bfType = (WORD)('M'<<8)|'B';    //位图文件头位“BM”
	
	
	//计算整个文件的大小
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                 pbih->biSize + pbih->biClrUsed 
                 * sizeof(RGBQUAD) + pbih->biSizeImage); 
 
    hdr.bfReserved1 = 0;
    hdr.bfReserved2 = 0; 
 
    //计算色彩数据阵列的位移
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                    pbih->biSize + pbih->biClrUsed 
                    * sizeof (RGBQUAD); 
 

    //写入 BITMAPFILEHEADER (位图文件头)
	fseek(pFile,0,SEEK_SET);
	fwrite(&hdr,sizeof(BYTE),sizeof(BITMAPFILEHEADER),pFile);
	//位图信息头
	fwrite(pbih,sizeof(BYTE), sizeof(BITMAPINFOHEADER) 
                  + pbih->biClrUsed * sizeof (RGBQUAD),pFile);
 
    //写入色彩数据阵列
	fwrite(lpBits,sizeof(BYTE),pbih->biSizeImage,pFile);

	fclose(pFile);
	delete lpBits;
	delete pbih;

	return TRUE;
}
//####################################################################
LPBITMAPINFO CImageView::GetBitmapInfo(HBITMAP hBmp)
{
    BITMAP				bmp;//位图对象的BITMAP结构
    LPBITMAPINFO		pbmi;//位图信息结构指针 
	BITMAPINFOHEADER	bmih;//位图信息头结构
	WORD				size;
 
    //得到位图的BITMAP结构
    if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) 
        return NULL;
 
	memset(&bmih,0,sizeof(BITMAPINFOHEADER));
	bmih.biSize = sizeof(BITMAPINFOHEADER);
	bmih.biWidth = bmp.bmWidth;
	bmih.biHeight = bmp.bmHeight;
	bmih.biPlanes = bmp.bmPlanes;
	bmih.biBitCount = bmp.bmBitsPixel;
	if ((bmih.biBitCount==16)||(bmih.biBitCount==32))
		bmih.biCompression = BI_BITFIELDS;
	else
		bmih.biCompression = BI_RGB;
	bmih.biSizeImage = bmp.bmHeight*DIBSCANLINE_WIDTHBYTES(bmp.bmWidth*bmp.bmBitsPixel);

	int cx = GetSystemMetrics(SM_CXSCREEN);
	int cy = GetSystemMetrics(SM_CYSCREEN);
	bmih.biXPelsPerMeter = (cx*1000)/cx;
	bmih.biYPelsPerMeter = (cy*1000)/cy;

	if(bmih.biBitCount == 16 || bmih.biBitCount == 32)
		size = sizeof(DWORD)*3;
	else
		size = sizeof(RGBQUAD)*2^bmih.biBitCount;
	bmih.biClrUsed = 2^bmih.biBitCount;

	pbmi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + size];
	if(!pbmi)
		return NULL;

	memcpy(pbmi,&bmih,sizeof(BITMAPINFOHEADER));

    return pbmi;
}
//###################################################################
HBITMAP CImageView::CopyBitmap(HDC hDC,HBITMAP hBmp)
{
	if(!hBmp || !hDC)
		return NULL;

	BITMAP bmp;
	HBITMAP hBmpDest = NULL;
	HDC hdcDest = NULL,hdcSrc = NULL;

	if(GetObject(hBmp,sizeof(BITMAP),&bmp) == 0)
		return NULL;

	hdcDest = CreateCompatibleDC(hDC);
	hdcSrc = CreateCompatibleDC(hDC);
	hBmpDest = CreateCompatibleBitmap(hDC,bmp.bmWidth,bmp.bmHeight);

	if(!hdcDest || !hdcSrc || !hBmpDest)
		goto Done;

	SelectObject(hdcDest,hBmpDest);
	SelectObject(hdcSrc,hBmp);

	BitBlt(hdcDest,0,0,bmp.bmWidth,bmp.bmHeight,hdcSrc,0,0,SRCCOPY);

Done:
	if(hdcDest)
		DeleteDC(hdcDest);
	if(hdcSrc)
		DeleteDC(hdcSrc);

	return hBmpDest;
}