截图工具
//调用
CSnapScreen snap(this);
snap.SetTipBackground(::LoadBitmap(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDB_TIPBG)), CRect(12, 32, 12, 12));
snap.SetTipText(
STRING(IDS_SNAP_INTRODUCIONT1, "按下鼠标左键并拖动选择截取范围。\n\n按下[ESC]或鼠标右键退出。")
, STRING(IDS_SNAP_INTRODUCIONT2, "使用活动矩形调整截取范围。\n\n按下[ENTER]或双击选择区域内部确定截取。\n\n按下[ESC]或鼠标右键重新选取。"));
snap.SetSizeInfoPattern(STRING(IDS_SIZEINFO, "起点坐标: %d, %d\n选取尺寸: %d x %d"));
snap.SetColors(RGB(0, 128, 255), RGB(0, 0, 0), RGB(0, 128, 255));
ServicePTR<IMainView> pMainView(m_pContext, UC_SERVICE_MAINVIEW);
if (pMainView.get())
{
pMainView->SetIsCapture(TRUE);
}
// 获取截图
HBITMAP hBmp = snap.Snap();
if (pMainView.get())
{
pMainView->SetIsCapture(FALSE);
}
if (hBmp == NULL)
{
m_RichEditInput.SetFocus();
return;
}
// 点对点
if (m_pChatSession != NULL && m_pChatSession->GetType() != IChatSession::ST_TEAM)
{
m_RichEditInput.InsertBitmap(-1, hBmp);
}
// 将图片保存到剪切板
HWND hWnd = GetSafeHwnd(); // 获取安全窗口句柄
::OpenClipboard(hWnd); // 打开剪贴板
::EmptyClipboard(); // 清空剪贴板
::SetClipboardData(CF_BITMAP, hBmp); // 将内存中的数据放置到剪贴板
::CloseClipboard(); // 关闭剪贴板
// 清空资源
::DeleteObject(hBmp);
hBmp = NULL;
m_RichEditInput.SetFocus();
// 内容摘要:截屏控制类
#pragma once
#include "SnapScreenWnd.h"
/// <summary>
/// 类名称:CSnapScreen
/// 内容摘要:截屏控制类
/// </summary>
class CSnapScreen
{
public:
// 构造函数
CSnapScreen(CWnd* pParentWnd = NULL);
// 析构函数
virtual ~CSnapScreen();
// 截取屏幕图片
HBITMAP Snap(BOOL bFullScreen = FALSE);
/// <summary>
/// 设置提示背景
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置提示背景
/// </remarks>
/// <param name="hBitmap">位图句柄</param>
/// <param name="rcMargin">边界区域</param>
/// <returns>返回:无
/// </returns>
inline void SetTipBackground(HBITMAP hBitmap, LPRECT rcMargin)
{
m_wndSnap.SetTipBackground(hBitmap, rcMargin);
}
/// <summary>
/// 设置提示文本
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置提示文本
/// </remarks>
/// <param name="lpTipText1">提示文本</param>
/// <param name="lpTipText2">提示文本</param>
/// <returns>返回:无
/// </returns>
inline void SetTipText(LPCTSTR lpTipText1, LPCTSTR lpTipText2)
{
m_wndSnap.SetTipText(lpTipText1, lpTipText2);
}
/// <summary>
/// 设置大小信息式样
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置大小信息式样
/// </remarks>
/// <param name="lpSizeInfoPattern">大小信息式样</param>
/// <returns>返回:无
/// </returns>
inline void SetSizeInfoPattern(LPCTSTR lpSizeInfoPattern)
{
m_wndSnap.SetSizeInfoPattern(lpSizeInfoPattern);
}
/// <summary>
/// 设置颜色
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置颜色
/// </remarks>
/// <param name="clrTracker">追踪者颜色</param>
/// <param name="clrTipText">提示文本颜色</param>
/// <param name="clrSizeInfo">大小信息颜色</param>
/// <returns>返回:无
/// </returns>
inline void SetColors(COLORREF clrTracker, COLORREF clrTipText, COLORREF clrSizeInfo)
{
m_wndSnap.SetColors(clrTracker, clrTipText, clrSizeInfo);
}
protected:
// 截屏窗口类对象
CSnapScreenWnd m_wndSnap;
};
// 内容摘要:截屏窗口类
#pragma once
#include "SnapTracker.h"
#include "ModalWnd.h"
#include "DrawAssist.h"
/// <summary>
/// 类编号:
/// 类名称:CSnapScreenWnd
/// 内容摘要:截屏窗口类
/// </summary>
class CSnapScreenWnd : public CModalWnd
{
DECLARE_DYNAMIC(CSnapScreenWnd)
public:
// 构造函数
CSnapScreenWnd(CWnd* pParentWnd = NULL);
// 析构函数
virtual ~CSnapScreenWnd();
// 设置提示背景
void SetTipBackground(HBITMAP hBitmap, LPRECT rcMargin);
// 设置提示文本
void SetTipText(LPCTSTR lpTipText1, LPCTSTR lpTipText2);
// 设置大小信息式样
void SetSizeInfoPattern(LPCTSTR lpSizeInfoPattern);
// 设置颜色
void SetColors(COLORREF clrTracker, COLORREF clrTipText, COLORREF clrSizeInfo);
// 截取屏幕转化为位图
static HBITMAP CopyScreenToBitmap(LPRECT lpRect = NULL);
// 截取屏幕
HBITMAP SnapScreen();
// 使图片变暗
HBITMAP FadeBitmap(HBITMAP hBmp, int nTrans);
void DrawSelectArea(CBufferDC& dc);
protected:
HBITMAP m_hResult; // 截取的图像
CBitmap m_bmpTipBg; // 操作提示背景
CRect m_rcTipMargin; // 操作提示文字位置
CString m_csTipText1; // 操作提示
CString m_csTipText2; // 操作提示
CString m_csSizeInfoPatt; // 尺寸信息
COLORREF m_clrTipText; // 操作提示文字颜色
COLORREF m_clrSizeInfo; // 尺寸信息颜色
HBITMAP m_hScreenBmp; // 屏幕图像
HBITMAP m_hBackground; // 背景图像
int m_nScreenX; // 屏幕宽度
int m_nScreenY; // 屏幕高度
BOOL m_bDragged; // 已经进行拖动操作
BOOL m_bDragging; // 正在拖动
BOOL m_bShowSizeInfo; // 显示尺寸信息
BOOL m_bShowZoomer; // 显示放大镜
CPoint m_ptStart; // 截取矩形左上角
CRect m_rcTip; // 操作提示位置
BOOL m_bSizing; // 是否在拖动大小
CSnapTracker m_tracker; // 橡皮筋类
BOOL m_bMoveArea; // 是否移动选择区
CPoint m_ptStartMove;
CRect m_rcGragging; // 拖动前的矩形区
int m_nHitType;
// 绘制尺寸信息
void DrawSizeInfo(CDC* pDC, CRect& rect);
// 绘制操作提示
void DrawToolTip(CDC* pDC);
// 绘制放大镜
void DrawZoomer(CDC* pDC);
// 确定截取
void ConfirmSnap();
// 预翻译消息
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
afx_msg void OnPaint(); // 绘制
afx_msg void OnMouseMove(UINT nFlags, CPoint point); // 鼠标移动选中区域
afx_msg void OnLButtonDown(UINT nFlags, CPoint point); // 单击鼠标左键
afx_msg void OnLButtonUp(UINT nFlags, CPoint point); // 释放鼠标左键
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); // 双击鼠标左键
afx_msg void OnRButtonUp(UINT nFlags, CPoint point); // 释放鼠标右键
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); // 设置光标
DECLARE_MESSAGE_MAP()
};
// 内容摘要:截屏窗口类
/*****************************************************************************
* #include *
*****************************************************************************/
#include "stdafx.h"
#include <afxpriv.h>
#include "SnapScreenWnd.h"
#ifdef _DEBUG
# define new DEBUG_NEW
# undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// CSnapScreenWnd
const int TRACKER_INIT_SIZE = 4;
const int TRACKER_INFO_SPACE = 5;
const COLORREF COLOR_TRACKER = RGB(10, 100, 130);
const COLORREF COLOR_TIPTEXT = RGB(0, 0, 0);
const COLORREF COLOR_SIZEINFO = RGB(0, 0, 0);
const CSize DEFAULT_TIP_SIZE = CSize(200, 120);
const int TIP_POSITION = 20;
const int TIP_SPACE = 8;
const LPCTSTR SIZEINFO_PATTERN = _T("Start Point:\t%d, %d\nSelected Size:\t%d x %d");
const LPCTSTR TIP_TEXT_1 = _T("Click and hold on left button, then drag to select target region.\n\nPress [ESC] key or click right button to cancel.");
const LPCTSTR TIP_TEXT_2 = _T("Adjust target region with the rectangle tracker.\n\nPress [ENTER] key or double click selected region to confirm.\n\nPress [ESC] key or click right button to restart.");
const int ZOOMER_SIZE = 32;
const int ZOOMER_RATIO = 4;
/*****************************************************************************
* 类实现 *
*****************************************************************************/
IMPLEMENT_DYNAMIC(CSnapScreenWnd, CModalWnd)
/// <summary>
/// 构造函数
/// </summary>
/// <remarks>
/// 实现流程:
/// 初始化对象
/// </remarks>
/// <param name="pParentWnd">父窗口对象指针</param>
/// <returns>返回:无
/// </returns>
CSnapScreenWnd::CSnapScreenWnd(CWnd* pParentWnd /*=NULL*/)
: CModalWnd(pParentWnd)
, m_rcTipMargin(TIP_SPACE, TIP_SPACE, TIP_SPACE, TIP_SPACE)
, m_clrTipText(COLOR_TIPTEXT)
, m_clrSizeInfo(COLOR_SIZEINFO)
, m_csSizeInfoPatt(SIZEINFO_PATTERN)
, m_csTipText1(TIP_TEXT_1)
, m_csTipText2(TIP_TEXT_2)
, m_bDragging(FALSE)
, m_bDragged(FALSE)
, m_bShowSizeInfo(FALSE)
, m_bShowZoomer(TRUE)
, m_ptStart(0, 0)
, m_bMoveArea(FALSE)
, m_bSizing(FALSE)
, m_nHitType(-1)
{
m_hScreenBmp = CopyScreenToBitmap(NULL);
m_hBackground = FadeBitmap(CopyScreenToBitmap(NULL), 2);
m_nScreenX = ::GetSystemMetrics(SM_CXSCREEN);
m_nScreenY = ::GetSystemMetrics(SM_CYSCREEN);
m_tracker.m_nStyle = CRectTracker::solidLine | CRectTracker::resizeInside |
CRectTracker::dottedLine | CRectTracker::hatchedBorder;
m_tracker.m_rect.SetRect(-1, -1, -1, -1);
m_tracker.SetRectColor(COLOR_TRACKER);
}
/// <summary>
/// 析构函数
/// </summary>
/// <remarks>
/// 实现流程:删除背景对象
/// </remarks>
/// <returns>返回:无
/// </returns>
CSnapScreenWnd::~CSnapScreenWnd()
{
if (m_hBackground)
{
::DeleteObject(m_hBackground);
}
if (m_hScreenBmp)
{
::DeleteObject(m_hScreenBmp);
}
}
BEGIN_MESSAGE_MAP(CSnapScreenWnd, CWnd)
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONUP()
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
/// <summary>
/// 绘制
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、绘制背景
/// 2、已经进行拖动操作,进行橡皮筋等的绘制
/// 3、绘制放大镜
/// 4、绘制操作提示
/// </remarks>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::OnPaint()
{
CPaintDC dc(this);
CBufferDC dcBuffer(dc);
// 绘制背景
HDC hMemDC = ::CreateCompatibleDC(dcBuffer.GetSafeHdc());
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, m_hBackground);
::BitBlt(dcBuffer.GetSafeHdc(), 0, 0, m_nScreenX, m_nScreenY, hMemDC, 0, 0, SRCCOPY);
::SelectObject(hMemDC, hOldBmp);
::DeleteDC(hMemDC);
// 画选择区域
DrawSelectArea(dcBuffer);
// 已经进行拖动操作
if (m_bDragged)
{
// 绘制橡皮筋
m_tracker.Draw(&dcBuffer);
// 绘制尺寸信息
if (m_bShowSizeInfo)
{
CRect rect;
m_tracker.GetTrueRect(&rect);
DrawSizeInfo(&dcBuffer, rect);
}
}
// 绘制放大镜
if (m_bShowZoomer)
{
DrawZoomer(&dcBuffer);
}
// 绘制操作提示
DrawToolTip(&dcBuffer);
}
/// <summary>
/// 绘制尺寸信息
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置字体
/// 2、设置画布参数
/// 3、计算文字尺寸
/// 4、获取当前坐标
/// 5、绘制尺寸信息
/// </remarks>
/// <param name="pDC">设备上下文类对象指针</param>
/// <param name="rect">相关区域</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::DrawSizeInfo(CDC* pDC, CRect& rect)
{
// 设置字体
LOGFONT lfIcon;
::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIcon), &lfIcon, 0);
CFont font;
font.CreateFontIndirect(&lfIcon);
CFontDC dcFont(pDC, &font, m_clrSizeInfo);
// 设置画布参数
CPenDC dcPen(pDC->GetSafeHdc(), m_clrSizeInfo);
CBrush* pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrushDC dcBrush(pDC, pBrush);
int nOldBkMode = pDC->SetBkMode(TRANSPARENT);
// 计算文字尺寸
CString csText;
csText.Format(m_csSizeInfoPatt, rect.left, rect.top, rect.Width(), rect.Height());
CRect rcTemp(0, 0, 0, 0);
pDC->DrawText(csText, -1, &rcTemp, DT_CALCRECT | DT_LEFT | DT_TOP | DT_EXPANDTABS);
CSize szText(rcTemp.Width(), rcTemp.Height());
// 当前坐标
CPoint ptStart;
GetCursorPos(&ptStart);
CRect rcInfo(ptStart.x + TRACKER_INFO_SPACE, ptStart.y - TRACKER_INFO_SPACE * 3 - szText.cy,
ptStart.x + TRACKER_INFO_SPACE * 3 + szText.cx, ptStart.y - TRACKER_INFO_SPACE);
// 当right 大于m_nScreenX
if (rcInfo.right > m_nScreenX)
{
CRect rcTemp(rcInfo);
rcTemp.right = ptStart.x - TRACKER_INFO_SPACE;
rcTemp.left = ptStart.x - TRACKER_INFO_SPACE * 3 - szText.cx;
rcInfo = rcTemp;
}
// 当top小于
if (rcInfo.top < 0)
{
CRect rcTemp(rcInfo);
rcTemp.top = ptStart.y + TRACKER_INFO_SPACE;
rcTemp.bottom = ptStart.y + TRACKER_INFO_SPACE * 3 + szText.cy;
rcInfo = rcTemp;
}
pDC->Rectangle(&rcInfo);
rcInfo.OffsetRect(TRACKER_INFO_SPACE, TRACKER_INFO_SPACE);
pDC->DrawText(csText, -1, &rcInfo, DT_LEFT | DT_TOP | DT_EXPANDTABS);
pDC->SetBkMode(nOldBkMode);
}
/// <summary>
/// 绘制操作提示
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、获取提示背景尺寸
/// 2、光标位置
/// 3、绘制背景
/// 4、设置字体
/// 5、绘制提示文字
/// </remarks>
/// <param name="pDC">设备上下文类对象指针</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::DrawToolTip(CDC* pDC)
{
static int nPosID = 0;
CSize szTip(DEFAULT_TIP_SIZE);
// 获取提示背景尺寸
if (m_bmpTipBg.GetSafeHandle())
{
BITMAP bm;
m_bmpTipBg.GetObject(sizeof(BITMAP), &bm);
szTip.cx = bm.bmWidth;
szTip.cy = bm.bmHeight;
}
CRect rcTip[2];
rcTip[0] = CRect(CPoint(TIP_POSITION, TIP_POSITION), szTip);
rcTip[1] = CRect(CPoint(m_nScreenX - TIP_POSITION - szTip.cx, TIP_POSITION), szTip);
CPoint ptCursor;
::GetCursorPos(&ptCursor);
// 光标位置
if (rcTip[nPosID].PtInRect(ptCursor))
{
nPosID = !nPosID;
}
CRect rcDest(rcTip[nPosID]);
// 绘制背景
// 图片
if (m_bmpTipBg.GetSafeHandle())
{
CDC dcBg;
dcBg.CreateCompatibleDC(pDC);
CBitmap* bmpOld = dcBg.SelectObject(&m_bmpTipBg);
pDC->BitBlt(rcDest.left, rcDest.top, rcDest.Width(), rcDest.Height(),
&dcBg, 0, 0, SRCCOPY);
dcBg.SelectObject(bmpOld);
}
// 非图片
else
{
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPenDC dcPen(pDC, &pen);
CBrushDC dcBrush(pDC->GetSafeHdc(), RGB(255, 255, 255));
pDC->Rectangle(&rcDest);
}
// 设置字体
LOGFONT lfIcon;
::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIcon), &lfIcon, 0);
CFont font;
font.CreateFontIndirect(&lfIcon);
CFontDC dcFont(pDC, &font, m_clrTipText);
// 绘制提示文字
int nOldBkMode = pDC->SetBkMode(TRANSPARENT);
CString csTipText = (m_bDragged && !m_bDragging) ? m_csTipText2 : m_csTipText1;
rcDest.DeflateRect(&m_rcTipMargin);
pDC->DrawText(csTipText, &rcDest, DT_LEFT | DT_TOP | DT_WORDBREAK);
pDC->SetBkMode(nOldBkMode);
}
/// <summary>
/// 绘制放大镜
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、绘制放大镜
/// </remarks>
/// <param name="pDC">设备上下文类对象指针</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::DrawZoomer(CDC* pDC)
{
return;
static int nPosID = 0;
CSize szZoomer((ZOOMER_SIZE + 3) * ZOOMER_RATIO, (ZOOMER_SIZE + 3) * ZOOMER_RATIO);
CRect rcZoomer[2];
rcZoomer[0] = CRect(CPoint(TIP_POSITION, m_nScreenY - TIP_POSITION - szZoomer.cy), szZoomer);
rcZoomer[1] = CRect(CPoint(m_nScreenX - TIP_POSITION - szZoomer.cx, m_nScreenY - TIP_POSITION - szZoomer.cy), szZoomer);
CPoint ptCursor;
::GetCursorPos(&ptCursor);
// 光标位置
if (rcZoomer[nPosID].PtInRect(ptCursor))
{
nPosID = !nPosID;
}
// 绘制放大镜
CRect rcDest(rcZoomer[nPosID]);
pDC->FillSolidRect(&rcDest, RGB(0, 0, 0));
rcDest.DeflateRect(ZOOMER_RATIO, ZOOMER_RATIO);
HDC hBgDC = ::CreateCompatibleDC(pDC->GetSafeHdc());
HBITMAP hOldBgBmp = (HBITMAP)::SelectObject(hBgDC, m_hBackground);
HDC hZoomerDC = ::CreateCompatibleDC(hBgDC);
HBITMAP hZoomerBmp = ::CreateCompatibleBitmap(hBgDC, ZOOMER_SIZE + 1, ZOOMER_SIZE + 1);
HBITMAP hOldZoomerBmp = (HBITMAP)::SelectObject(hZoomerDC, hZoomerBmp);
ptCursor.Offset(-ZOOMER_SIZE / 2, -ZOOMER_SIZE / 2);
::BitBlt(hZoomerDC, 0, 0, ZOOMER_SIZE + 1, ZOOMER_SIZE + 1,
hBgDC, ptCursor.x, ptCursor.y, SRCCOPY);
CPenDC dcPen(hZoomerDC, RGB(0, 0, 0));
CPoint ptCenter(ZOOMER_SIZE / 2, ZOOMER_SIZE / 2);
::MoveToEx(hZoomerDC, ptCenter.x - 3, ptCenter.y, NULL);
::LineTo(hZoomerDC, ptCenter.x + 4, ptCenter.y);
::MoveToEx(hZoomerDC, ptCenter.x, ptCenter.y - 3, NULL);
::LineTo(hZoomerDC, ptCenter.x, ptCenter.y + 4);
::StretchBlt(pDC->GetSafeHdc(), rcDest.left, rcDest.top, rcDest.Width(), rcDest.Height(),
hZoomerDC, 0, 0, ZOOMER_SIZE + 1, ZOOMER_SIZE + 1, SRCCOPY);
// 清除对象
::SelectObject(hBgDC, hOldBgBmp);
::DeleteDC(hBgDC);
::SelectObject(hZoomerDC, hOldZoomerBmp);
::DeleteDC(hZoomerDC);
::DeleteObject(hZoomerBmp);
}
/// <summary>
/// 单击鼠标左键
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、第一次画矩形
/// </remarks>
/// <param name="nFlags">设备上下文类对象指针</param>
/// <param name="point">设备上下文类对象指针</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
m_nHitType = m_tracker.HitTest(point);
if (m_nHitType < 0)
{
//第一次画矩形
if (!m_bDragged)
{
m_ptStart = point;
m_bDragging = TRUE;
m_bDragged = TRUE;
m_bShowSizeInfo = TRUE;
m_tracker.m_rect.SetRect(point.x, point.y,
point.x + TRACKER_INIT_SIZE, point.y + TRACKER_INIT_SIZE);
Invalidate(FALSE);
}
}
// 显示
else if( CSnapTracker::hitMiddle == m_nHitType )
{
m_bShowSizeInfo = TRUE;
m_bShowZoomer = TRUE;
Invalidate(FALSE);
if (m_bDragged)
{
m_bMoveArea = TRUE;
m_ptStartMove = point;
//m_tracker.Track(this, point, TRUE);
Invalidate(FALSE);
}
}
else
{
m_rcGragging = m_tracker.m_rect;
m_bShowSizeInfo = TRUE;
m_bShowZoomer = TRUE;
m_bSizing = TRUE;
m_bDragging = TRUE;
Invalidate(FALSE);
}
CWnd::OnLButtonDown(nFlags, point);
}
/// <summary>
/// 鼠标移动选中区域
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、鼠标移动选中区域
/// </remarks>
/// <param name="nFlags">动作标识</param>
/// <param name="point">消息对象指针</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::OnMouseMove(UINT nFlags, CPoint point)
{
// 未进行拖动
if (!m_bDragged && !m_bDragging)
{
Invalidate(FALSE);
}
else if( m_bMoveArea )
{
m_tracker.m_rect.OffsetRect( point.x - m_ptStartMove.x,point.y - m_ptStartMove.y );
m_ptStartMove = point;
Invalidate(FALSE);
}
//拖动中
else if ( m_bDragging && m_bSizing)
{
switch( m_nHitType )
{
case CSnapTracker::hitTopLeft: // 左上角,以右下角为基准坐标
m_tracker.m_rect.SetRect(m_rcGragging.right, m_rcGragging.bottom, point.x, point.y);
break;
case CSnapTracker::hitTopRight: // 右上角,以左下角为基准坐标
m_tracker.m_rect.SetRect(m_rcGragging.left, m_rcGragging.bottom, point.x, point.y);
break;
case CSnapTracker::hitBottomRight: // 右下角
m_tracker.m_rect.SetRect(m_rcGragging.left, m_rcGragging.top, point.x, point.y);
break;
case CSnapTracker::hitBottomLeft: // 左下角
m_tracker.m_rect.SetRect(m_rcGragging.right, m_rcGragging.top, point.x, point.y);
break;
case CSnapTracker::hitTop: // 上边
m_tracker.m_rect.SetRect(m_rcGragging.left, m_rcGragging.bottom, m_rcGragging.right, point.y);
break;
case CSnapTracker::hitRight: // 右边
m_tracker.m_rect.SetRect(m_rcGragging.left, m_rcGragging.top, point.x, m_rcGragging.bottom);
break;
case CSnapTracker::hitBottom: // 底边
m_tracker.m_rect.SetRect(m_rcGragging.left, m_rcGragging.top, m_rcGragging.right, point.y);
break;
case CSnapTracker::hitLeft: // 左边
m_tracker.m_rect.SetRect(m_rcGragging.right, m_rcGragging.top, point.x, m_rcGragging.bottom);
break;
}
Invalidate(FALSE);
}
else if( m_bDragging )
{
m_tracker.m_rect.SetRect(m_ptStart.x,m_ptStart.y, point.x, point.y);
Invalidate(FALSE);
}
CWnd::OnMouseMove(nFlags, point);
}
/// <summary>
/// 释放鼠标左键
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、释放鼠标左键
/// </remarks>
/// <param name="nFlags">动作标识</param>
/// <param name="point">鼠标位置</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::OnLButtonUp(UINT nFlags, CPoint point)
{
BOOL bDragging = m_bDragging;
m_bShowSizeInfo = FALSE;
m_bShowZoomer = FALSE;
m_bDragging = FALSE;
m_bMoveArea = FALSE;
m_bSizing = FALSE;
// 拖动中释放鼠标
if (bDragging)
{
Invalidate(FALSE);
m_tracker.SetCursor(this, HTCLIENT);
}
CWnd::OnLButtonUp(nFlags, point);
}
/// <summary>
/// 双击鼠标左键
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、双击鼠标左键确认截屏
/// </remarks>
/// <param name="nFlags">动作标识</param>
/// <param name="point">鼠标位置</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::OnLButtonDblClk(UINT nFlags, CPoint point)
{
//当前鼠标位置在选中区域
if (m_tracker.HitTest(point) == CRectTracker::hitMiddle)
{
// 确认截屏
ConfirmSnap();
}
CWnd::OnLButtonDblClk(nFlags, point);
}
/// <summary>
/// 释放鼠标右键
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、释放鼠标右键
/// </remarks>
/// <param name="nFlags">动作标识</param>
/// <param name="point">鼠标位置</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::OnRButtonUp(UINT nFlags, CPoint point)
{
// 已经进行拖动操作
if (m_bDragged)
{
m_bDragged = FALSE;
m_bShowZoomer = TRUE;
m_tracker.m_rect.SetRect(-1, -1, -1, -1);
Invalidate(FALSE);
SetCursor(::LoadCursor(0, IDC_CROSS));
}
// 结束截屏
else
{
EndModalLoop(0);
}
CWnd::OnRButtonUp(nFlags, point);
}
/// <summary>
/// 设置光标
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置光标
/// </remarks>
/// <param name="pWnd">包含光标的窗口对象</param>
/// <param name="nHitTest">光标位置</param>
/// <param name="message">鼠标消息成员</param>
/// <returns>返回:无
/// </returns>
BOOL CSnapScreenWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// 根据鼠标坐标位置设置光标
if (pWnd == this && m_tracker.SetCursor(this, nHitTest)
&& !m_bDragging && m_bDragged)
{
return TRUE;
}
SetCursor(::LoadCursor(0, (m_bDragged && !m_bDragging) ? IDC_ARROW : IDC_CROSS));
return TRUE;
}
/// <summary>
/// 确定截取
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、确定截取
/// </remarks>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::ConfirmSnap()
{
CRect rcDest;
m_tracker.GetTrueRect(&rcDest);
rcDest &= CRect(0, 0, m_nScreenX, m_nScreenY);
// 确定截取
HDC hBgDC = ::CreateCompatibleDC(0);
HBITMAP hBgOldBmp = (HBITMAP)::SelectObject(hBgDC, m_hScreenBmp);
HDC hDestDC = ::CreateCompatibleDC(0);
m_hResult = ::CreateCompatibleBitmap(hBgDC, rcDest.Width(), rcDest.Height());
HBITMAP hDestOldBmp = (HBITMAP)::SelectObject(hDestDC, m_hResult);
::BitBlt(hDestDC, 0, 0, rcDest.Width(), rcDest.Height(), hBgDC, rcDest.left, rcDest.top, SRCCOPY);
::SelectObject(hBgDC, hBgOldBmp);
::DeleteDC(hBgDC);
::SelectObject(hDestDC, hDestOldBmp);
::DeleteDC(hDestDC);
// 结束截屏
EndModalLoop(IDOK);
}
/// <summary>
/// 截取屏幕转化为位图
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、截取全屏
/// </remarks>
/// <param name="lpRect">消息对象指针</param>
/// <returns>返回:无
/// </returns>
HBITMAP CSnapScreenWnd::CopyScreenToBitmap(LPRECT lpRect /*=NULL*/)
{
CRect rcSrc(0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN));
// 输入区域不为空
if( NULL != lpRect )
{
CRect rcInput;
rcInput.SetRect(lpRect->left,lpRect->top,lpRect->right,lpRect->bottom);
rcInput.NormalizeRect();
if (!rcInput.IsRectEmpty())
{
rcSrc = rcInput;
}
}
// 转化为位图
HDC hScreenDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
HDC hMemoryDC = ::CreateCompatibleDC(hScreenDC);
HBITMAP hBitmap = ::CreateCompatibleBitmap(hScreenDC, rcSrc.Width(), rcSrc.Height());
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
::BitBlt(hMemoryDC, 0, 0, rcSrc.Width(), rcSrc.Height(), hScreenDC, rcSrc.left, rcSrc.top, SRCCOPY);
::SelectObject(hMemoryDC, hOldBmp);
::DeleteDC(hScreenDC);
::DeleteDC(hMemoryDC);
return hBitmap;
}
/// <summary>
/// 预翻译消息
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、预翻译消息
/// </remarks>
/// <param name="pMsg">消息对象指针</param>
/// <returns>返回:无
/// </returns>
BOOL CSnapScreenWnd::PreTranslateMessage(MSG* pMsg)
{
// 键盘按下事件
if (pMsg->message == WM_KEYDOWN)
{
// 判断所按键
switch (pMsg->wParam)
{
case VK_ESCAPE:
// 取消选中
if (m_bDragged)
{
m_bDragged = FALSE;
m_bDragging = FALSE;
m_tracker.m_rect.SetRect(-1,-1,-1,-1);
Invalidate(FALSE);
return TRUE;
}
// 取消截屏
else
{
EndModalLoop(IDCANCEL);
return TRUE;
}
break;
case VK_RETURN:
// 确认截屏
if (m_bDragged && !m_bDragging)
{
ConfirmSnap();
}
}
}
return CWnd::PreTranslateMessage(pMsg);
}
/// <summary>
/// 设置提示背景
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置提示背景
/// </remarks>
/// <param name="hBitmap">位图句柄</param>
/// <param name="rcMargin">边界间距</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::SetTipBackground(HBITMAP hBitmap, LPRECT rcMargin)
{
m_bmpTipBg.DeleteObject();
m_bmpTipBg.Attach(hBitmap);
m_rcTipMargin = rcMargin;
}
/// <summary>
/// 设置提示文本
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置提示文本
/// </remarks>
/// <param name="lpTipText1">提示文本</param>
/// <param name="lpTipText2">提示文本</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::SetTipText(LPCTSTR lpTipText1, LPCTSTR lpTipText2)
{
m_csTipText1 = lpTipText1;
m_csTipText2 = lpTipText2;
}
/// <summary>
/// 设置大小信息式样
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置大小信息式样
/// </remarks>
/// <param name="lpSizeInfoPattern">大小信息式样</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::SetSizeInfoPattern(LPCTSTR lpSizeInfoPattern)
{
m_csSizeInfoPatt = lpSizeInfoPattern;
}
/// <summary>
/// 设置颜色
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、设置颜色
/// </remarks>
/// <param name="clrTracker">tracker颜色</param>
/// <param name="clrTipText">提示文本颜色</param>
/// <param name="clrSizeInfo">尺寸信息颜色</param>
/// <returns>返回:无
/// </returns>
void CSnapScreenWnd::SetColors(COLORREF clrTracker, COLORREF clrTipText, COLORREF clrSizeInfo)
{
m_tracker.SetRectColor(clrTracker);
m_clrTipText = clrTipText;
m_clrSizeInfo = clrSizeInfo;
}
/**
使窗口变暗
hBmp需要变灰的图片句柄
nTrans 转换尺度 2~8 数字也大越暗
*/
HBITMAP CSnapScreenWnd::FadeBitmap(HBITMAP hBmp, int nTrans)
{
BITMAP btm;
GetObject(hBmp, sizeof(BITMAP), &btm);
int nSize = btm.bmWidthBytes * btm.bmHeight;
nSize = btm.bmWidth * btm.bmHeight * btm.bmBitsPixel / 8;
BYTE* lpData = (BYTE*)malloc(sizeof(BYTE) * nSize);
GetBitmapBits(hBmp, nSize, lpData);
for(int i = 0; i < nSize; i++)
{
lpData[i] = lpData[i] / nTrans;
}
SetBitmapBits(hBmp, nSize, lpData);
free(lpData);
return hBmp;
}
#if 0
// 使图片变灰,(黑白色)
HBITMAP CSnapScreenWnd::FadeBitmap(HBITMAP hBmp, int nTrans)
{
HBITMAP hRetBmp = NULL;
if (hBmp)
{
HDC hBufferDC = CreateCompatibleDC(NULL);
HGDIOBJ hPrevBufObject = SelectObject(hBufferDC, hBmp);
HDC hDirectDC = CreateCompatibleDC(NULL); // DC for working
if (hDirectDC)
{
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
BITMAPINFO bmInfo;
ZeroMemory(&bmInfo,sizeof(bmInfo));
bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biWidth = bm.bmWidth;
bmInfo.bmiHeader.biHeight = bm.bmHeight;
bmInfo.bmiHeader.biPlanes = 1;
bmInfo.bmiHeader.biBitCount = 32;
UINT* ptPixels;
HBITMAP hDirectBitmap = CreateDIBSection(hDirectDC,
(BITMAPINFO*)&bmInfo,
DIB_RGB_COLORS,(void**)&ptPixels, NULL, 0);
if (hDirectBitmap)
{
// 将hDirectBitmap放入hDirectDC中处理
HGDIOBJ hPrevBufDirObject = SelectObject(hDirectDC, hDirectBitmap);
// 当前将原hBmp即屏幕的所有像素写入到hDirectDC
// 即需要对像素灰度处理的DC中
BitBlt(hDirectDC,0,0,bm.bmWidth,bm.bmHeight,hBufferDC,0,0,SRCCOPY);
int iAlpha = (int)(255.0 * nTrans / 100.0);
int nSize = bm.bmWidth * bm.bmHeight;
for (int i=0; i<nSize; i++)
{
// 0.212671 * R + 0.715160 * G + 0.072169 * B
int iSrcR = (ptPixels[i]) & 0x00ff0000 >> 16;
int iSrcG = ptPixels[i] & 0x0000ff00 >> 8;
int iSrcB = ptPixels[i] & 0x000000ff;
/**
调整合成颜色的基数
int iGrey = (iSrcR * 54 + iSrcG * 182 + iSrcB * 19) >> 8;
*/
int iGrey = (iSrcR * 0 + iSrcG * 0 + iSrcB * 0) >> 8;
COLORREF Col =iGrey ; //RGB(iGrey, iGrey, iGrey) ;
ptPixels[i] = RGB(
(GetBValue( Col ) * iAlpha + iSrcB * (255 - iAlpha)) >> 8,
(GetGValue( Col ) * iAlpha + iSrcG * (255 - iAlpha)) >> 8,
(GetRValue( Col ) * iAlpha + iSrcR * (255 - iAlpha)) >> 8 );
}
SelectObject(hDirectDC,hPrevBufDirObject);
hRetBmp = hDirectBitmap;
}
DeleteDC(hDirectDC);
}
SelectObject(hBufferDC, hPrevBufObject);
DeleteDC(hBufferDC);
}
return hRetBmp;
}
#endif
void CSnapScreenWnd::DrawSelectArea(CBufferDC& dcBuffer)
{
CRect rcDest;
m_tracker.GetTrueRect(&rcDest);
rcDest &= CRect(0, 0, m_nScreenX, m_nScreenY);
HDC hMemDC = ::CreateCompatibleDC(dcBuffer.GetSafeHdc());
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, m_hScreenBmp);
::BitBlt(dcBuffer.GetSafeHdc(), rcDest.left, rcDest.top, rcDest.Width(), rcDest.Height(),
hMemDC, rcDest.left, rcDest.top, SRCCOPY);
::SelectObject(hMemDC, hOldBmp);
::DeleteDC(hMemDC);
}
/// <summary>
/// 截取选中屏幕
/// </summary>
/// <remarks>
/// 实现流程:
/// 1、显示截取屏幕界面
/// 2、返回确认截屏后所得位图句柄
/// </remarks>
/// <returns>返回:位图句柄
/// </returns>
HBITMAP CSnapScreenWnd::SnapScreen()
{
m_hResult = NULL;
// 显示截取屏幕界面
DoModal(WS_EX_TOPMOST, NULL, NULL, WS_VISIBLE | WS_POPUP & ~WS_BORDER,
0, 0, m_nScreenX, m_nScreenY, m_pParentWnd->GetSafeHwnd(), NULL);
// 返回确认截屏后所得位图句柄
return m_hResult;
}