您的位置:首页 > 其它

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

2007-02-13 11:08 295 查看
 
[align=left] ScreenBase实现屏幕任意区域的截取 [/align]
[align=left]//========================================================================
//TITLE:
//    ScreenBase实现屏幕任意区域的截取
//AUTHOR:
//    norains
//DATE:
//    Tuesday  16-January -2007
//Environment:
//  EVC4.0 + Standard SDK
//========================================================================[/align]
[align=left]1.ScreenBase 源码[/align]
[align=left]  ScreenBase为自己写代码方便而封装的一个API类,该类的的主要功能是截取屏幕任意区域的图像,并将之保存为BMP文件.[/align]
[align=left]  源代码如下:[/align]
[align=left]
/**///////////////////////////////////////////////////////////////////////        
// 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

[/align]
[align=left] [/align]

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

[align=left] [/align]
[align=left]2.如何截取屏幕[/align]
[align=left]  采用CScreenBase类截取全屏非常简单:
  
  首先声明一个CScreenBase类对象: [/align]
[align=left] CScreenBase scrBase;[/align]
[align=left]  接着便是初始化:[/align]
[align=left] scrBase.Initialize();[/align]
[align=left]
  
  拷贝屏幕图像:[/align]
[align=left]  scrBase.CopyScreen();[/align]
[align=left]  
  最后,把截屏保存到文件中:[/align]
[align=left] scrBase.SaveFile(TEXT("Capture.bmp"));[/align]
[align=left] 
  如果是截取屏幕的某个区域,需要在初始化的时候确定区域.
  例如,我们需要截取屏幕上以(20,20)为起点,对角为(50,60)的区域,只需更改初始化代码即可:[/align]
[align=left]  RECT rcWnd = ...{20,20,50,60};
  scrBase.Initialize(&rcWnd);[/align]
[align=left] 
  
  
3.进阶用法:将截取的区域直接显示到屏幕[/align]
[align=left]  因为CScreenBase类本意是作为一个截图的基本类,所以没有封装直接显示到屏幕的方法.不过,我们可以继承该类,然后返回保存区域图片的句柄,最后将其显示于屏幕即可.
  
  派生一个ScreenPro类,用来返回所需的句柄.[/align]
[align=left]        class ScreenPro: public CScreenBase
        ...{
            public:
                HDC GetSaveDC()...{return m_SaveDCInfo.hDC;};
                RECT GetSaveRect()...{return m_rcSave;};
        };[/align]
[align=left]
  最后我们只需在WM_PAINT消息相应函数将保存的区域像素绘制出来即可: [/align]
[align=left]    //----------------------------------------------------------------------
        //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);
            }
        }[/align]

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  null colors struct class byte api