Re: Copying Bitmap
Thanks for your inputs, the updated function is shown below.
Unfortunately, this function doesn't work when it is called by a timer and
the source window area is obscured by another application. Under this
situation, the target's contents includes a partial source and the other
application window area.
Do you know how it should be corrected?
////////////////////
void CopyWindowAreaToStaticAndBitmap(CDC& dc_source, CStatic& cs_target,
CBitmap& bitmap_output, bool& bitmap_output_valid)
{
bitmap_output.DeleteObject();
bitmap_output_valid = false;
CRect rc_static;
cs_target.GetClientRect( rc_static );
bitmap_output.CreateCompatibleBitmap( &dc_source, rc_static.Width(),
rc_static.Height() );
// Copy source onto output bitmap
CDC dc_bitmap;
dc_bitmap.CreateCompatibleDC( &dc_source );
dc_bitmap.SelectObject( &bitmap_output );
dc_bitmap.BitBlt( 0, 0, rc_static.Width(), rc_static.Height(), &dc_source,
0, 0, SRCCOPY );
// Copy output bitmap onto display target
CClientDC dc_target( &cs_target );
dc_target.BitBlt( 0, 0, rc_static.Width(), rc_static.Height(), &dc_bitmap,
0, 0, SRCCOPY );
}
////////////////////
"Ashot Geodakov" wrote:
Here's what should work for you:
void CMyDlg::CopyWindowAreaToStatic( CDC& cdc )
{
// First copy a screen area to a compatible DC/Bitmap.
CDC dcCompatible;
dcCompatible.CreateCompatibleDC( &cdc );
CBitmap bitmap;
bitmap.CreateCompatibleBitmap( &cdc, 200, 200 ); // Change the width and
height to desired ones.
dcCompatible.SelectObject( &bitmap );
dcCompatible.BitBlt( 0, 0, 200, 200, &cdc, 0, 0, SRCCOPY );
// This is to test that dcCompatible indeed has the right bits in it.
CClientDC dcStatic( &m_picture );
dcStatic.BitBlt( 0, 0, 200, 200, &dcCompatible, 0, 0, SRCCOPY );
// This is to test if bitmap has the correct bits in it.
BYTE bits[200 * 200 * 4]; // Assuming there's 4 bytes per pixel.
bitmap.GetBitmapBits( 200 * 200 * 4, bits );
// You may append these bits to a correct bitmap file headers and save
it as a .BMP file.
}
Make this bitmap a class member if you want to re-use it in painting
procedures. But add bitmap.DeleteObject() at the beginning of this function.
Hope it helps...
"Charles Tam" <CharlesTam@discussions.microsoft.com> wrote in message
news:4F9C0B47-A23F-439F-AE4F-5DCB408CFCC9@microsoft.com...
I've tried your approach and it's working very well. Thanks.
Could you help me to extend the function to return a CBitmap copy of the
source image? Is the correct way (see below)?
void CMyDlg::CopyWindowAreaToStatic( CDC& cdc, CBitmap& bm_copy )
{
CClientDC dcStatic( &m_picture );
CRect rcStatic;
m_picture.GetClientRect( rcStatic );
dcStatic.BitBlt( 0, 0, rcStatic.Width(), rcStatic.Height(), &cdc, 0, 0,
SRCCOPY );
bm_copy.CreateCompatibleBitmap( cdc, rsStatic.Width(),
rcStatic.Height()
);
}
"Ashot Geodakov" wrote:
Create a sample MFC dialog app.
On the dialog place two buttons, "Copy Window" and "Copy Client".
Also place a static Image control and create its corresponding variable
m_picture in the dialog class. Using Wizard, it'll generate something
like
CStatic m_picture;
in the dialog definition.
Define the following function in the dialog:
p[ublic/rotected/rivate]:
void CMyDlg::CopyWindowAreaToStatic( CDC& cdc )
{
CClientDC dcStatic( &m_picture );
CRect rcStatic;
m_picture.GetClientRect( rcStatic );
dcStatic.BitBlt( 0, 0, rcStatic.Width(), rcStatic.Height(), &cdc, 0,
0,
SRCCOPY );
}
Handle two button clicks for Copying window and client area:
void CMyDlg::OnBnClickedButtonwindow()
{
// TODO: Add your control notification handler code here
CopyWindowAreaToStatic( CWindowDC( this ) );
}
void CMyDlg::OnBnClickedButtonclient()
{
// TODO: Add your control notification handler code here
CopyWindowAreaToStatic( CClientDC( this ) );
}
Done...
"Charles Tam" <CharlesTam@discussions.microsoft.com> wrote in message
news:969926C2-418B-4598-BDE9-1BAA3941DC5F@microsoft.com...
I'm trying to copy the bitmap onto a CStatic object for display
purposes
insteads of the clipboard. Unfortunately, I cannot got it to work.
How
could I correct it?
/////////////////////////////////
CDC dc;
HDC hdc;
hdc = ::GetWindowDC(this->m_hWnd);
dc.Attach(hdc);
CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap bm;
CRect r;
this->GetWindowRect(&r);
CString s;
this->GetWindowText(s);
CSize sz(r.Width(), r.Height());
bm.CreateCompatibleBitmap(&dc, sz.cx, sz.cy);
CBitmap * oldbm = memDC.SelectObject(&bm);
memDC.BitBlt(0, 0, sz.cx, sz.cy, &dc, 0, 0, SRCCOPY);
m_copy.SetBitmap(bm); // display the bitmap onto a CStatic object
memDC.SelectObject(oldbm);
bm.Detach();
::ReleaseDC(this->m_hWnd, dc.Detach());
/////////////////////////////////
"Ashot Geodakov" wrote:
There are also nice classes like CWindowDC and CClientDC available,
why
go
through all this Attach(), Detach() and ReleaseDC() ?
"Charles Tam" <CharlesTam@discussions.microsoft.com> wrote in message
news:064C6EBA-A49D-4873-973F-843F781B702B@microsoft.com...
Hi Joseph, I've tried your code
"http://www.flounder.com/screencapture.htm"
in an example MFC app (VS6 C++).
Unfortunately, the compiler has returned an error on the line
"::ReleaseDC(dc.Detach());" with an error message of "error C2660:
'ReleaseDC' : function does not take 1 parameters".
Could you please tell me how to correct it?
"Joseph M. Newcomer" wrote:
It captures whatever pixels are on the screen.
joe
On Fri, 1 Jun 2007 11:43:01 -0700, Charles Tam
<CharlesTam@discussions.microsoft.com>
wrote:
Thanks for your reply and reference information.
I've another question on screen capturing.
For example, my MFC app contains a Windows Media Player ActiveX
control
and
is displaying a video session. Could I try out your screen
capture
technique to copy the current video frame on the control into a
CBitmap
object?
"Joseph M. Newcomer" wrote:
Depends on how the data is created and whether or not all
information
is displayed on the
screen.
For example, see my essay on Screen Capture on my MVP Tips site.
But
this only works if
the image contains everything you need to see, and is not
obscured
by
other windows. If
the actual image is is larger, then what you would have to do is
create a memory DC,
select a bitmap into it, and then call your OnDraw handler to
write
into the bitmap. The
catch here is that you have to know how large to make the
bitmap,
which means that you
will somehow have to track this. One way to handle this is to
simply
call OnDraw with the
default (one-pixel) bitmap and track the largest physical pixel
coordinate you write
(taking into account mapping modes), then create a bitmap, call
OnDraw
again, only this
time with a correctly-sized correct-color-depth bitmap selected
in.
Unless you have an
independent way to compute the bitmap size, this may be the only
solution that works.
joe
On Thu, 31 May 2007 23:55:00 -0700, Charles Tam
<CharlesTam@discussions.microsoft.com>
wrote:
I've a CWnd derived class e.g. CWMPPlayer4.
How do I copy the current displayed data from the CMPPlayer4
object
into a
CBitmap object?
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm