很多时候登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 这个函数 获取整个屏幕//截取屏幕到位图中
然后处理 WM_ERASEBKGND 消息 将获取到的屏幕设置为背景。所以看上去似乎是在桌面绘图。
m_pBitmap=CBitmap::FromHandle(CopyScreenToBitmap(&rect)); 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; }
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2302
- 用户1336
- 访客10968998
每日一句
Qingming Festival invites us to honor ancestors with quiet reflection and respect.
清明节邀请我们以静思与敬意祭奠祖先。
清明节邀请我们以静思与敬意祭奠祖先。
新会员