免費論壇 繁體 | 簡體
Sclub交友聊天~加入聊天室當版主
分享
返回列表 发帖

自定义区域截图

①、实现的原理:
点击截图按钮时,弹出一屏幕大小的模态对话框,将整个屏幕的图像画到此模态对话框上面,之后,在此对话框上面利用橡皮筋类进行自定义区域的截图操作!
===================================================
②、插入一对话框资源:
去掉所有子控件,并设置其 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);
}

返回列表