265 lines
13 KiB
C++
265 lines
13 KiB
C++
// ==========================================================================
|
||
// Class Implementation : COXScreenGrabber
|
||
// ==========================================================================
|
||
|
||
// Source file : oxscreengrab.cpp
|
||
|
||
// Version: 9.3
|
||
|
||
// This software along with its related components, documentation and files ("The Libraries")
|
||
// is ?1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
||
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
||
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
||
// to obtain this file, or directly from our office. For a copy of the license governing
|
||
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
||
|
||
// //////////////////////////////////////////////////////////////////////////
|
||
|
||
#include "stdafx.h" // standard MFC include
|
||
#include "oxscreengrab.h" // file header
|
||
|
||
|
||
#ifdef _DEBUG
|
||
#undef THIS_FILE
|
||
static char BASED_CODE THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
IMPLEMENT_DYNAMIC(COXScreenGrabber, CObject)
|
||
|
||
#define new DEBUG_NEW
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Definition of static members
|
||
|
||
// Data members -------------------------------------------------------------
|
||
// protected:
|
||
|
||
// private:
|
||
|
||
// Member functions ---------------------------------------------------------
|
||
// public:
|
||
|
||
COXScreenGrabber::COXScreenGrabber()
|
||
{
|
||
}
|
||
|
||
BOOL COXScreenGrabber::GrabFullWindow(CWnd* pWnd /* = NULL */)
|
||
{
|
||
CRect WndRect(0, 0, 0, 0);
|
||
|
||
if (!PrepareWindow(FALSE, WndRect, pWnd))
|
||
return FALSE;
|
||
|
||
return GrabRectangle(WndRect);
|
||
}
|
||
|
||
BOOL COXScreenGrabber::GrabClientWindow(CWnd* pWnd /* = NULL */)
|
||
{
|
||
CRect ClientRect(0, 0, 0, 0);
|
||
|
||
if (!PrepareWindow(TRUE, ClientRect, pWnd))
|
||
return FALSE;
|
||
|
||
return GrabRectangle(ClientRect);
|
||
}
|
||
|
||
BOOL COXScreenGrabber::GrabRectangle(CRect SrcRect)
|
||
{
|
||
CDC SrcDC, MemDC;
|
||
|
||
// Check For an empty rectangle
|
||
if(SrcRect.IsRectEmpty())
|
||
return FALSE;
|
||
|
||
MSG msg;
|
||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0)
|
||
{
|
||
TranslateMessage(&msg);
|
||
DispatchMessage(&msg);
|
||
}
|
||
|
||
// create a DC for the screen and create
|
||
// a memory DC compatible to screen DC
|
||
if (!SrcDC.CreateDC(_T("DISPLAY"), NULL, NULL, NULL))
|
||
return FALSE;
|
||
if (!MemDC.CreateCompatibleDC(&SrcDC))
|
||
{
|
||
SrcDC.DeleteDC();
|
||
return FALSE;
|
||
}
|
||
|
||
// get screen resolution
|
||
int nXScrn = SrcDC.GetDeviceCaps(HORZRES);
|
||
int nYScrn = SrcDC.GetDeviceCaps(VERTRES);
|
||
|
||
#if(WINVER >= 0x0500)
|
||
|
||
DISPLAY_DEVICE display;
|
||
display.cb = sizeof(DISPLAY_DEVICE);
|
||
if (EnumDisplayDevices(NULL, 1, &display, 0))
|
||
{
|
||
DEVMODE devMode;
|
||
devMode.dmSize = sizeof(DEVMODE);
|
||
if (EnumDisplaySettings((LPCTSTR)&display.DeviceName[0], ENUM_CURRENT_SETTINGS, &devMode))
|
||
{
|
||
// This assumes that the second monitor is set to draw to the 'right' of the first one.
|
||
nXScrn += devMode.dmPelsWidth;
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
// make sure window rectangle is visible
|
||
if (SrcRect.left < 0)
|
||
SrcRect.left = 0;
|
||
if (SrcRect.top < 0)
|
||
SrcRect.top = 0;
|
||
if (SrcRect.right > nXScrn)
|
||
SrcRect.right = nXScrn;
|
||
if (SrcRect.bottom > nYScrn)
|
||
SrcRect.bottom = nYScrn;
|
||
|
||
// create a bitmap compatible with the screen DC
|
||
CBitmap ScreenBMP;
|
||
if(!ScreenBMP.CreateCompatibleBitmap(&SrcDC, SrcRect.Width(), SrcRect.Height()))
|
||
{
|
||
SrcDC.DeleteDC();
|
||
MemDC.DeleteDC();
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
// select new bitmap into memory DC
|
||
CBitmap* pOldBitmap = MemDC.SelectObject(&ScreenBMP);
|
||
|
||
// bitblt screen DC to memory DC
|
||
MemDC.BitBlt(0, 0, SrcRect.Width(), SrcRect.Height(), &SrcDC, SrcRect.left, SrcRect.top, SRCCOPY);
|
||
|
||
// select old bitmap back into memory DC
|
||
MemDC.SelectObject(pOldBitmap);
|
||
|
||
// Clear previous contents of DIB
|
||
GrabDIB.Empty();
|
||
|
||
CPalette SysPalette;
|
||
COXDIB::GetSystemPalette(&SysPalette);
|
||
GrabDIB.BitmapToDIB(HBITMAP(ScreenBMP), &SysPalette);
|
||
|
||
// clean up
|
||
SrcDC.DeleteDC();
|
||
MemDC.DeleteDC();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
COXDIB* COXScreenGrabber::GetGrabDIB()
|
||
{
|
||
return &GrabDIB;
|
||
}
|
||
|
||
BOOL COXScreenGrabber::GrabTracker(CWnd* pWndFromStartPoint, CPoint StartPoint, CWnd* pWndForRect)
|
||
{
|
||
// some simple validations
|
||
if (pWndFromStartPoint == NULL)
|
||
pWndFromStartPoint = CWnd::GetDesktopWindow();
|
||
|
||
if (pWndForRect == NULL)
|
||
return FALSE;
|
||
|
||
// the startpoint is defined in the client coordinate system of pWndFromStartPoint
|
||
// but the tracking rect will be defined within pWndForRect, so convert
|
||
pWndFromStartPoint->MapWindowPoints(pWndForRect, &StartPoint, 1);
|
||
|
||
CRectTracker tracker;
|
||
|
||
// do the tracking
|
||
if (tracker.TrackRubberBand(pWndForRect, StartPoint, TRUE))
|
||
{
|
||
CRect rect = tracker.m_rect;
|
||
|
||
// because we allowed inversion in the tracking, normalize the rect
|
||
rect.NormalizeRect();
|
||
|
||
// the screengrabber needs screen coordinates
|
||
pWndForRect->ClientToScreen(&rect);
|
||
|
||
return GrabRectangle(rect);
|
||
}
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
#ifdef _DEBUG
|
||
void COXScreenGrabber::Dump(CDumpContext& dc) const
|
||
{
|
||
CObject::Dump(dc);
|
||
}
|
||
|
||
void COXScreenGrabber::AssertValid() const
|
||
{
|
||
CObject::AssertValid();
|
||
}
|
||
#endif
|
||
|
||
// Protected member functions
|
||
BOOL COXScreenGrabber::PrepareWindow(BOOL bClient, CRect& ScrRect, CWnd* pWnd)
|
||
{
|
||
if (pWnd == NULL)
|
||
pWnd = CWnd::GetForegroundWindow();
|
||
if (pWnd == NULL)
|
||
pWnd = CWnd::GetDesktopWindow();
|
||
|
||
ASSERT(pWnd != NULL);
|
||
if (!pWnd->IsWindowVisible())
|
||
return FALSE;
|
||
|
||
if (pWnd == CWnd::GetDesktopWindow())
|
||
{
|
||
// create a DC for the screen and create
|
||
CDC SreenDC;
|
||
if (!SreenDC.CreateDC(_T("DISPLAY"), NULL, NULL, NULL))
|
||
return FALSE;
|
||
|
||
// get screen resolution and set Rect
|
||
ScrRect.left = 0;
|
||
ScrRect.top = 0;
|
||
ScrRect.right = SreenDC.GetDeviceCaps(HORZRES);
|
||
ScrRect.bottom = SreenDC.GetDeviceCaps(VERTRES);
|
||
|
||
SreenDC.DeleteDC();
|
||
}
|
||
else
|
||
{
|
||
// Move window which was selected to top of Z-order for
|
||
// the capture, and make it redraw itself
|
||
pWnd->SetWindowPos(NULL, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOSIZE | SWP_NOMOVE);
|
||
pWnd->UpdateWindow();
|
||
|
||
if (bClient)
|
||
{
|
||
// get the client area dimensions
|
||
pWnd->GetClientRect(&ScrRect);
|
||
|
||
// convert client coords to screen coords
|
||
CPoint pt1(ScrRect.left, ScrRect.top);
|
||
CPoint pt2(ScrRect.right, ScrRect.bottom);
|
||
|
||
pWnd->ClientToScreen(&pt1);
|
||
pWnd->ClientToScreen(&pt2);
|
||
|
||
ScrRect.left = pt1.x;
|
||
ScrRect.top = pt1.y;
|
||
ScrRect.right = pt2.x;
|
||
ScrRect.bottom = pt2.y;
|
||
}
|
||
else
|
||
pWnd->GetWindowRect(&ScrRect);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
COXScreenGrabber::~COXScreenGrabber()
|
||
{
|
||
}
|
||
|