15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


How Do You Create A Bitmap from a image in a window?

Gary Krone -- gkrone@inconsys.com
Friday, March 07, 1997

Environment:    VC++ 4.2-flat, WinNT 4.0

This has got to be simple!

What I want to know is how you can take an image drawn on a window and make
a CBitmap Object out of it ( Or similar way to take a 'snapshot' of the
screen image for later use ).  The catch is the image doesn't exist previous
to being drawn on the window surface.  If anyone has some sample code on how
to do this it would be greatly appreciated.
Gary Krone
gkrone@inconsys.com
gkrone@execpc.com





Norman C. Byers -- nbyers@intxxnet.com
Sunday, March 09, 1997

[Mini-digest: 9 responses]

Read the documentation for CreateDC. You use a driver name of "DISPLAY". 
Once you have a DC to the screen, its fairly simple to find your images 
location, and do the appropriate create compatible DC and compatible 
bitmaps, do bitblts and all that neat junk. You can get this Windows 101 
stuff from the earliest Petzold books.

----------
From:  Gary Krone[SMTP:gkrone@inconsys.com]
Sent:  Friday, March 07, 1997 9:03 AM
To:  mfc-l@netcom.com
Subject:  How Do You Create A Bitmap from a image in a window?

Environment:    VC++ 4.2-flat, WinNT 4.0

This has got to be simple!

What I want to know is how you can take an image drawn on a window and make
a CBitmap Object out of it ( Or similar way to take a 'snapshot' of the
screen image for later use ).  The catch is the image doesn't exist 
previous
to being drawn on the window surface.  If anyone has some sample code on 
how
to do this it would be greatly appreciated.
Gary Krone
gkrone@inconsys.com
gkrone@execpc.com



-----From: Ben Burnett 

Gary Krone wrote:

  Environment:    VC++ 4.2-flat, WinNT 4.0

  This has got to be simple!

  What I want to know is how you can take an image drawn on a window
  and make
  a CBitmap Object out of it ( Or similar way to take a 'snapshot' of
  the
  screen image for later use ).  The catch is the image doesn't exist
  previous
  to being drawn on the window surface.  If anyone has some sample
  code on how
  to do this it would be greatly appreciated.
  Gary Krone
  gkrone@inconsys.com
  gkrone@execpc.com

 If your still looking for the sample code just e-mail me and i'll send
you an attachment

-----From: Sreekant Sreedharan 

Hi Gary,
	I don't remember how I did it, but I can give an idea. 
	To begin with, you should create a bitmap of the properties(
width,height,bits-per-pixel etc.). Select this bitmap into the window
device context, this is important. Then you can use
CDC::GetCurrentBitmap to retrieve the CBitmap* anytime to take your
'snapshot'. 
	Please let me know if you have a problem.

Gary Krone wrote:
> 
> Environment:    VC++ 4.2-flat, WinNT 4.0
> 
> This has got to be simple!
> 
> What I want to know is how you can take an image drawn on a window and make
> a CBitmap Object out of it ( Or similar way to take a 'snapshot' of the
> screen image for later use ).  The catch is the image doesn't exist previous
> to being drawn on the window surface.  If anyone has some sample code on how
> to do this it would be greatly appreciated.
> Gary Krone
> gkrone@inconsys.com
> gkrone@execpc.com

-- 
---- From "Sreekant Sreedharan"
-----From: igor_firkusny@abtassoc.com


     
     
     So, you have done some drawing to a Window, and you want to cache the 
     rendered graphics to a memory bitmap? I don't have sample code on 
     hand, but the general approach is the following:
     
     Create a memory DC compatible to your window's DC using 
     CreateCompatibleDC. This DC will initially have a dummy, 1-bit bitmap 
     tied to it, which is pretty useless, so you need to create a bitmap to 
     associate with it using CreateCompatibleBitmap(), specifying the 
     source window's DC. Then select this new bitmap into the memory DC 
     with SelectObject(), and then bit-transfer (BitBlt() etc) the bitmap 
     in the source to the destination DC.
     
     Remember to destroy both the bitmap and the memory DC you created 
     after you're done, or it will leak. 
     
     
     I have done this and it works. However, this message was written from 
     memory, so I apologize if I misstated something.
     
     
     --if


______________________________ Reply Separator _________________________________
Subject: How Do You Create A Bitmap from a image in a window?
Author:  uunet!netcom.com!mfc-l at UUCPmail
Date:    3/9/97 9:23 AM


Environment:    VC++ 4.2-flat, WinNT 4.0
     
This has got to be simple!
     
What I want to know is how you can take an image drawn on a window and make 
a CBitmap Object out of it ( Or similar way to take a 'snapshot' of the 
screen image for later use ).  The catch is the image doesn't exist previous 
to being drawn on the window surface.  If anyone has some sample code on how 
to do this it would be greatly appreciated.
Gary Krone
gkrone@inconsys.com
gkrone@execpc.com
     
     
-----From: Joao Marcos Melo Mendes 

Ahoy, :)

On Fri, 7 Mar 1997, Gary Krone wrote:

Environment:    VC++ 4.2-flat, WinNT 4.0

Actually, I'm using 4.2b now, but I upgraded only recently. I can tell 
you for sure weather this code predates the upgrade or not, but more 
likely than not it did, so it should work for you.

> This has got to be simple!

Well, yes and no. :) What I wanted to do was to save a CBitmap taken from 
a window into a BMP file, so you'll find the code is a little convoluted, 
but I'm sure you'll be able to strip up the stuff you don't need.

> What I want to know is how you can take an image drawn on a window and make
> a CBitmap Object out of it ( Or similar way to take a 'snapshot' of the

The root of the matter is simple: get the window DC, create a compatible 
DC, create a compatible bitmap, select the bitmap into the compatible DC, 
then BitBlt between the two.

Try this:

long CMyWnd::SaveFile(CString strFName)
{
  CFile f;
  CBitmap bmp, * bmpOld;
  CDC dcTmp, * pdc;
  CRect rct;
  BITMAPINFO * lp;
  BITMAPFILEHEADER bfh;
  long l, lngSize;

  GetClientRect(rct);

  if ( (pdc=GetDC()) == NULL )
    return (long)FALSE;

  if ( bmp.CreateBitmap(rct.Width(),rct.Height(),pdc->GetDeviceCaps(PLANES),pdc->GetDeviceCaps(BITSPIXEL),NULL) == 0 ) {
    ReleaseDC(pdc);
    return (long)FALSE; }
  HBITMAP hbmp=(HBITMAP)bmp.GetSafeHandle();

  if ( dcTmp.CreateCompatibleDC(pdc) == 0 ) {
    ReleaseDC(pdc);
    return (long)FALSE; }
  HDC hdc=dcTmp.GetSafeHdc();

  if ( (bmpOld=dcTmp.SelectObject(&bmp)) == NULL ) {
    ReleaseDC(pdc);
    return (long)FALSE; }

  if ( dcTmp.BitBlt(0,0,rct.Width(),rct.Height(),pdc,0,0,SRCCOPY) == 0 ) {
    dcTmp.SelectObject(bmpOld);
    ReleaseDC(pdc);
    return (long)FALSE; }

  dcTmp.SelectObject(bmpOld);
  ReleaseDC(pdc);

  long len = sizeof(BITMAPINFOHEADER)+4*rct.Width()*rct.Height();

  if ( (lp = (BITMAPINFO *)GlobalAllocPtr(GHND,len)) == NULL ) {
    bmp.DeleteObject();
    return (long)FALSE; }
  lp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  LPVOID lpv = ((LPBYTE)lp)+sizeof(BITMAPINFOHEADER);

  if ( (l=::GetDIBits(hdc,hbmp,0,0,NULL,lp,DIB_RGB_COLORS)) == 0 ) {
    GlobalFreePtr((LPVOID)lp);
    bmp.DeleteObject();
    return (long)FALSE; }

  if ( ::GetDIBits(hdc,hbmp,0,l,lpv, lp, DIB_RGB_COLORS) == 0 ) {
    GlobalFreePtr((LPVOID)lp);
    bmp.DeleteObject();
    return (long)FALSE; }

  bmp.DeleteObject();

  lngSize = ( lp->bmiHeader.biSizeImage != 0 ? lp->bmiHeader.biSizeImage : 4*rct.Width()*rct.Height() );

  bfh.bfType = 'M'*256+'B';
  bfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lngSize;
  bfh.bfReserved1 = 0;
  bfh.bfReserved2 = 0;
  bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

  if ( f.Open(strFName,CFile::modeCreate|CFile::modeWrite) == NULL ) {
    GlobalFreePtr((LPVOID)lp);
    return (long)FALSE; }

  f.Write(&bfh,sizeof(BITMAPFILEHEADER));
  f.Write(lp,sizeof(BITMAPINFOHEADER));
  f.Write(lpv,lngSize);

  f.Close();
  GlobalFreePtr((LPVOID)lp);
  return (long)TRUE;
}

BTW, unfortunately, I have verified that this code only works when the 
screen color depth is 24-bit. Otherwise, I get corrupted BMP files 
(though I couldn't tell you the exact nature of the corruption). ( It 
should work fine for just extracting CBitmap objects, though.)

Anyway, if anyone could point me in the direction of a way with which to 
save the CBitmap object to file regardless of screen color depth, I would 
be indebted.

                                        Joao Mendes
                                        MegaMedia, S.A.

"We're fools to make war on our brothers in arms." - Mark Knopfler

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.2

mQBNAzKu3TgAAAECAL8+YSEFZ0XrlBMu9t2xDq3rhpWZoscP83VrX5MevAm3UOd6
fOtDKsJxsWugnVMexo50NfBjeWOHz5nA1b9hYx0ABRG0H0pvYW8gTWVuZGVzIDxq
bW1tQG1lZ2FtZWRpYS5wdD4=
=sspP
-----END PGP PUBLIC KEY BLOCK-----

-----From: "Manyam Khaja" 

Here is the code I use to capture the screen contents of a window:

int CaptureWindowScreenToBitmap(CWnd* wnd, HBITMAP* bitmap)
{
    RECT r;
    CClientDC dc(wnd);
    HDC         hScrDC, hMemDC;         // screen DC and memory DC
    HBITMAP     hBitmap, hOldBitmap;    // handles to deice-dependent
bitmaps

    wnd->GetClientRect(&r);
    hScrDC = dc.GetSafeHdc();
    hMemDC = CreateCompatibleDC(hScrDC);
  
    // create a bitmap compatible with the screen DC
    hBitmap = CreateCompatibleBitmap(hScrDC, r.right, r.bottom);

    // select new bitmap into memory DC
    hOldBitmap = (HBITMAP) SelectObject(hMemDC, hBitmap);

    // bitblt screen DC to memory DC
    BitBlt(hMemDC, 0, 0, r.right, r.bottom, hScrDC, 0, 0, SRCCOPY);

    // select old bitmap back into memory DC and get handle to
    // bitmap of the screen
    *bitmap = (HBITMAP) SelectObject(hMemDC, hOldBitmap);

    // clean up
    DeleteDC(hScrDC);
    DeleteDC(hMemDC);

    return 0;
}

incase you need it, here is the code to paste the bitmap back to the
window screen:

int PasteBitmapToWindowScreen(CWnd* wnd, HBITMAP* bitmap)
{
    HDC hScrDC, hMemDC;         // screen DC and memory DC
    CClientDC dc(wnd);
    hScrDC = dc.GetSafeHdc();
    hMemDC = CreateCompatibleDC(hScrDC);
    SelectObject(hMemDC, *bitmap);
    RECT r;
    wnd->GetClientRect(&r);
    BitBlt(hScrDC, 0, 0, r.right, r.bottom, hMemDC, 0, 0, SRCCOPY);
    DeleteDC(hScrDC);
    DeleteDC(hMemDC);

    return 0;
}

Hope that helps,
-Manyam


Gary Krone wrote:
> 
> Environment:    VC++ 4.2-flat, WinNT 4.0
> 
> This has got to be simple!
> 
> What I want to know is how you can take an image drawn on a window and make
> a CBitmap Object out of it ( Or similar way to take a 'snapshot' of the
> screen image for later use ).  The catch is the image doesn't exist previous
> to being drawn on the window surface.  If anyone has some sample code on how
> to do this it would be greatly appreciated.
> Gary Krone
> gkrone@inconsys.com
> gkrone@execpc.com
-----From: Roma 

Gary Krone wrote:
> 
> Environment:    VC++ 4.2-flat, WinNT 4.0
> 
> This has got to be simple!
> 
> What I want to know is how you can take an image drawn on a window and make
> a CBitmap Object out of it ( Or similar way to take a 'snapshot' of the
> screen image for later use ).  The catch is the image doesn't exist previous
> to being drawn on the window surface.  If anyone has some sample code on how
> to do this it would be greatly appreciated.
> Gary Krone
> gkrone@inconsys.com
> gkrone@execpc.com
Hi,
here is a code from one my old program. I didn't try it under winNT, it
was written on 
MSVC 1.5 on WFW, but I hope there is no difference in this things:

clas CSomeView : public CView
{
  ...
  CBitmap m_Picture;
  ...
};


void CSomeView::DrawAndStorePicture()
{
    CClientDC *pDC = new CClientDC(this);
    
    //Actual drawing to the window
    PaintPicture(pDC);
    
    
    //Now, let's copy just created image into bitmap.
    //In WFW this is true - other processes can't overlap our window,
but in Win32 I don't
    //know what will happen if your window will be overlapped by other
window at the moment
    //between drawing and BitBlt.

    CDC MemDC;
    MemDC.CreateCompatibleDC(pDC);
                                          
    CRect ClientRect;
    GetClientRect(ClientRect);
                                          
    m_Picture.DeleteObject();
    m_Picture.CreateCompatibleBitmap(pDC, ClientRect.Width(),
ClientRect.Height());
    
    CBitmap* pOldBmp = m_MemDC.SelectObject(&m_Picture);
    
    //This call copy bits from screen to the bitmap, selected into
memory dc.
    MemDC.BitBlt(0, 0, ClientRect.Width(), ClientRect.Height(), pDC, 0,
0, SRCCOPY);
    
    MemDC.SelectObject(pOldBmp);
}

HTH,
-Roma
roma@neonet.lv
-----From: Pal_Sukhram/svoa0008@ssb.com


--openmail-part-09a2d75c-00000001
Content-Type: text/plain; charset=US-ASCII; name="RE:"




Become an MFC-L member | Вернуться в корень Архива |