Jump to content
  • Advertisement
Sign in to follow this  
irreversible

Getting HBITMAP from a DC

This topic is 3937 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I thought this'd be a trivial matter, but for some reason Microsoft seems to have made this overly complicated. This is my code:
	BITMAPINFO bi;
	ZeroMemory(&bi, sizeof(bi));
	bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	
	HBITMAP rbmp = (HBITMAP)SelectObject(rdc, (HGDIOBJ)NULL);

        // 100 is an arbitrary value - I don't know the precise
        // measurements of rbmp; I just want to get the size/format
	GetDIBits(rdc, rbmp, 0, 100, NULL, &bi, DIB_RGB_COLORS);

I also tried replacing HBITMAP rbmp = (HBITMAP)SelectObject(rdc, (HGDIOBJ)NULL); with HBITMAP new_bmp = CreateCompatibleBitmap(rdc, 1, 1); HBITMAP rbmp = (HBITMAP)SelectObject(rdc, (HGDIOBJ)new_bmp); SelectObject() always returns NULL and bi remains unchanged. Is there a simpler way of accomplishing this? A way that works, maybe? If there is, I certainly cannot find it on MSDN. PS - I tried calling this code after and between calls to BeginPaint() / EndPaint().

Share this post


Link to post
Share on other sites
Advertisement
From the MSDN for SelectObject:
Quote:

The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type.

What type of object is NULL? Is a BITMAP, a BRUSH, a PEN, a FONT or anything else that can be selected into a DC? To get the current contents of a portion of the thing a DC is drawing on you need to do the following:

1. Create a new bitmap
2. Create a new DC
3. Select new bitmap into new DC
4. BitBlt from DC of interest into new DC

But if all you want is the dimensions and/or the format of the thing the DC is drawing to then you need to use GetDeviceCaps (link to MSDN information).

Skizz

Share this post


Link to post
Share on other sites
Colin - yeah, as far as I can tell, the DC is valid and GetLastError() returns no error.


Skizz - erm, call GetDeviceCaps() with which arguments? As far as I can tell, the following seems to be the most reliable way:


HWND hwnd = WindowFromDC(rdc);
RECT rc;
GetClientRect(hwnd, &rc);
int wd = rc.right - rc.left;
int ht = rc.bottom - rc.top;

HDC tDC = CreateCompatibleDC(rdc);
HBITMAP tBMP = CreateCompatibleBitmap(rdc, width, height);
SelectObject(tDC, tBMP);
BitBlt(tDC, 0, 0, width, height, rdc, x, y, SRCCOPY);



DeleteDC(tDC);
DeleteObject(tBMP);

Share this post


Link to post
Share on other sites
Thanks! Unfortunately in this case, thinking about it a little, it's not really of too much use unless there's a function equivalent of GetDIBits() that'd allow me to get a subsection of rdc into a buffer (eg a width x height patch at coordinates x, y).

But it is kind of criminal that this function isn't more actively cross-referenced in MSDN as I've felt need for it before and done some quite extensive Googling and still not found it.

Share this post


Link to post
Share on other sites
Quote:
Original post by irreversible
equivalent of GetDIBits() that'd allow me to get a subsection of rdc into a buffer (eg a width x height patch at coordinates x, y).

See my previous post, i.e. BitBlt.

Skizz

Share this post


Link to post
Share on other sites
What I meant is that GetCurrentObject() would be useful if I could get a subsection of the HBITMAP returned by it as a regular data buffer without having to allocate an intermediate HDC/HBITMAP, which would mean I could skip the blitting bit altogether.

Currently I can just as well just allocate the new HDC/HBITMAP, blit the section I need directly from the other DC and then retrieve the data buffer with GetDIBits(), making the GetCurrentObject() call obsolete.

Share this post


Link to post
Share on other sites
Quote:
Original post by irreversible
What I meant is that GetCurrentObject() would be useful if I could get a subsection of the HBITMAP returned by it as a regular data buffer without having to allocate an intermediate HDC/HBITMAP, which would mean I could skip the blitting bit altogether.

Currently I can just as well just allocate the new HDC/HBITMAP, blit the section I need directly from the other DC and then retrieve the data buffer with GetDIBits(), making the GetCurrentObject() call obsolete.
There's nothing like this built into the Win32 API, it's a pretty specialised thing you want to do, and you can't get direct access to the bits, because they're in a device dependant format. BitBlt()int to a scratch surface seems the best choice here.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!