①、实现的原理:
点击截图按钮时,弹出一屏幕大小的模态对话框,将整个屏幕的图像画到此模态对话框上面,之后,在此对话框上面利用橡皮筋类进行自定义区域的截图操作!
===================================================
②、插入一对话框资源:
去掉所有子控件,并设置其 Title Bar 属性为 FALSE;
关联对话框类:CCaptureDlg
===================================================
③、在“开始截图”按钮中进行模态对话框的弹出:
CCaptureDlg dlg;
dlg.DoModal();
===================================================
④、CCaptureDlg 类的初始化函数中添加如下代码:
// CCaptureDlg::OnInitDialog() 函数中添加:
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
MoveWindow(-3, -3, screenWidth+6, screenHeight+6);
//SetWindowPos(&wndTopMost, -3, -3, screenWidth+6, screenHeight+6, SWP_SHOWWINDOW);
m_rectTracker.m_nStyle = CRectTracker::resizeOutside | CRectTracker::dottedLine;
m_rectTracker.m_rect.SetRect(0, 0, 0, 0);
===================================================
⑤、将整个屏幕的内容作为 CCaptureDlg 对话框的背景:
1》CCaptureDlg 构造函数中添加如下代码:CopyScreenToBitmap(m_ScreenBmp);
2》CCaptureDlg 析构函数中添加如下代码:m_ScreenBmp.DeleteObject();
响应 WM_ERASEBKGND 消息,在响应函数中添加如下代码:
BOOL CCaptureDlg::OnEraseBkgnd(CDC* pDC)
{
CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.SelectObject(&m_ScreenBmp);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
memDC.DeleteDC();
return TRUE;
return CDialog::OnEraseBkgnd(pDC);
}
其中 CopyScreenToBitmap 函数的定义如下:
BOOL CopyScreenToBitmap(CBitmap &tBmp)
{
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
CDC *pDC = CDC::FromHandle(::GetDC(NULL));
CDC memDc;
memDc.CreateCompatibleDC(pDC);
CBitmap *pOldBmp = NULL;
tBmp.CreateCompatibleBitmap(pDC, screenWidth, screenHeight);
pOldBmp = memDc.SelectObject(&tBmp);
memDc.BitBlt(0, 0, screenWidth, screenHeight, pDC, 0, 0, SRCCOPY);
memDc.SelectObject(pOldBmp);
memDc.DeleteDC();
::ReleaseDC(NULL, pDC->m_hDC);
return TRUE;
}
===================================================
⑥、CCaptureDlg 类中橡皮筋类对象的构造及初始化:
// CCaptureDlg.h
CRectTracker m_rectTracker;
// CCaptureDlg.cpp
m_rectTracker.m_nStyle = CRectTracker::resizeOutside | CRectTracker::dottedLine;
m_rectTracker.m_rect.SetRect(0, 0, 0, 0);
===================================================
⑦、左键按下,橡皮筋矩形构建:
void CCaptureDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
if(m_rectTracker.HitTest(point) == CRectTracker::hitNothing)
{
m_rectTracker.TrackRubberBand(this, point, TRUE);
} else {
m_rectTracker.Track(this, point, TRUE);
m_rectTracker.m_rect.NormalizeRect();
}
Invalidate(TRUE);
CDialog::OnLButtonDown(nFlags, point);
}
===================================================
⑧、橡皮筋的绘制:
void CCaptureDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CDialog::OnPaint() for painting messages
CDC *pDC = GetDC();
m_rectTracker.Draw(pDC);
ReleaseDC(pDC);
}
===================================================
⑨、当鼠标放到橡皮筋窗口的边缘时,进行光标样式的改变:
响应 WM_SETCURSOR 消息,并在其响应函数中添加如下代码:
BOOL CCaptureDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (pWnd == this && m_rectTracker.SetCursor(this, nHitTest))
return TRUE;
else
return CDialog::OnSetCursor(pWnd, nHitTest, message);
}
◆◆◆ 遇到的问题及解决办法:
1>、工程改用 Use MFC in a Shared DLL,即:动态链接到MFC运行库;
2>、修改工程的 *.rc 文件,去掉其中的以下语句:#define _AFX_NO_TRACKER_RESOURCES
===================================================
⑩、双击保存图片:
void CCaptureDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHight = GetSystemMetrics(SM_CYSCREEN);
if (m_rectTracker.HitTest(point) != CRectTracker::hitMiddle)
{
return;
}
CDC *pDC = GetDC();
CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.SelectObject(&m_ScreenBmp);
CRect rect;
rect = m_rectTracker.m_rect;
if (rect.left < 0)
{
rect.left = 0;
}
if (rect.top < 0)
{
rect.top = 0;
}
if (rect.bottom > screenHight)
{
rect.bottom = screenHight;
}
if (rect.right > screenWidth)
{
rect.right = screenWidth;
}
CBitmap mBmp, *pOldBmp = NULL;
mBmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CDC dstDC;
dstDC.CreateCompatibleDC(pDC);
pOldBmp = dstDC.SelectObject(&mBmp);
dstDC.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, rect.left, rect.top, SRCCOPY);
CImage img;
img.Attach(mBmp);
img.Save(_T("c:\\123.png"));
mBmp.DeleteObject();
memDC.DeleteDC();
dstDC.DeleteDC();
ReleaseDC(pDC);
CDialog::OnCancel();
//CDialog::OnLButtonDblClk(nFlags, point);
} |