全屏背景实现 截图功能实现(一)

时间:2022-08-05 10:06:46
最近的一个项目需要实现一个类似QQ截图一样的功能,以前一直没有研究过 全屏背景实现 截图功能实现(一)表示鸭梨很大,没办法只能硬着头皮上了。
  经过一天的时间,网上翻阅了一些资料,其实截图功能的原理相当简单 全屏背景实现 截图功能实现(一)一下子信心,就是创建一个全屏的对话框置顶显示(注意是当前窗口最顶)并且把当前桌面上的所有可见当作该对话框的背景,如果实现了以上的功能表示截图的最初功能基本实现,但是观察QQ截图发下功能没那么简单,人家有把背景变暗,鼠标拖动框选区域,工具条,涂鸦,自动框选,保存各种格式的图片等等功能。 全屏背景实现 截图功能实现(一)我们的路还很漫长,所以要一步一步走,不能一口吃下一个胖子。
   回到刚才话题,看似简单,在实际操作的时候,发现一些问题,首先遇到的问题是如何创建一个全屏的对话框注意这里的全屏对话框就是在有多显示器的时候也需要适应,翻阅了百度,goolge终于发现GetSystemMetrics这个函数是我需要的
    m_cxScreen=::GetSystemMetrics(SM_CXVIRTUALSCREEN);//获取设备宽度
    m_cyScreen=::GetSystemMetrics(SM_CYVIRTUALSCREEN);//获取设备高度
    m_xScreen =::GetSystemMetrics( SM_XVIRTUALSCREEN );//对话框左上角的点相当屏幕的X坐标
    m_yScreen =::GetSystemMetrics( SM_YVIRTUALSCREEN );//对话框左上角的点相当屏幕的Y坐标
这里要说明下屏幕坐标 全屏背景实现 截图功能实现(一)箭头处为左上角也就是对话框的起点,x为要显示对话框宽度,y对话框的高度,如图所示,这个时候对话框起点不在是(0,0)了而且可能出现负数,因此在后面的操作中如果获取来的屏幕坐标一定先转为对话框的相当坐标,这个很关键,这个后面还会遇到,到时再说

    OK 全屏背景实现 截图功能实现(一)取到了对话的高度和宽度,以及在屏幕上要显示的点的位置就可以创建对话框了,创建对话框应该都会在这里我采用MFC来做,当然也可以用win32API 创建,由于项目已经用MFC 而且对MFC也比较熟悉,所以我就采用MFC来了。在对话框的OnInitDialog函数里添加SetWindowPos(&wndTopMost,m_xScreen,m_yScreen,m_cxScreen,m_cyScreen,SWP_SHOWWINDOW);创建一个全屏置顶的对话框(需要把对话设置为无标题栏(TitleBar FALSE),样式弹出式(style Popup))。
  这样对话框创建完成了,那么还有一个就是吧当前桌面作为对话框的背景 既然要获取桌面上画的是什么那么久要获取桌面的DC了获取桌面DC有几种
::GetDC(NULL),::GetDC(::GetDesktopWindow()),::GetWindowDC(::GetDesktopWindow());
随便选一个
在OnInitDialog添加如下代码
HDC hDeskDC = ::GetWindowDC(::GetDesktopWindow());    CDCdeskDc;
deskDc.Attach(hDeskDC);
m_pBitmap =new CBitmap;//存放背景图片的CBitmap对象为后面其他功能实现需要
m_pBitmap->CreateCompatibleBitmap(&deskDc,m_cxScreen, m_cyScreen);//创建兼容位图
m_pbmpdesktop = new CBitmap;
m_pbmpdesktop->CreateCompatibleBitmap(&deskDc,m_cxScreen, m_cyScreen);
CDCdcTemp;
dcTemp.CreateCompatibleDC(&deskDc);
dcTemp.SelectObject(m_pBitmap);
dcTemp.BitBlt(0,0,m_cxScreen, m_cyScreen, &deskDc,m_xScreen,m_yScreen,SRCCOPY);
::ReleaseDC(NULL, hDeskDC);


之后还需在OnPaint添加一个画背景的函数DrawBackground( CDC * pMemDC )参数为内存用于双缓冲防止出现闪烁具体如何请查看相关的双缓冲知识这里就不再陈述了
这个函数的实现如下
void CScreenShotDlg::DrawBackground( CDC * pMemDC ){
CDCdcTemp;
dcTemp.CreateCompatibleDC(pMemDC);
dcTemp.SelectObject(m_pBitmap);
pMemDC->BitBlt(0,0, m_cxScreen, m_cyScreen,&dcTemp, 0,0, SRCCOPY);
if(!m_pMaskBmp)
{
m_pMaskBmp =new CBitmap;
m_pMaskBmp->CreateCompatibleBitmap(pMemDC,m_cxScreen, m_cyScreen);
dcTemp.SelectObject(m_pMaskBmp);
dcTemp.FillSolidRect(0,0, m_cxScreen, m_cyScreen,BKCOLOR);//BKCOLOR混合要达到的颜色RGB(?,?,?)
}
else
{
dcTemp.SelectObject(m_pMaskBmp);
}
BLENDFUNCTION bf;
bf.BlendOp =AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 128; //透明度
bf.AlphaFormat = 0;
AlphaBlend(pMemDC->GetSafeHdc(),0,0,m_cxScreen,m_cyScreen,dcTemp.GetSafeHdc(),0,0,m_cxScreen,m_cyScreen,bf);
dcTemp.DeleteDC();
}


这里用到一个AlphaBlend 这个API 主要是把源DC于目标DC混合达到透明的效果这里的源DC是dcTemp,目标DCpMemDC,主要在混合前一定要保证目标和源都是新的(防止出现颜色越来越深最后完全变成BKCOLOR颜色),这个时候前面保存的m_pBitmap,以及 m_pMaskBmp就派上用处了,在每次混合前重新选择m_pBitmap到源DC。
  这样就完成了基本对话框创建,背景绘制以及背景变暗等功能。可以看看效果图 全屏背景实现 截图功能实现(一)

哈哈这个是在我的截图上再用QQ截图又保存为jpg 难免会有点失真的样子,不过具体效果就好QQ截图差不多。
下面的一些功能实现下次再说,第一次写东西有什么地方错的请指教。 全屏背景实现 截图功能实现(一)谢谢