Display screen remotely

Started by
58 comments, last by David Lake 10 years, 8 months ago

Btw, you can extract your bitmap in 24 bits per pixel if you wish, by settings the LPBITMAPINFO bmiHeader.biBitCount member to 24


// ... some code removed

        // De-select our hbmp
        SelectObject(s_hdc, ex_hbmp);

	// Allocate a BITMAPINFO buffer 
	LPBITMAPINFO lpbi = (LPBITMAPINFO)(new BYTE[BMISize]);
	ZeroMemory(lpbi, sizeof(BITMAPINFO));
	lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

	// Get information about the screenshot image format
	GetDIBits(s_hdc, hbmp, 0, h, NULL, lpbi, DIB_RGB_COLORS);
	lpbi->bmiHeader.biCompression = BI_RGB;
	// Make sure it's gonna be extracted in 24 bits format
	lpbi->bmiHeader.biBitCount  = 24;
	lpbi->bmiHeader.biSizeImage = NumPixels * 3;

	// Extract the image in 24 bits format
	GetDIBits(s_hdc, hbmp, 0, h, pSrc->GetBuffer(), lpbi, DIB_RGB_COLORS);

...
Advertisement

Oh yea I understand now, my brain dont work as well as it used to and im only 24!

Yipeee that sped it up a bit!

1 xor 1 = 0
1 xor 0 = 1
0 xor 1 = 1
0 xor 0 = 0

Do some exercise with a pen and paper, with 2 Bytes. Try it twice with identical value, then try it twice again with non-identical value.

You'll get it eventually.

Edit: Oh, now it was me that though you where being sarcastic haha.

Now I would like a faster way to display the image than a picturebox if possible?

I also need to remove the alpha channel as bitblt gives me no choice on that, whats the best way to do that, in the xor loop in my dll?

You need directx or opengl for that, in c#, i dunno how that would work though. All you have to do is create a texture once, then replace it with the new one each frame, then draw it on a quad the size of the screen, using the texture above.

As for the alpha channel, i can post all my code but it's in c++


//-----------------------------------------------------------------------------
// Draw the cursor
//-----------------------------------------------------------------------------
void CScreenShot::DrawCurcor(HDC hDC)
{
	CURSORINFO CursorInfo;
	CursorInfo.cbSize = sizeof(CURSORINFO);
	GetCursorInfo(&CursorInfo);

	static DWORD Version = WinVer.DetectWindowsVersion();
	//static HCURSOR hCur = LoadCursor(NULL, IDC_ARROW);

	DWORD CursorWidth  = GetSystemMetrics(SM_CXCURSOR);
	DWORD CursorHeight = GetSystemMetrics(SM_CYCURSOR);

	POINT CursorPos;
	GetCursorPos(&CursorPos);
	
	// Needed for XP or older windows
	if(Version < _WIN_VISTA_){
		CursorPos.x -= CursorWidth  >> 2;
		CursorPos.y -= CursorHeight >> 2;
	}

	DrawIconEx(hDC, CursorPos.x, CursorPos.y, CursorInfo.hCursor, CursorWidth, CursorHeight, 0, NULL, DI_NORMAL);
}

//-----------------------------------------------------------------------------
// Take a screenshot, extract it to a buffer in 24 bits, and compress it
//-----------------------------------------------------------------------------
int CScreenShot::GenMPEGScreenShot(CVideoEncoder *pVideoEncoder, BOOL ShowCursor)
{
	HWND hDesktopWnd = GetDesktopWindow();
	HDC  hdc = GetDC(hDesktopWnd);

	int x = 0;
	int y = 0;
	int w = GetSystemMetrics(SM_CXSCREEN);
	int h = GetSystemMetrics(SM_CYSCREEN);

	HDC     s_hdc   = CreateCompatibleDC(hdc);
	HBITMAP hbmp    = CreateCompatibleBitmap(hdc, w,h);
	HBITMAP ex_hbmp = (HBITMAP)SelectObject(s_hdc, hbmp);

/////////////////////////////////////////////////////////////////////////////////////////

	// Copy the screen image in our bitmap
	BitBlt(s_hdc, x,y,w,h, hdc, x,y, SRCCOPY);

	// Draw the cursor over the image
	if(ShowCursor)
		DrawCurcor(s_hdc);
	
	ReleaseDC(hDesktopWnd, hdc);

/////////////////////////////////////////////////////////////////////////////////////////

	// Create pointers to our buffers object
	CRawBuffer *pSrc = &Buffers.MPEG.ScreenShot;
	CRawBuffer *pDst = &Buffers.MPEG.Encoded;

	// Allocate buffers
	DWORD NumPixels = w * h;
	if(pSrc->GetBufferSize() != NumPixels * 3)
		pSrc->Allocate(NumPixels * 3);

	// Allocate a BITMAPINFO buffer 
	LPBITMAPINFO lpbi = (LPBITMAPINFO)(new BYTE[BMISize]);
	ZeroMemory(lpbi, sizeof(BITMAPINFO));
	lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

	// De-select our hbmp
	SelectObject(s_hdc, ex_hbmp);

	// Get information about the screenshot image format
	GetDIBits(s_hdc, hbmp, 0, h, NULL, lpbi, DIB_RGB_COLORS);
	lpbi->bmiHeader.biCompression = BI_RGB;
	// Make sure it's gonna be extracted in 24 bits format
	lpbi->bmiHeader.biBitCount  = 24;
	lpbi->bmiHeader.biSizeImage = NumPixels * 3;

	// Extract the image in 24 bits format
	GetDIBits(s_hdc, hbmp, 0, h, pSrc->GetBuffer(), lpbi, DIB_RGB_COLORS);

	// Delete the BITMAPINFO buffer
	SAFE_DELETE_ARRAY(lpbi);

	// Release the bitmap handles
	if(SelectObject(s_hdc, hbmp)){
		DeleteObject(hbmp);
		DeleteDC(s_hdc);
	}

/////////////////////////////////////////////////////////////////////////////////////////

	// Convert from BGR to RGB
	Convert24bitsBGRTORGB(pSrc->GetBuffer(), pSrc->GetBufferSize());

/////////////////////////////////////////////////////////////////////////////////////////

	// Compress the frame using ffmpeg
	int FrameSize = pVideoEncoder->EncodeFrame(pDst->GetBuffer(6), pSrc->GetBuffer(), pSrc->GetBufferSize());
	
	// Write the packet header 
	WORD MsgID = MSG_MP1_IMG_REQUEST;
	memcpy(pDst->GetBuffer(0), &FrameSize, sizeof(DWORD));
	memcpy(pDst->GetBuffer(4), &MsgID,     sizeof(WORD));

	// Free our source buffer
	pSrc->Free(); 

	// Return compressed buffer size
	Size = FrameSize;
	return Size;
}

Could you give me the includes for that code please?

Well you don't have to use it "as it is", just take the most important bits. The CRawBuffer object are just managed BYTE arrays in a class. And you dont need to code at the bottom, im about to rewrite all that.

I believe it's based on this site or something similar, i don't remember anymore. Here's another one (look better imo).

I want to consolidate the screen capture process from bitblt with multiple pinvokes to a single pinvoke with the capture code in my C++ dll.

Every time I find a bit of C++ code I get squiggly red lines because nobody thinks to include the includes.

This should do it (havent compiled it but it should be fine)


int GenMPEGScreenShot(BYTE *pBuffer)
{
	HWND hDesktopWnd = GetDesktopWindow();
	HDC  hdc = GetDC(hDesktopWnd);

	int x = 0;
	int y = 0;
	int w = GetSystemMetrics(SM_CXSCREEN);
	int h = GetSystemMetrics(SM_CYSCREEN);

	HDC     s_hdc   = CreateCompatibleDC(hdc);
	HBITMAP hbmp    = CreateCompatibleBitmap(hdc, w,h);
	HBITMAP ex_hbmp = (HBITMAP)SelectObject(s_hdc, hbmp);

/////////////////////////////////////////////////////////////////////////////////////////

	// Copy the screen image in our bitmap
	BitBlt(s_hdc, x,y,w,h, hdc, x,y, SRCCOPY);

	// Draw the cursor over the image
	//if(ShowCursor)
	//	DrawCurcor(s_hdc);
	
	ReleaseDC(hDesktopWnd, hdc);

/////////////////////////////////////////////////////////////////////////////////////////

	if(pBuffer)
		delete [] pBuffer;

	DWORD NumPixels = w * h;
	DWORD BufSize = NumPixels * 3;

	// Allocate buffers
	pBuffer = new BYTE[BufSize];
	ZeroMemory(pBuffer, BufSize);

	// Allocate a BITMAPINFO buffer 
	LPBITMAPINFO lpbi = (LPBITMAPINFO)(new BYTE[BMISize]);
	ZeroMemory(lpbi, sizeof(BITMAPINFO));
	lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

	// De-select our hbmp
	SelectObject(s_hdc, ex_hbmp);

	// Get information about the screenshot image format
	GetDIBits(s_hdc, hbmp, 0, h, NULL, lpbi, DIB_RGB_COLORS);
	lpbi->bmiHeader.biCompression = BI_RGB;
	// Make sure it's gonna be extracted in 24 bits format
	lpbi->bmiHeader.biBitCount  = 24;
	lpbi->bmiHeader.biSizeImage = BufSize;

	// Extract the image in 24 bits format
	GetDIBits(s_hdc, hbmp, 0, h, pBuffer, lpbi, DIB_RGB_COLORS);

	// Delete the BITMAPINFO buffer
	if(lpbi)
		delete [] lpbi;

	// Release the bitmap handles
	if(SelectObject(s_hdc, hbmp)){
		DeleteObject(hbmp);
		DeleteDC(s_hdc);
	}

	return BufSize;
}

Just make sure to pass a NULL pointer the first time this function is called, and delete the buffer at the end of your program (maybe with another function that just call delete [] on the pBuffer pointer)

Thanks but I'm still a noob with C++ and I get 44 errors with that code I think I need some includes, if so what ones?

Found it!

#include <WinGDI.h>

Actually I'm getting more and more errors in other files HELP!

This topic is closed to new replies.

Advertisement