Click here to Skip to main content
12,621,302 members (32,263 online)
Click here to Skip to main content
Add your own
alternative version

Stats

21.2K views
49 bookmarked
Posted

Using "RDP Encoder Mirror Driver" to Capture Screen

, 27 Jan 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
High Performance Method for Capturing Screen

Introduction

My code snippet takes a screenshot with "RDP Encoder Mirror Driver". Capturing screen with mirror driver is a very high performance method, but relying on a mirror driver. "RDP Encoder Mirror Driver" is included in Windows 7, and using it to take screenshots has no need to install other mirror driver. 

Background

When I do my work to drive LED Display, I need to have a screenshot and send the bitmap data to the hardware which communicates with computer in UDP. It is easy to take a screenshot with GDI API, but its performance is poor. I know that using Mirror Driver is a good idea and develop my mirror driver. When I wrote a testing program to list out all the display devices, I found "RDP Encoder Mirror Driver" in the list. After I tested the "RDP Encoder Mirror Driver", I found it works well.

Using the Code

At first, we need to detect whether the "RDP Encoder Mirror Driver" exists. If the "RDP Encoder Mirror Driver" exists, it can be used to take screenshots.

int Detect_MirrorDriver(vector<DISPLAY_DEVICE>& devices,map<int,DEVMODE>& settings)
{
	CString all_mirror_divers[2] = {
					_T("RDP Encoder Mirror Driver"),//included in windows 7
					_T("LEDXXX Mirror Driver")//my own mirror driver, used in Windows XP
									};
	DISPLAY_DEVICE dd;
	ZeroMemory(&dd, sizeof(dd));
	dd.cb = sizeof(dd);
	int n = 0;
	while(EnumDisplayDevices(NULL, n, &dd, EDD_GET_DEVICE_INTERFACE_NAME))
	{
		n++;
		devices.push_back(dd);
	}
	for(int i=0;i<(int)devices.size();i++)
	{
		DEVMODE dm;
		ZeroMemory(&dm, sizeof(DEVMODE));
		dm.dmSize = sizeof(DEVMODE);
		dm.dmDriverExtra = 0;
		if(EnumDisplaySettingsEx(devices[i].DeviceName,ENUM_CURRENT_SETTINGS,&dm,EDS_ROTATEDMODE))
		{
			settings.insert(map<int,DEVMODE>::value_type(i,dm));
		}
	}
	for(int m =0;m<2;m++)
	{
		for(int i=0;i<(int)devices.size();i++)
		{
			CString drv(devices[i].DeviceString);
			if(drv == all_mirror_divers[m])
			{
				return m;
			}
		}
	}
	return -1;//can not use any mirror driver
} 

Using the "RDP Encoder Mirror Driver" to take screenshots is very simple:

class RDPCapture
{
	int mw;
	int mh;
	int mx0;
	int my0;
	DEVMODE myDM;
	DISPLAY_DEVICE myDev;
	HDC m_driverDC;
	CDC m_cdc;
	BITMAPINFO	m_BmpInfo;
	HBITMAP	m_Bitmap;
	HBITMAP	Old_bitmap;
	DEVMODE oldDM;
public:
	RDPCapture(){}
	RDPCapture(DISPLAY_DEVICE dev,DEVMODE dm)
	{
		myDev = dev;
		myDM = dm;
		oldDM = dm;
		m_driverDC = NULL;
	}
	~RDPCapture()
	{
		SelectObject(m_cdc,Old_bitmap);
		DeleteObject(m_Bitmap);
		m_cdc.DeleteDC();
		if(m_driverDC != NULL) DeleteDC(m_driverDC);
		oldDM.dmDeviceName[0] = 0;
		ChangeDisplaySettingsEx(myDev.DeviceName,&oldDM, 0, 0, 0);
	}
	virtual bool Init(int x0,int y0,int width,int height)
	{
		mx0 = x0;
		my0 = y0;
		mw = (width + 3)&0xFFFC;
		mh = height;

		DEVMODE dm;
		dm = myDM;
		WORD drvExtraSaved = dm.dmDriverExtra;
		memset(&dm, 0, sizeof(DEVMODE));
		dm.dmSize = sizeof(DEVMODE);
		dm.dmDriverExtra = drvExtraSaved;
		dm.dmPelsWidth = 2048;
		dm.dmPelsHeight = 1280;
		dm.dmBitsPerPel = 24;
		dm.dmPosition.x = 0;
		dm.dmPosition.y = 0;
		dm.dmDeviceName[0] = '\0';
		dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH |
                      DM_PELSHEIGHT | DM_POSITION;
		if(ChangeDisplaySettingsEx(myDev.DeviceName, &dm, 0, CDS_UPDATEREGISTRY, 0))
		{
			ChangeDisplaySettingsEx(myDev.DeviceName, &dm, 0, 0, 0);
		}
		//------------------------------------------------
		ZeroMemory(&m_BmpInfo, sizeof(BITMAPINFO));
		m_BmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
		m_BmpInfo.bmiHeader.biBitCount = 24;
		m_BmpInfo.bmiHeader.biCompression = BI_RGB;
		m_BmpInfo.bmiHeader.biPlanes = 1;
		m_BmpInfo.bmiHeader.biWidth = mw;
		m_BmpInfo.bmiHeader.biHeight = -mh;
		m_BmpInfo.bmiHeader.biSizeImage= mw*mh*3;	
		HDC Top = ::GetDC(GetDesktopWindow());
		m_cdc.CreateCompatibleDC(NULL);//兼容设备上下文环境
		m_Bitmap = CreateCompatibleBitmap(Top, mw,mh);//Bitmap,画布
		Old_bitmap = (HBITMAP)SelectObject(m_cdc, m_Bitmap);//画布与设备上下文环境关联
		::ReleaseDC(GetDesktopWindow(),Top);
		m_driverDC = CreateDC(myDev.DeviceName, 0, 0, 0);
		return true;
	};
	virtual bool GetData(unsigned char *buf)
	{
		BitBlt(m_cdc,0,0,mw,mh,m_driverDC,mx0,my0,SRCCOPY|CAPTUREBLT);		
		GetDIBits(m_cdc,m_Bitmap,0,mh,buf, &m_BmpInfo, DIB_RGB_COLORS);
		return true;
	};
}; 

To use the class "RDPCapture", you can write code like below:

RDPCapture* rdp_capture = NULL;
vector<DISPLAY_DEVICE> devices;
map<int,DEVMODE>& settings;
int res = Detect_MirrorDriver(devices,settings);
if(res ==0)
{
	rdp_capture = new RDPCapture(devices[0],settings[0]);
}

Points of Interest

When I wrote this article, I found it interesting to use a mirror driver with GDI API.

History

  • 2014/1/27 First version
  • 2014/1/27 Remove the base class of RDPCapture  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Amazing LED Display
United States United States
No Biography provided

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionQuestion about mirror driver Pin
miquelt10-Jun-15 23:04
membermiquelt10-Jun-15 23:04 
Questioncan not capture some transportation window Pin
quakeguo10-Jun-15 20:43
memberquakeguo10-Jun-15 20:43 
QuestionGetting a gray screenshot Pin
Member 1012087627-Dec-14 22:04
memberMember 1012087627-Dec-14 22:04 
QuestionCan you please include the vs solution? Pin
seanzcan6-Mar-14 16:06
memberseanzcan6-Mar-14 16:06 
QuestionRe: Can you please include the vs solution? Pin
dirend15-Apr-14 23:10
memberdirend15-Apr-14 23:10 
QuestionHow to get the changed region information Pin
Namilwoo5-Feb-14 18:04
memberNamilwoo5-Feb-14 18:04 
AnswerRe: How to get the changed region information Pin
Amazing LED Display7-Feb-14 0:26
memberAmazing LED Display7-Feb-14 0:26 
GeneralRe: How to get the changed region information Pin
vbxbert17-Jul-14 0:24
membervbxbert17-Jul-14 0:24 
Questionerror C2504: 'ICapture' : base class undefined Pin
flyboybin26-Jan-14 23:22
memberflyboybin26-Jan-14 23:22 
AnswerRe: error C2504: 'ICapture' : base class undefined Pin
Amazing LED Display27-Jan-14 4:14
memberAmazing LED Display27-Jan-14 4:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161128.1 | Last Updated 27 Jan 2014
Article Copyright 2014 by Amazing LED Display
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid