ScreenBase实现屏幕任意区域的截取

    技术2022-05-11  57

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

    最新回复(0)