很多时候登QQ只是为了截图..虽然系统有截屏键,浏览器什么的都有截屏插件,但总觉得QQ是做的做好的。只此一家别无分号。但有时候断网就悲催了。
于是周六周末摸索着自己实现了一下它的两个基本功能,截屏到剪切板和保存到文件。参考了两个版本的代码 。一个是VC 驿站上的QQ2008版本的截屏。它采用了橡皮筋类。一种是之前CSDN上一个牛人放出的模拟ipad效果的源代码里面的截屏功能。 1 先说QQ2008版本的 在程序启动后,鼠标会变成一个彩色的箭头。拖动后就会显示一个虚线框。这是通过 CRectTracker 派生的一个橡皮筋类 。之所以不直接使用基类,源代码的注释中说是 更新窗口,消除TRACK时的虚线框 接下来就是在程序中对橡皮筋类的初始化
//初始化像皮筋类
m_RectTracker.m_nStyle=CRectTracker::resizeInside|CRectTracker::dottedLine;
m_RectTracker.m_rect.SetRect(-1,-1,-1,-1);
获取屏幕分辨率 截取屏幕到位图中 获取要更新的区域 和设置鼠标为彩色等一系列活动。具体看源代码。
最核心的一个函数就是拷贝屏幕 源代码如下
HBITMAP CScreenSpyDlg::CopyScreenToBitmap(LPRECT lpRect,BOOL bSave)
//lpRect 代表选定区域
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
//确保选定区域是可见的
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > m_xScreen)
nX2 = m_xScreen;
if (nY2 > m_yScreen)
nY2 = m_yScreen;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap
(hScrDC, nWidth, nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
if(bSave)
{
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(CDC::FromHandle(hMemDC));
dcCompatible.SelectObject(m_pBitmap);
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
dcCompatible, nX, nY, SRCCOPY);
}
else
{
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
hScrDC, nX, nY, SRCCOPY);
}
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
//得到屏幕位图的句柄
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 返回位图句柄
if(bSave)
{
if (OpenClipboard())
{
//清空剪贴板
EmptyClipboard();
//把屏幕内容粘贴到剪贴板上,
//hBitmap 为刚才的屏幕位图句柄
SetClipboardData(CF_BITMAP, hBitmap);
//关闭剪贴板
CloseClipboard();
}
}
return hBitmap;
}
这里就完成了截取屏幕到剪切板的操作。
还有一点可能是我们这种菜鸟犯晕的地方,就是它如何做到在屏幕上画出一个虚线框的。这一点,实际上它是通过设置透明窗体实现的。所以看上去像是直接在桌面上画图。这个方法是一开始初始化就调用
CopyScreenToBitmap 这个函数 获取整个屏幕//截取屏幕到位图中
m_pBitmap=CBitmap::FromHandle(CopyScreenToBitmap(&rect));
然后处理 WM_ERASEBKGND 消息 将获取到的屏幕设置为背景。所以看上去似乎是在桌面绘图。
BOOL CScreenSpyDlg::OnEraseBkgnd(CDC* pDC)
{
BITMAP bmp;
m_pBitmap->GetBitmap(&bmp);
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC);
dcCompatible.SelectObject(m_pBitmap);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);
return TRUE;
}
源代码已经上传 有需要的同学可以看一下。高手请无视^_^
接下来是QQ2012这种方式
QQ2012摒弃了08版的虚线框形式。而是采用了更炫的效果,首先在启动的时候讲这个屏幕弄的灰不溜秋的。然后将截取出来的区域正常显示,就造成了一种高亮效果。
之前一直没弄明白它是怎么做的这个效果(郁闷的菜鸟ing..)后来参考了一下别人的源代码。它的实现方式是贴图。大量的贴图。不禁肃然起敬。这样都可以!.#$$%
它的源代码和08的并没有多少本质的区别,所以就不多赘述了。主要就是那个灰色背景效果。还有就是多了一个加载工具栏的功能。工具栏提供了设置截屏为桌面壁纸的功能,保存为磁盘文件的功能。(设置为壁纸的功能存在BUG,暂时没时间去Review。深表惭愧。)因为有源码。就不多贴代码片段了,需要指出的是,这个版本的源代码我写的比较乱(可能程序员看别人的代码都是一团乱糟糟吧^_^),有些没有用到的类,函数都放在里面,只是简单的注销了。有的甚至没有屏蔽。希望不会给看代码的人带来困惑。
^_^ witch_2012_06
QQ2008版截屏工具源代码地址 :
http://download.csdn.net/detail/witch_soya/4370139
QQ2012版截屏工具源代码地址 :
http://download.csdn.net/detail/witch_soya/4370199
/*
最后衷心感谢提供 08 源代码的VC BASE
以及Deskpad源代码的网友。
╰Witchつ
2012_06_13
*/

于是周六周末摸索着自己实现了一下它的两个基本功能,截屏到剪切板和保存到文件。参考了两个版本的代码 。一个是VC 驿站上的QQ2008版本的截屏。它采用了橡皮筋类。一种是之前CSDN上一个牛人放出的模拟ipad效果的源代码里面的截屏功能。 1 先说QQ2008版本的 在程序启动后,鼠标会变成一个彩色的箭头。拖动后就会显示一个虚线框。这是通过 CRectTracker 派生的一个橡皮筋类 。之所以不直接使用基类,源代码的注释中说是 更新窗口,消除TRACK时的虚线框 接下来就是在程序中对橡皮筋类的初始化
//初始化像皮筋类
m_RectTracker.m_nStyle=CRectTracker::resizeInside|CRectTracker::dottedLine;
m_RectTracker.m_rect.SetRect(-1,-1,-1,-1);
获取屏幕分辨率 截取屏幕到位图中 获取要更新的区域 和设置鼠标为彩色等一系列活动。具体看源代码。
最核心的一个函数就是拷贝屏幕 源代码如下
HBITMAP CScreenSpyDlg::CopyScreenToBitmap(LPRECT lpRect,BOOL bSave)
//lpRect 代表选定区域
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
//确保选定区域是可见的
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > m_xScreen)
nX2 = m_xScreen;
if (nY2 > m_yScreen)
nY2 = m_yScreen;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap
(hScrDC, nWidth, nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
if(bSave)
{
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(CDC::FromHandle(hMemDC));
dcCompatible.SelectObject(m_pBitmap);
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
dcCompatible, nX, nY, SRCCOPY);
}
else
{
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
hScrDC, nX, nY, SRCCOPY);
}
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
//得到屏幕位图的句柄
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 返回位图句柄
if(bSave)
{
if (OpenClipboard())
{
//清空剪贴板
EmptyClipboard();
//把屏幕内容粘贴到剪贴板上,
//hBitmap 为刚才的屏幕位图句柄
SetClipboardData(CF_BITMAP, hBitmap);
//关闭剪贴板
CloseClipboard();
}
}
return hBitmap;
}
这里就完成了截取屏幕到剪切板的操作。
还有一点可能是我们这种菜鸟犯晕的地方,就是它如何做到在屏幕上画出一个虚线框的。这一点,实际上它是通过设置透明窗体实现的。所以看上去像是直接在桌面上画图。这个方法是一开始初始化就调用
CopyScreenToBitmap 这个函数 获取整个屏幕//截取屏幕到位图中
m_pBitmap=CBitmap::FromHandle(CopyScreenToBitmap(&rect));
然后处理 WM_ERASEBKGND 消息 将获取到的屏幕设置为背景。所以看上去似乎是在桌面绘图。
BOOL CScreenSpyDlg::OnEraseBkgnd(CDC* pDC)
{
BITMAP bmp;
m_pBitmap->GetBitmap(&bmp);
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC);
dcCompatible.SelectObject(m_pBitmap);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);
return TRUE;
}
源代码已经上传 有需要的同学可以看一下。高手请无视^_^
接下来是QQ2012这种方式
QQ2012摒弃了08版的虚线框形式。而是采用了更炫的效果,首先在启动的时候讲这个屏幕弄的灰不溜秋的。然后将截取出来的区域正常显示,就造成了一种高亮效果。
之前一直没弄明白它是怎么做的这个效果(郁闷的菜鸟ing..)后来参考了一下别人的源代码。它的实现方式是贴图。大量的贴图。不禁肃然起敬。这样都可以!.#$$%
它的源代码和08的并没有多少本质的区别,所以就不多赘述了。主要就是那个灰色背景效果。还有就是多了一个加载工具栏的功能。工具栏提供了设置截屏为桌面壁纸的功能,保存为磁盘文件的功能。(设置为壁纸的功能存在BUG,暂时没时间去Review。深表惭愧。)因为有源码。就不多贴代码片段了,需要指出的是,这个版本的源代码我写的比较乱(可能程序员看别人的代码都是一团乱糟糟吧^_^),有些没有用到的类,函数都放在里面,只是简单的注销了。有的甚至没有屏蔽。希望不会给看代码的人带来困惑。
^_^ witch_2012_06
QQ2008版截屏工具源代码地址 :
http://download.csdn.net/detail/witch_soya/4370139
QQ2012版截屏工具源代码地址 :
http://download.csdn.net/detail/witch_soya/4370199
/*
最后衷心感谢提供 08 源代码的VC BASE
以及Deskpad源代码的网友。
╰Witchつ
2012_06_13
*/