当前位置:C++技术网 > 资讯 > 简易的代码实现屏幕截图的功能

简易的代码实现屏幕截图的功能

更新时间:2016-01-03 16:17:14浏览次数:1+次

屏幕抓图程序的关键有两点:一是应该确认图片所在窗口的窗口句柄,也就是说,在什么地方捕获图片;二是,如何对抓取到的图片进行保存,这个问题,GDI+完美的为你解决了。

对于问题一,我们知道,可以利用SetCapture函数能够追踪鼠标指针移动的特点,在移动鼠标的过程中,还可以根据鼠标指针所在的位置来判断当前窗口的句柄。我们可以利用一个平时程序员不经常使用的函数WindowFromPoint,这个函数能够找出鼠标指针当前位置所对应的窗口句柄。

创建基于对话框的工程,同时写入GDI+代码,形成一个GDI+工程,请看网站的GDI+文章,有关于GDI+代码的介绍。主要代码:

void CScreenCaptionDlg::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	///如果用户按住鼠标左键不放,则开始抓取图片
	if(nFlags==MK_LBUTTON)
	{
		//隐藏程序窗口,以免影响在抓取时的"视野"
		ShowWindow(SW_HIDE);
		//HCURSOR cur=LoadCursor(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));
		SetCapture();
		///获得鼠标指针所在窗口的句柄
		ClientToScreen(&point);
		hwndCapture=(HWND)::WindowFromPoint(point);
		//取得屏幕的设备环境句柄,以便在屏幕的任何位置绘图
		HDC hDC=::GetDC(NULL);
		///建立一支红色的画笔
		HPEN hPen=CreatePen(PS_INSIDEFRAME,6,RGB(255,0,0));
		///将毁图模式设为R2_NOTXORPEN,在绘图时可以不破坏原有的背景
		int nMode=SetROP2(hDC,R2_NOTXORPEN);
		HPEN hpenOld=(HPEN)SelectObject(hDC,hPen);
		//得到鼠标指针所在窗口的区域
		::GetWindowRect(hwndCapture,&rectCapture);
		//在鼠标指针所在处的窗口四周画一红色矩形,作为选定时的提示
		POINT pt[5];
		pt[0]=CPoint(rectCapture.left,rectCapture.top);
		pt[1]=CPoint(rectCapture.right,rectCapture.top);
		pt[2]=CPoint(rectCapture.right,rectCapture.bottom);
		pt[3]=CPoint(rectCapture.left,rectCapture.bottom);
		pt[4]=CPoint(rectCapture.left,rectCapture.top);

		::Polyline(hDC,pt,5);
		///延时后再重绘红色矩形,这样就不会破坏原有内容
		Sleep(100);
		::SelectObject(hDC,hpenOld);
		::ReleaseDC(NULL,hDC);
	}
	CDialogEx::OnMouseMove(nFlags, point);
}


void CScreenCaptionDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	//得到鼠标指针所在窗口的区域的宽,高
	int nWidth=rectCapture.Width();
	int nHeight=rectCapture.Height();
	HDC hdcScreen,hMemDC;
	HBITMAP hBitmap,hOldBitmap;
	///建立一个屏幕设备环境句柄
	hdcScreen=CreateDC(L"DISPLAY",NULL,NULL,NULL);
	hMemDC=CreateCompatibleDC(hdcScreen);
	//建立一个与屏幕设备环境句柄兼容,与鼠标指针所在窗口的区域等大的位图
	hBitmap=CreateCompatibleBitmap(hdcScreen,nWidth,nHeight);
	//把新位图选到内存设备描述表中
	hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);
	///把屏幕设备描述表拷贝到内存设备描述表中
	BitBlt(hMemDC,0,0,nWidth,nHeight,hdcScreen,rectCapture.left,rectCapture.top,SRCCOPY);
	//区域鼠标指针所在窗口的屏幕位图的句柄
	hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);
	DeleteDC(hdcScreen);
	DeleteDC(hMemDC);

	///返回位图句柄
	//打开剪贴板,并将位图拷到剪贴板上
	OpenClipboard();
	EmptyClipboard();
	SetClipboardData(CF_BITMAP,hBitmap);
	CloseClipboard();
	MessageBox(L"屏幕内容已经拷到剪贴板!");
	ReleaseCapture();
	ShowWindow(SW_NORMAL);

	OPENFILENAME ofn;
	TCHAR lpstrFileName[MAX_PATH]=L"屏幕截图文件.bmp";
	ZeroMemory(&ofn,sizeof(ofn));
	ofn.lStructSize=sizeof(OPENFILENAME);
	ofn.hwndOwner=this->m_hWnd;
	ofn.lpstrFilter=L"位图文件(.BMP)\0*.bmp";
	ofn.nMaxFile=MAX_PATH;
	ofn.lpstrFile=lpstrFileName;
	ofn.lpstrTitle=L"将屏幕截图文件另存为?";

	if(GetSaveFileName(&ofn))
	{
		CLSID pngClsid;
		Bitmap bmp(hBitmap,NULL);
		GetEncoderClsid(L"image/bmp",&pngClsid);
		CString tmp(ofn.lpstrFile);
		CStringW filename(tmp);
		bmp.Save(filename,&pngClsid);
	}
	CDialogEx::OnLButtonUp(nFlags, point);
}

int CScreenCaptionDlg::GetEncoderClsid(WCHAR* format, CLSID* pClsid)
{
	UINT  num = 0;
	UINT  size = 0;
	ImageCodecInfo* pImageCodecInfo = NULL;
	GetImageEncodersSize(&num, &size);
	if (size == 0)
		return -1;

	pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
	if (pImageCodecInfo == NULL)
		return -1;

	GetImageEncoders(num, size, pImageCodecInfo);
	for (UINT j = 0; j < num; ++j)
	{
		if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
		{
			*pClsid = pImageCodecInfo[j].Clsid;
			free(pImageCodecInfo);
			return j;
		}
	}
	free(pImageCodecInfo);
	return -1;
}
在头文件中:
HWND hwndCapture;
CRect rectCapture;
int GetEncoderClsid(WCHAR* format, CLSID* pClsid);

对于GetEncoderClsid,请看之前的文章,搜索作者阿郎找找就行了。由于特殊原因,我这里查不了,就看读者你的好学心了

代码实现: