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(pMe mDC,...)
- 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)->Ge tClientRec t(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->CreateCompatibleBitm ap(pFrameW ndDC,
(((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.
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(pMe
- 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)->Ge
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
BmpInfoHdr.biYPelsPerMeter
BmpInfoHdr.biClrUsed = 0;
BmpInfoHdr.biClrImportant = 0;
HDC hDC;
CBitmap* pBMP;
HBITMAP hBMP;
void* pBitmapBuff = calloc((((rtWnd.Width()*3)
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->CreateCompatibleBitm
(((rtWnd.Width()*3)+3)/4)*
hBMP = (HBITMAP) pBMP->GetSafeHandle();
GetDIBits( hDC, hBMP, 0, BmpInfoHdr.biHeight,
pBitmapBuff, (LPBITMAPINFO) &BmpInfoHdr, DIB_RGB_COLORS);
SaveAs24BMPFile("Test.bmp"
delete pBMP;
}
-------
Any comments will be appreciated.
ASKER
Edited text of question
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
}
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=GetDesktopWin dow();
CDC *pDesktopTempDC=pDesktopWn d->GetDC() ;
// Create compatible DC
CDC *pMemDC=new CDC;
CBitmap *pMemBmp=new CBitmap;
pMemDC->CreateCompatibleDC (pDesktopT empDC);
pMemBmp->CreateCompatibleB itmap(pDes ktopTempDC ,
::GetSystemMetrics(SM_CXSC REEN),
::GetSystemMetrics(SM_CYSC REEN));
// Release the temporary DC
pDesktopWnd->ReleaseDC(pDe sktopTempD C);
// Select the memory bitmap
int nSDC=pMemDC->SaveDC();
pMemDC->SelectObject(pMemB mp);
// Render the desktop window into the memory bitmap
GetDesktopWindow()->SendMe ssage(WM_P RINT,
(WPARAM)pMemDC->GetSafeHdc (),
PRF_CLIENT|
PRF_ERASEBKGND|
PRF_CHILDREN|PRF_OWNED);
pMemDC->RestoreDC(nSDC);
delete pMemDC;
// Now pMemBmp should contain the desktops' contents.
with CRichEditCtrl's ...)
CWnd *pDesktopWnd=GetDesktopWin
CDC *pDesktopTempDC=pDesktopWn
// Create compatible DC
CDC *pMemDC=new CDC;
CBitmap *pMemBmp=new CBitmap;
pMemDC->CreateCompatibleDC
pMemBmp->CreateCompatibleB
::GetSystemMetrics(SM_CXSC
::GetSystemMetrics(SM_CYSC
// Release the temporary DC
pDesktopWnd->ReleaseDC(pDe
// Select the memory bitmap
int nSDC=pMemDC->SaveDC();
pMemDC->SelectObject(pMemB
// Render the desktop window into the memory bitmap
GetDesktopWindow()->SendMe
(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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER