Link to home
Start Free TrialLog in
Avatar of okg
okg

asked on

How to Capture Screen ?

Dear experts

I'm using VC++5.0 in WindowNT4.0 SP 3.
I'd like to capture the screen image programatically.
I have to save the certain area which has associated memory DC to 24 bit BMP file on any VGA color depth.
i.e. if my app run on non-true-color VGA environment, memoryDC must be changed and saved as 24 bit type.
For this, I tried as following :
 - CreateCompatibleBitmap(pMemDC,...)
 - Get 24 bit bitmap data with GetDIBits(hBitmap, ..).
But I always get empty data buffer. i.e. '0'.

Following is source code of my app.
--------
CRect rtWnd;
GetDlgItem(IDC_FRAME1)->GetClientRect(rtWnd);

CDC* pFrameWndDC;

BITMAPINFOHEADER      BmpInfoHdr;

BmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
BmpInfoHdr.biWidth = rtWnd.Width();
BmpInfoHdr.biHeight = rtWnd.Height();
BmpInfoHdr.biPlanes = 1;
BmpInfoHdr.biBitCount = 24;
BmpInfoHdr.biCompression = BI_RGB;
BmpInfoHdr.biSizeImage = 0;
BmpInfoHdr.biXPelsPerMeter = 0;
BmpInfoHdr.biYPelsPerMeter = 0;
BmpInfoHdr.biClrUsed = 0;
BmpInfoHdr.biClrImportant = 0;

HDC hDC;
CBitmap* pBMP;
HBITMAP hBMP;

void*   pBitmapBuff = calloc((((rtWnd.Width()*3)+3)/4)*4 * rtWnd.Height() * 3, 1); // 24 Bit
      
int nTotlaFrameCount = m_lstMemDC.GetCount();

POSITION pos = m_lstMemDC.GetHeadPosition();

for(int i=0; i<nTotlaFrameCount; i++)
{
    pFrameWndDC = GetFrameDC(i);
            
    hDC = pFrameWndDC->GetSafeHdc();
    pBMP = new CBitmap;
    pBMP->CreateCompatibleBitmap(pFrameWndDC,
           (((rtWnd.Width()*3)+3)/4)*4, rtWnd.Height());
    hBMP = (HBITMAP) pBMP->GetSafeHandle();

    GetDIBits( hDC, hBMP, 0, BmpInfoHdr.biHeight,  
  pBitmapBuff, (LPBITMAPINFO) &BmpInfoHdr, DIB_RGB_COLORS);

   SaveAs24BMPFile("Test.bmp", pBitmapBuff, BmpInfoHdr);
   delete pBMP;
}
-------

Any comments will be appreciated.
Avatar of okg
okg

ASKER

Edited text of question
Avatar of okg

ASKER

Edited text of question
Avatar of okg

ASKER

Edited text of question
HI! I can`t find BitBlt call in your code. According your code you don`t  capture screen? just create empty bitmap and get it`s buffer.
To capture screen you must select created bitmap into DC and copy screen buffer to them.
for example:
{
ClentToScreen(rtWnd);
HDC hDeskDC = ::GetDC(NULL);
HBITMAP hOldBm = ::SelectObject(hDC,  hBMP);
::BitBlt(hDC, hDeskDC, 0, 0, rtWnd.Width(), rtWnd.Height(), hDeskDC, rtWnd.Left, rtWnd. Top, SRCCOPY);
 ::SelectObject(hDC,  hOldBm );
::ReleaseDC(NULL, hDeskDC);
// now your hBMP contain copy of the screen image
}

I've never tried this, but maybe it works ( it works at least
with CRichEditCtrl's ...)

CWnd *pDesktopWnd=GetDesktopWindow();
CDC  *pDesktopTempDC=pDesktopWnd->GetDC();
// Create compatible DC
CDC  *pMemDC=new CDC;
CBitmap *pMemBmp=new CBitmap;
pMemDC->CreateCompatibleDC(pDesktopTempDC);
pMemBmp->CreateCompatibleBitmap(pDesktopTempDC,
                                ::GetSystemMetrics(SM_CXSCREEN),
                                ::GetSystemMetrics(SM_CYSCREEN));
// Release the temporary DC
pDesktopWnd->ReleaseDC(pDesktopTempDC);

// Select the memory bitmap
int nSDC=pMemDC->SaveDC();
pMemDC->SelectObject(pMemBmp);
// Render the desktop window into the memory bitmap
GetDesktopWindow()->SendMessage(WM_PRINT,
                                (WPARAM)pMemDC->GetSafeHdc(),
                                PRF_CLIENT|
                                PRF_ERASEBKGND|
                                PRF_CHILDREN|PRF_OWNED);
pMemDC->RestoreDC(nSDC);
delete pMemDC;

// Now pMemBmp should contain the desktops' contents.
ASKER CERTIFIED SOLUTION
Avatar of atari
atari

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial