⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 screensnapdlg.cpp

📁 截取屏幕部分
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	}
	
	CDialog::OnTimer(nIDEvent);
}

//********************************************************************************
//* 名称:OnHideWindow
//* 功能:隐藏窗体
//********************************************************************************
void CScreenSnapDlg::OnHideWindow() 
{
	OnShowhide();
}

//********************************************************************************
//* 名称:OnSnapWindow
//* 功能:系统区菜单抓图操作
//********************************************************************************
void CScreenSnapDlg::OnSnapWindow() 
{
	OnScreensnap();	
}

//********************************************************************************
//* 名称:DDBToDIB
//* 功能:设备相关转换为设备无关位图
//********************************************************************************
HANDLE CScreenSnapDlg::DDBToDIB( CBitmap& bitmap, DWORD dwCompression /* = BI_RGB */) 
{
    BITMAP				bm;
    BITMAPINFOHEADER    bi;
    LPBITMAPINFOHEADER  lpbi;
    DWORD				dwLen;
    HANDLE				hDIB;
    HANDLE				handle;
    HDC					hDC;
    HPALETTE			hPal;

    CWindowDC			dc( this );
    CPalette			pal;
    //如果支持调色板的话,则建立它
    if( dc.GetDeviceCaps( RASTERCAPS ) & RC_PALETTE )
    {
        UINT        nSize   = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
        LOGPALETTE* pLP     = (LOGPALETTE*)new BYTE[nSize];
        pLP->palVersion     = 0x300;
        pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( dc, 0, 255, 
        pLP->palPalEntry );

        pal.CreatePalette( pLP );

        //释放
        delete[] pLP;
    }

    ASSERT( bitmap.GetSafeHandle() );

    //不支持BI_BITFIELDS类型
    if( dwCompression == BI_BITFIELDS )
        return NULL;

    //如果调色板为空,则用默认调色板
    hPal = (HPALETTE) pal.GetSafeHandle();
    if (hPal==NULL)
        hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

    //获取位图信息
    bitmap.GetObject(sizeof(bm),(LPSTR)&bm);

    //初始化位图信息头
    bi.biSize        = sizeof(BITMAPINFOHEADER);
    bi.biWidth        = bm.bmWidth;
    bi.biHeight         = bm.bmHeight;
    bi.biPlanes         = 1;
    bi.biBitCount        = (unsigned short)(bm.bmPlanes * bm.bmBitsPixel) ;
    bi.biCompression    = dwCompression;
    bi.biSizeImage        = 0;
    bi.biXPelsPerMeter    = 0;
    bi.biYPelsPerMeter    = 0;
    bi.biClrUsed        = 0;
    bi.biClrImportant    = 0;

    //计算信息头及颜色表大小
    int nColors = 0;
    if(bi.biBitCount <= 8)
        {
        nColors = (1 << bi.biBitCount);
        }
    dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);

    hDC = ::GetDC(NULL);
    hPal = SelectPalette(hDC,hPal,FALSE);
    RealizePalette(hDC);

    //为信息头及颜色表分配内存
    hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

    if (!hDIB){
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
    }

    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);

    *lpbi = bi;

    //调用 GetDIBits 计算图像大小
    GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
            (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);

    bi = *lpbi;

    //图像的每一行都对齐(32bit)边界
    if (bi.biSizeImage == 0){
        bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) 
                        * bi.biHeight;

        if (dwCompression != BI_RGB)
            bi.biSizeImage = (bi.biSizeImage * 3) / 2;
    }

    //重新分配内存大小,以便放下所有数据
    dwLen += bi.biSizeImage;
    handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE) ;
    if (handle != NULL)
        hDIB = handle;
    else
        {
        GlobalFree(hDIB);

        //重选原始调色板
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
        }

    //获取位图数据
    lpbi = (LPBITMAPINFOHEADER)hDIB;

    //最终获得的DIB
    BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
                0L,                      //扫描行起始处
                (DWORD)bi.biHeight,      //扫描行数
                (LPBYTE)lpbi             //位图数据地址
                + (bi.biSize + nColors * sizeof(RGBQUAD)),
                (LPBITMAPINFO)lpbi,      //位图信息地址
                (DWORD)DIB_RGB_COLORS);  //颜色板使用RGB

    if( !bGotBits )
    {
        GlobalFree(hDIB);
        
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
    }

    SelectPalette(hDC,hPal,FALSE);
    ::ReleaseDC(NULL,hDC);
    return hDIB;
}

//********************************************************************************
//* 名称:SaveBitmapToFile
//* 功能:保存为位图文件
//********************************************************************************
BOOL CScreenSnapDlg::SaveBitmapToFile(HBITMAP hBitmap , CString lpFileName) 
{    	 
	HDC				hDC;							//设备描述表  
    int				iBits;							//当前显示分辨率下每个像素所占字节数
	WORD            wBitCount;						//位图中每个像素所占字节数
	DWORD           dwPaletteSize=0,				//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
					dwBmBitsSize,
					dwDIBSize, dwWritten;
	BITMAP          Bitmap;        
	BITMAPFILEHEADER   bmfHdr;						//位图属性结构    
    BITMAPINFOHEADER   bi;							//位图文件头结构       
	LPBITMAPINFOHEADER lpbi;						//位图信息头结构     
    HANDLE          fh, hDib, hPal,hOldPal=NULL;	//指向位图信息头结构,定义文件,分配内存句柄,调色板句柄
  
   //计算位图文件每个像素所占字节数
   hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
   iBits = GetDeviceCaps(hDC, BITSPIXEL) * 
   GetDeviceCaps(hDC, PLANES);
   DeleteDC(hDC);
   if (iBits <= 1)
      wBitCount = 1;
   else if (iBits <= 4)
      wBitCount = 4;
   else if (iBits <= 8)
      wBitCount = 8;
   else if (iBits <= 24)
      wBitCount = 24;
   //计算调色板大小
   if (wBitCount <= 8)
      dwPaletteSize = (1 << wBitCount) *sizeof(RGBQUAD);
   
   //设置位图信息头结构
   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
   bi.biSize            = sizeof(BITMAPINFOHEADER);
   bi.biWidth           = Bitmap.bmWidth;
   bi.biHeight          = Bitmap.bmHeight;
   bi.biPlanes          = 1;
   bi.biBitCount         = wBitCount;
   bi.biCompression      = BI_RGB;
   bi.biSizeImage        = 0;
   bi.biXPelsPerMeter     = 0;
   bi.biYPelsPerMeter     = 0;
   bi.biClrUsed         = 0;
   bi.biClrImportant      = 0;

   dwBmBitsSize = ((Bitmap.bmWidth *
    wBitCount+31)/32)* 4
	 *Bitmap.bmHeight ;

   //为位图内容分配内存
   hDib  = GlobalAlloc(GHND,dwBmBitsSize+
	dwPaletteSize+sizeof(BITMAPINFOHEADER));
   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
   *lpbi = bi;

   // 处理调色板   
   hPal = GetStockObject(DEFAULT_PALETTE);
   if (hPal)
   {
	   hDC  = ::GetDC(NULL);
	   hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
       RealizePalette(hDC);
   }

   // 获取该调色板下新的像素值
   GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
	 (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
	 (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);

   //恢复调色板   
   if (hOldPal)
   {
      SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
      RealizePalette(hDC);
      ::ReleaseDC(NULL, hDC);
   }

   //创建位图文件    
	fh = CreateFile(lpFileName, GENERIC_WRITE, 
		 0, NULL, CREATE_ALWAYS,
         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);

   if (fh == INVALID_HANDLE_VALUE)
      return FALSE;

   // 设置位图文件头
   bmfHdr.bfType = 0x4D42;  // "BM"
   dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;  
   bmfHdr.bfSize = dwDIBSize;
   bmfHdr.bfReserved1 = 0;
   bmfHdr.bfReserved2 = 0;
   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) 
      + (DWORD)sizeof(BITMAPINFOHEADER)
     + dwPaletteSize;

   // 写入位图文件头
   WriteFile(fh, (LPSTR)&bmfHdr, sizeof
	(BITMAPFILEHEADER), &dwWritten, NULL);
   // 写入位图文件其余内容
   WriteFile(fh, (LPSTR)lpbi, dwDIBSize, 
   &dwWritten, NULL);

   //消除内存分配  
   GlobalUnlock(hDib);
   GlobalFree(hDib);
   CloseHandle(fh);

   return TRUE;
}

//********************************************************************************
//* 名称:OnSavebmp
//* 功能:保存为位图
//********************************************************************************
void CScreenSnapDlg::OnSavebmp() 
{
	if (m_hwndFoundWindow)								//如果已有选中窗口的话,则刷新它
	{
		//打开保存对话框,获取保存文件名
		CString	strFileName;	
		CFileDialog dlg( FALSE,"bmp", "*.bmp", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "*.bmp||" );
		dlg.m_ofn.Flags|=OFN_FILEMUSTEXIST;
		dlg.m_ofn.lpstrTitle="保存为位图";
		if( dlg.DoModal() == IDCANCEL )
			return ;
		strFileName = dlg.GetPathName();

		//先隐藏窗体
		if(IsWindowVisible())				 //窗体是否已隐藏
		{
			ShowWindow(SW_HIDE);             //先隐藏窗体
			WinAnimation(true);			     //窗体动画滑入到系统区中 
		}

		//获取选中图像窗口的位图句柄
		CDC dc;
        HDC hdc = ::GetWindowDC(m_hwndFoundWindow);
        dc.Attach(hdc);

		CDC memDC;
		memDC.CreateCompatibleDC(&dc);
		
		CBitmap bm;
		CRect r;
		
		((CWnd *)CWnd::FromHandle(m_hwndFoundWindow))->GetWindowRect(&r);
	
		CSize sz(r.Width(), r.Height());
		bm.CreateCompatibleBitmap(&dc, sz.cx, sz.cy);
		CBitmap * oldbm = memDC.SelectObject(&bm);
		memDC.BitBlt(0, 0, sz.cx, sz.cy, &dc, 0, 0, SRCCOPY);
		
		//保存为指定位图文件
		if(SaveBitmapToFile((HBITMAP)bm.m_hObject,strFileName))
			m_Description.SetWindowText("位图保存成功!");
		else
			m_Description.SetWindowText("位图保存失败!");
		
		//恢复原始环境
		memDC.SelectObject(oldbm);
		bm.Detach();  

		//恢复窗体正常显示
		if(!IsWindowVisible())				 //窗体是否已隐藏
		{
			ShowWindow(SW_SHOW);             
			WinAnimation(false);			 //窗体动画从系统区中滑出 
		}

	}
	else
	{
		MessageBox("没有找到选中图像,请在抓图后,按F3键完成抓图!");
		m_Description.SetWindowText("没有找到选中图像,请在抓图后,按F3键完成抓图!");
	}
}

//********************************************************************************
//* 名称:OnSaveBmp
//* 功能:系统区菜单中保存位图操作
//********************************************************************************
void CScreenSnapDlg::OnSaveBmp() 
{
	OnSavebmp();	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -