PDA

View Full Version : Keeping previous screen image



Messiaha
04-18-2002, 03:33 AM
This is a win specific question.
Is there any way you can keep the exact contents of the framebuffer(desktop image etc.) for use in the opengl device context? Or if not is there another way of obtaining the screen image prior to switching contexts?
I am trying to make a funky application statup effect.

ScottManDeath
04-18-2002, 05:34 AM
Hi
you could get a HDC of the desktop by using GetDesktopDC(). You could then play around with it (wglCreateContext...).Im not sure if this is "fair" to OpenGL because you aren't the owner, but give it a try and look around in the win32 sdk doc
Bye
ScottManDeath

zed
04-18-2002, 01:02 PM
A/ use realpixels
B/ wgl_buffer_region (im not 100% sure if this work if u swap rc's)

V-man
04-18-2002, 05:09 PM
Why not render to p-buffers? It will eat up a lot of video memory and slow things if you plan on making many.
Dont know what buffer_region does exactly. I think it protects by masking...

V-man

ChrisBond
04-20-2002, 05:58 AM
***************
OT WARNING
***************

... Only the last few sentences of all this have anything to do with OGL specifically; it's mostly showing how to get access to the pixel data on the desktop (or any other window you have a handle to - even an OpenGL Window once you've called wglSwapBuffers()...), which seems like a problem that would crop up from time to time for any application developer working specifically with graphics.

A lot of this can probably be found at more general programming sites like CodeGuru.com or CodeProject.com I'd suggest you look there for more info.

General approach:
Get access to the pixel data for the desktop, then use your favorite Bitmap-to-texture technique to get the data out to your OpenGL window.

Step-By-Step:

First, use

HDC hDesktop = ::GetDC(NULL);
CDC *pDC = CDC::FromHandle(hDesktop);
CRect rectClient;
pDC->GetClientRect(rectClient);

To get a handle to the desktop's DC and it's dimensions.

Second, create a memory device context compatible with hDesktop, and a also Bitmap compatible with and the same size as hDesktop's client areas:
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap Bitmap;
Bitmap.CreateCompatibleBitmap(pDC, rectClient.Width(), rectClient.Height());

Third, copy the image from the Desktop to your memory DC:
MemDC.BitBlt(0, 0, rectClient.Width(), rectClient.Height(), pDC, 0, 0, SRCCOPY);

And go ahead and release that desktop device context.
::ReleaseDC(pDC->GetSafeHdc());

(You now have a CBitmap with all the pixel data, but to get it out to a texture requires an actual pointer to the data)

Fourth, To be safe, go get a BITMAP structure describing the exact dimensions of the pixel data (as opposed to using the info you have to guess at it.)

BITMAP infoBitmap;
Bitmap.GetBitmap(&infoBitmap);

Fifth, allocate memory for you raw pixel data:
unsigned char *pRawPixelData = NULL;
pRawPixelData = new unsigned char[infoBitmap.bmWidthBytes * infoBitmap.bmHeight];

Sixth, go get that raw data.
Bitmap.GetBitmapBits(infoBitmap.bmWidthBytes * infoBitmap.bmHeight, pRawPixelData);

So, finally, you have a buffer full of raw pixel data you can hand off to OpenGL with a call to either ::glDrawPixels() or ::glTexImage2D(). I'd probably use teh handy pBuffer class on the NVidia site to create a pBuffer, glDrawPixels() the data to it, then use wglMakeCurrentRead() to do subsequent drawing in my actual window, but there may be better approaches - I'm a Win32 guy still picking up OpenGL.

As an aside, if you have Microsoft's August 2001 Platform SDK update, use Gdiplus. Unless this is for a commercial product, in which case you need to read the liscensing drek about the prerelease stuff. But using Gdiplus gives you much finer control over pixelformats, and IMHO is a *much* better abstraction of the graphics subsystem than MFC.

-Chris Bond

knackered
04-20-2002, 06:35 AM
I've always used the following to get the desktops HDC:-

HWND desktopwin = ::GetWindow(::GetWindow(::FindWindow("ProgMan",NULL), GW_CHILD), GW_CHILD);
HDC desktopdc = ::GetDC(desktopwin);


Can't remember where I found this info, but it works on all versions of windows..

CGameProgrammer
04-21-2002, 01:36 PM
But he's not trying to get the desktop image. He's trying to get the image the desktop and all the windows currently opened. Basically, he's trying to do what Ctrl+PrintScreen does.

knackered
04-21-2002, 01:50 PM
...and that is exactly what he will get with chrisbonds code.
I was just suggesting a more compatible way of getting the dc of the desktop.

Messiaha
04-22-2002, 04:07 AM
Thanks for your help I used Chris Bond's code to do what I was trying to do.