Window shot -> AUX_RGBImageRec (grrrr)

Hi guys

Here’s another one for all you hardcore Win32/OpenGL peeps… I want to create a texture from a snapshot of an active window, given a HWND.

So say I did…

HWND Notepad = NULL;
Notepad = FindWindow("Notepad", "");

… to get a handle on a running instance of Notepad, I want to use a snapshot of the window as a texture.

Now I can use GDI to capture the window as a bitmap with something along the lines of…

(Code used to be here)

… but I haven’t got a clue how to get a AUX_RGBImageRec out of it - any ideas?

Of course I don’t really care if the structure I’m using is a AUX_RGBImageRec or not, anything will do so long as I can pour my screenshot data into it and then use it to generate an OpenGL texture.

Having struggled with this for days, I’m now ready to plead to those with superior Win32 skills.

Brgrds, and thanks,

[This message has been edited by IainC (edited 10-24-2000).]

Does it have to be programmatic solution? Can’t you just select the window with the mouse and use ALT+Print Screen to copy the selected window to the clipboard, then paste the clipboard as a new image in an image editor?
Works for me with a TNT and Paint Shop Pro.
In fact, Paint Shop Pro has fairly extensive screen and window capturing abilities of its own.

This will not work with hardware overlay windows however.

[This message has been edited by DFrey (edited 10-20-2000).]

Unfortunately, it absolutely definately HAS to be done in code

gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, hbmOutput);

hbmOutput is a handle, you need the pixel data.
Read about the following in the MSDN.

int GetDIBits(
HDC hdc, // handle to DC
HBITMAP hbmp, // handle to bitmap
UINT uStartScan, // first scan line to set
UINT cScanLines, // number of scan lines to copy
LPVOID lpvBits, // array for bitmap bits
LPBITMAPINFO lpbi, // bitmap data buffer
UINT uUsage // RGB or palette index

And you probably need to use GL_BGR_EXT if you don’t massage the data.

shouldn’t you have something in your code like this?

AUX_RGBImageRec *TextureImage[1];

glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);

This is only a suggestion but somehow you have to get the AUX_RGBImageRec class pointing to a bitmap.


This is where I’m at:

(Code used to be here)

… which isn’t working. I get a corrupted texture, but even if I’m not running a Notepad instance I end up with exactly the same corrupted texture…

I tried GetDIBits but the MSDN documentation doesn’t give any decent examples, nor does anywhere else. But you were obviously right about hbmOutput not being a pointer to the colour array as I’d presumed; bitmaps turned out to be a lot more complex than that

So I’m trying with the deprecated GetBitmapBits (which at least I understand if I’m reading the docs correctly!) but still getting nowhere.

delta_z: Obviously if I could find a way to make GDI output a bitmap to a AUX_RGBImageRec easily then I’d be made. The AUX_RGBImageRec is largely irrelevant though, it’s just a structure with some dimensions and the color array in. glTexImage2D or gluBuild2DMipmaps just need a pointer to the array.

[This message has been edited by IainC (edited 10-24-2000).]

Well, I now have this, which I think should work if the screen’s 24 bit (it’s modified from some 24 bit bitmap-loading code), but since my TNT2 M64 can only do 16 or 32 bit I can’t test it!

Plus I really need a way to handle other screen bitdepths

The reason this is so simple is because in a 24-bit bitmap the data doesn’t need radically massaging to make it OGL-readable. Any ideas on how to do that massaging? Looked at this article on MSDN but couldn’t get anything to work

If anybody whose card can do 24-bit feels like trying the below it’d be much appreciated!! It should give you a texture with part of the windows logo from you start button.


[This message has been edited by IainC (edited 10-24-2000).]

At the risk of proposing the slowest, stupidest, easiest way to do this, you could always read each individual pixel – isn’t there a GetPixel GDI call?

If you’re not happy with that, you’ll want to make a DIB and BitBlt from screen to DIB.

Does anyone actually use a 24-bit desktop any more? I’ve only seen 8/16/32 in the last few years.

  • Matt

Matt, that’s a great idea! Sometimes u just can’t see the wood for the trees… thanks so much, I’ll try it. I used a 24 bit desktop until a fortnight ago, when I replaced my old Rage IIC with my TNT2.

Well, doing this…

HWND hwnd = FindWindow(“Shell_TrayWnd”, “”);
HDC hdcScreen = GetWindowDC(hwnd); // Screen DC
HDC hdcCompatible = CreateCompatibleDC(hdcScreen); // Memory DC
HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, 256, 256);
SelectObject(hdcCompatible, hBitmap);
BitBlt(hdcCompatible, 0,0, 256, 256, hdcScreen, 0,0, SRCCOPY);
long bitmapData[256*256];
int count=0;
for (int q=0; q<256; q++)
for (int w=0; w<256; w++)
bitmapData[count] = GetPixel(hdcCompatible, q, w);
glGenTextures(1, &texture); // Generate name for and bind texture.
glBindTexture(GL_TEXTURE_2D, texture);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 256, 256, GL_BGR_EXT, GL_UNSIGNED_BYTE, bitmapData);

Gives me this - see

You can see that there’s missing pixels, and I suspect I need to massage the data according to bitdepth to get it looking nice, but I have no idea how to do this!

There are not really any pixels missing. Instead you have additional pixels that shouldn’t be there. You are telling opengl that the texture format is bgr in unsigned bytes (thus each pixel taking 3 bytes) but when copying the bitmap data, you are storing each pixel in 4 bytes rather than 3.
That’s the main problem I see.

Yeah, if you use GL_BGRA_EXT instead of GL_BGR_EXT (don’t bother increasing the components value of 3 to 4, it’s not necessary; note that GL_RGB would be more descriptive, though), you will probably get the results you’re looking for.

  • Matt