15,978
社区成员
发帖
与我相关
我的任务
分享
HBITMAP CxScreenShot::CopyScreenToBitmap2()
{
ssScreenDC.clear();
HWND desktop = GetDesktopWindow();
HDC desktopdc = ::GetDC(desktop);
CxRect rcSceen = CxGetAllScreenInfo();
ssScreenDC.hCmpDc = CreateCompatibleDC(desktopdc);
ssScreenDC.hCmpBmp = CreateCompatibleBitmap(desktopdc, rcSceen.Width(), rcSceen.Height());
HBITMAP oldbmp = (HBITMAP)SelectObject(ssScreenDC.hCmpDc, ssScreenDC.hCmpBmp);
BitBlt(ssScreenDC.hCmpDc,0,0,rcSceen.Width(),rcSceen.Height(),desktopdc,rcSceen.left,rcSceen.top, SRCCOPY|CAPTUREBLT);
::ReleaseDC(desktop,desktopdc);
return ssScreenDC.hCmpBmp;
}
// TestCaptureDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "TestCapture.h"
#include "TestCaptureDlg.h"
#include "afxdialogex.h"
#include <gdiplus.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace Gdiplus;
CLSID clsidPng;
int GetCodecClsid(const WCHAR* format,CLSID* pClsid)
{
UINT num=0;
UINT size=0;
ImageCodecInfo* pImageCodecInfo=NULL;
GetImageEncodersSize(&num,&size);
if (size==0) return -1;
pImageCodecInfo=new ImageCodecInfo[size];
if (pImageCodecInfo==NULL)
{
delete[] pImageCodecInfo;
return -1;
}
GetImageEncoders(num,size,pImageCodecInfo);
for (UINT j=0;j<num;j++)
{
if (wcscmp(pImageCodecInfo[j].MimeType,format)==0)
{
*pClsid=pImageCodecInfo[j].Clsid;
delete[] pImageCodecInfo;
return j;
}
}
delete[] pImageCodecInfo;
return -1;
}
// CTestCaptureDlg 对话框
CTestCaptureDlg::CTestCaptureDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_TESTCAPTURE_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTestCaptureDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CTestCaptureDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED (IDOK,&CTestCaptureDlg::OnBnClickedOk)
END_MESSAGE_MAP()
// CTestCaptureDlg 消息处理程序
BOOL CTestCaptureDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
GetCodecClsid(L"image/png",&clsidPng);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CTestCaptureDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CTestCaptureDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CTestCaptureDlg::Capture()
{
//桌面DC
CDC* pDeskDC=GetDesktopWindow()->GetDC();
//屏幕区域
CRect rc;
GetDesktopWindow()->GetClientRect(rc);
//内存DC
CDC memDC;
memDC.CreateCompatibleDC(pDeskDC);
//兼容位图
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDeskDC,rc.Width(),rc.Height());
//选择位图对象
memDC.SelectObject(&bmp);
BITMAP bitmap;
bmp.GetBitmap(&bitmap);
//调色板
int nPanelsize=0;
//判断是否真彩色位图
if (bitmap.bmBitsPixel<16)
nPanelsize=(int)pow((double)2,(int)(bitmap.bmBitsPixel*sizeof(RGBQUAD)));
//截屏
BITMAPINFO *pBInfo=(BITMAPINFO*)LocalAlloc(LPTR,sizeof(BITMAPINFO)+nPanelsize);
pBInfo->bmiHeader.biBitCount=bitmap.bmBitsPixel;
pBInfo->bmiHeader.biClrImportant=0;
pBInfo->bmiHeader.biCompression=0;
pBInfo->bmiHeader.biHeight=bitmap.bmHeight;
pBInfo->bmiHeader.biPlanes=bitmap.bmPlanes;
pBInfo->bmiHeader.biSize=sizeof(BITMAPINFO);
pBInfo->bmiHeader.biSizeImage=bitmap.bmWidthBytes*bitmap.bmHeight;
pBInfo->bmiHeader.biWidth=bitmap.bmWidth;
pBInfo->bmiHeader.biXPelsPerMeter=0;
pBInfo->bmiHeader.biYPelsPerMeter=0;
memDC.BitBlt(0,0,bitmap.bmWidth,bitmap.bmHeight,pDeskDC,0,0,SRCCOPY);
//保存
char* pData=new char[bitmap.bmWidthBytes*bitmap.bmHeight];
::GetDIBits(memDC.m_hDC,bmp,0,bitmap.bmHeight,pData,pBInfo,DIB_RGB_COLORS);
int nBufSize=nPanelsize+sizeof(BITMAPINFO)+bitmap.bmWidthBytes*bitmap.bmHeight;
Bitmap* pImage=Bitmap::FromBITMAPINFO(pBInfo,pData);
pImage->Save(_T("d:\\capture.png"),&clsidPng,NULL);
//释放资源
memDC.DeleteDC();
pDeskDC->DeleteDC();
if (pImage!=NULL) delete pImage;
delete[] pData;
::LocalFree((HLOCAL)pBInfo);
bmp.DeleteObject();
}
void CTestCaptureDlg::OnBnClickedOk ()
{
// TODO: 在此添加控件通知处理程序代码
this->Capture();
OnOK();
}
PS:虽然截屏用的MFC改成API也很简单,VS自动生成的代码自己略过吧。另外我用的VS2015,WIN10上跑正常