ScreenBase实现屏幕任意区域的截取
//========================================================================//TITLE:// ScreenBase
实现屏幕任意区域的截取
//AUTHOR:// norains//DATE:// Tuesday 16-January -2007//Environment:// EVC4.0 + Standard SDK//========================================================================
1.ScreenBase
源码
ScreenBase
为自己写代码方便而封装的一个
API
类
,
该类的的主要功能是截取屏幕任意区域的图像
,
并将之保存为
BMP
文件
.
源代码如下
:
/**/// // ScreenBase.h: interface for the CScreenBase class./**///#ifndef SCREENBASE_H#define SCREENBASE_H//-------------------------------------------------------------------class CScreenBase ...{public: void CopyScreen(); void SaveFile(TCHAR *pszPath); CScreenBase(); virtual ~CScreenBase(); void Initialize(const RECT *prcScr = NULL);protected: void Destroy(); typedef struct ...{ HDC hDC; //The DC save the screed DC HGDIOBJ hOldSel; //The old object of save DC HBITMAP hBmpSel; //The selected bitmap }SAVEDCINFO,*LPSAVEDCINFO; SAVEDCINFO m_SaveDCInfo; typedef struct ...{ BYTE *lpBitmapBits; //Pointer to a variable that receives a pointer to the location of the device-independent bitmap's bit values BITMAPINFO bitMapInfo; //The savebitmap info }SAVEBITMAPINFO,*LPSAVEBITMAPINFO; SAVEBITMAPINFO m_SaveBitmapInfo; void SaveFile(LPSAVEBITMAPINFO lpSaveBitmapInfo,TCHAR *pszPath); void InitializeSaveDC(LPSAVEDCINFO lpSaveDCInfo,LPSAVEBITMAPINFO lpSaveBitmapInfo,const RECT *prcSave); void DestroySaveDC(LPSAVEDCINFO lpSaveDCInfo,LPSAVEBITMAPINFO lpSaveBitmapInfo); void CopyScreenDC(HDC *pHdcDest,const LPSAVEBITMAPINFO lpSaveBitmapInfo,const RECT *prcSrc); RECT m_rcSave; //The area for saving HDC m_hScrDC; //The handle DC of screen};//--------------------------------------------------------------------------#endif // !defined SCREENBASE_H
/**///// ScreenBase.cpp: implementation of the CScreenBase class./**///#include "stdafx.h"#include "ScreenBase.h"/**///// Construction/Destruction/**///CScreenBase::CScreenBase()...{ memset(&m_rcSave,0,sizeof(m_rcSave)); m_hScrDC = NULL;}CScreenBase::~CScreenBase()...{ Destroy();}//----------------------------------------------------------------------//Description:// Destroy the save DC//--------------------------------------------------------------------void CScreenBase::DestroySaveDC(LPSAVEDCINFO lpSaveDCInfo, LPSAVEBITMAPINFO lpSaveBitmapInfo)...{ if(lpSaveDCInfo->hDC != NULL && lpSaveDCInfo->hOldSel != NULL) ...{ SelectObject(lpSaveDCInfo->hDC, lpSaveDCInfo->hOldSel); } if(lpSaveDCInfo->hDC != NULL) ...{ DeleteDC(lpSaveDCInfo->hDC); } if(lpSaveDCInfo->hBmpSel != NULL) ...{ DeleteObject(lpSaveDCInfo->hBmpSel); } memset(lpSaveDCInfo,0,sizeof(SAVEDCINFO)); memset(lpSaveBitmapInfo,0,sizeof(SAVEBITMAPINFO));}//----------------------------------------------------------------------//Description:// Initialize the save DC//--------------------------------------------------------------------void CScreenBase::InitializeSaveDC(LPSAVEDCINFO lpSaveDCInfo, LPSAVEBITMAPINFO lpSaveBitmapInfo,const RECT *prcSave)...{ //the pointer will save all pixel point's color value lpSaveBitmapInfo->lpBitmapBits = NULL; //creates a memory device context (DC) compatible with the screen device(hScrDC) lpSaveDCInfo->hDC = CreateCompatibleDC(m_hScrDC); //Initialise the struct BITMAPINFO for the bimap infomation
,
//in order to use the function CreateDIBSection on wince os, //each pixel stored by 24 bits(biBitCount=24) and no compressing(biCompression=0)
ZeroMemory(&m_SaveBitmapInfo.bitMapInfo,
sizeof
(BITMAPINFO)); lpSaveBitmapInfo->bitMapInfo.bmiHeader.biSize =
sizeof
(BITMAPINFOHEADER); lpSaveBitmapInfo->bitMapInfo.bmiHeader.biWidth = prcSave->right - prcSave->left; lpSaveBitmapInfo->bitMapInfo.bmiHeader.biHeight = prcSave->bottom - prcSave->top; lpSaveBitmapInfo->bitMapInfo.bmiHeader.biPlanes = 1; lpSaveBitmapInfo->bitMapInfo.bmiHeader.biBitCount = 24;
//use the function CreateDIBSection and SelectObject in order to get the bimap pointer : lpBitmapBits
lpSaveDCInfo->hBmpSel = CreateDIBSection(lpSaveDCInfo->hDC, &lpSaveBitmapInfo->bitMapInfo, DIB_RGB_COLORS, (
void
**)&lpSaveBitmapInfo->lpBitmapBits, NULL, 0); lpSaveDCInfo->hOldSel = SelectObject(lpSaveDCInfo->hDC, lpSaveDCInfo->hBmpSel);}
//----------------------------------------------------------------------//Description:// Save the bitmap of save dc to the file//--------------------------------------------------------------------
void
CScreenBase::SaveFile(LPSAVEBITMAPINFO lpSaveBitmapInfo, TCHAR *pszPath)
...
{
int
iWidth = lpSaveBitmapInfo->bitMapInfo.bmiHeader.biWidth;
int
iHeight = lpSaveBitmapInfo->bitMapInfo.bmiHeader.biHeight;
//If you only want to get the every pixel color value, //you can begin here and the following part of this function will be unuseful; //the following part is in order to write file; //Bimap file header in order to write bmp file
BITMAPFILEHEADER bmBITMAPFILEHEADER; ZeroMemory(&bmBITMAPFILEHEADER,
sizeof
(BITMAPFILEHEADER)); bmBITMAPFILEHEADER.bfType = 0x4d42;
//bmp
bmBITMAPFILEHEADER.bfOffBits =
sizeof
(BITMAPFILEHEADER) +
sizeof
(BITMAPINFOHEADER); bmBITMAPFILEHEADER.bfSize = bmBITMAPFILEHEADER.bfOffBits + ((iWidth * iHeight) * 3);
/**/
///
norains:3=(24 / 8)
//write into file FILE *mStream = NULL; if((mStream = _tfopen(pszPath, TEXT("wb")))) ...{ //write bitmap file header fwrite(&bmBITMAPFILEHEADER, sizeof(BITMAPFILEHEADER), 1, mStream); //write bitmap info fwrite(&(lpSaveBitmapInfo->bitMapInfo.bmiHeader), sizeof(BITMAPINFOHEADER), 1, mStream); //write bitmap pixels data fwrite(lpSaveBitmapInfo->lpBitmapBits, 3*iWidth*iHeight, 1, mStream); //close file fclose(mStream); }}
//----------------------------------------------------------------------//Description:// Copy the screen DC to the dest DC//--------------------------------------------------------------------
void
CScreenBase::CopyScreenDC(HDC *pHdcDest,
const
LPSAVEBITMAPINFO lpSaveBitmapInfo,
const
RECT *prcSrc)
...
{
// copy the screen dc to the memory dc
BitBlt(*pHdcDest, 0, 0, lpSaveBitmapInfo->bitMapInfo.bmiHeader.biWidth, lpSaveBitmapInfo->bitMapInfo.bmiHeader.biHeight, m_hScrDC, prcSrc->left, prcSrc->top, SRCCOPY);}
//----------------------------------------------------------------------//Description:// Initialize the instance//--------------------------------------------------------------------
void
CScreenBase::Initialize(
const
RECT *prcScr)
...
{ Destroy();
//creates a device context for the screen device
m_hScrDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
if
(prcScr != NULL)
...
{ m_rcSave = *prcScr; }
else
...
{
//Get the full window
int
iWidth = GetDeviceCaps(m_hScrDC, HORZRES);
int
iHeight = GetDeviceCaps(m_hScrDC, VERTRES); m_rcSave.left = 0; m_rcSave.top = 0; m_rcSave.bottom = iHeight; m_rcSave.right = iWidth; } InitializeSaveDC(&m_SaveDCInfo,&m_SaveBitmapInfo,&m_rcSave);}
//----------------------------------------------------------------------//Description:// Destroy all the resource//--------------------------------------------------------------------
void
CScreenBase::Destroy()
...
{
if
(m_hScrDC != NULL)
...
{ DeleteDC(m_hScrDC); m_hScrDC = NULL; } DestroySaveDC(&m_SaveDCInfo,&m_SaveBitmapInfo);}
//----------------------------------------------------------------------//Description:// Save the bitmap of screen to the file//--------------------------------------------------------------------
void
CScreenBase::SaveFile(TCHAR *pszPath)
...
{ SaveFile(&m_SaveBitmapInfo,pszPath);}
//----------------------------------------------------------------------//Description:// Copy the screen to the save DC//--------------------------------------------------------------------
void
CScreenBase::CopyScreen()
...
{ CopyScreenDC(&m_SaveDCInfo.hDC,&m_SaveBitmapInfo,&m_rcSave);}
2.
如何截取屏幕
采用
CScreenBase
类截取全屏非常简单
:
首先声明一个
CScreenBase
类对象
:
CScreenBase scrBase;
接着便是初始化
:
scrBase.Initialize();
拷贝屏幕图像
:
scrBase.CopyScreen();
最后
,
把截屏保存到文件中
:
scrBase.SaveFile(TEXT("Capture.bmp"));
如果是截取屏幕的某个区域
,
需要在初始化的时候确定区域
.
例如
,
我们需要截取屏幕上以
(20,20)
为起点
,
对角为
(50,60)
的区域
,
只需更改初始化代码即可
:
RECT rcWnd = ...{20,20,50,60}; scrBase.Initialize(&rcWnd);
3.
进阶用法
:
将截取的区域直接显示到屏幕
因为
CScreenBase
类本意是作为一个截图的基本类
,
所以没有封装直接显示到屏幕的方法
.
不过
,
我们可以继承该类
,
然后返回保存区域图片的句柄
,
最后将其显示于屏幕即可
.
派生一个
ScreenPro
类
,
用来返回所需的句柄
.
class ScreenPro: public CScreenBase ...{ public: HDC GetSaveDC()...{return m_SaveDCInfo.hDC;}; RECT GetSaveRect()...{return m_rcSave;}; };
最后我们只需在
WM_PAINT
消息相应函数将保存的区域像素绘制出来即可
:
//---------------------------------------------------------------------- //Description: // On message WM_PAINT //-------------------------------------------------------------------- void OnPaint(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) ...{ if(m_bScrCapture == TRUE) ...{ //
如果已经截屏
,
则将其显示于屏幕上
PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd,&ps);
//
获取截屏的区域
RECT rcWnd ; rcWnd = m_ScrCapture.GetSaveRect();
//
获取截屏数据保存的
DC
HDC hSaveDC = NULL; hSaveDC = m_ScrCapture.GetSaveDC();
//
绘制到屏幕
BitBlt(hdc,rcWnd.left,rcWnd.top,rcWnd.right,rcWnd.bottom,hSaveDC,0,0,SRCCOPY); EndPaint(hWnd,&ps); }
else
...
{ DefWindowProc(hWnd,wMsg,wParam,lParam); } }
转载请注明原文地址: https://ibbs.8miu.com/read-24523.html