c++ 屏幕截图指定窗口句柄后台截图返回位图句柄
/根据窗口句柄后台截图保存成BMP位图文件并且显示到picture 控件上 void GetScreenBmp(HWND hwnd, int left, int top, int width, int height, CHAR* path) { HDC pDC;// 源DC //判断是不是窗口句柄如果是的话不能使用GetDC来获取DC 不然截图会是黑屏 if (hwnd==::GetDesktopWindow()) { pDC = CreateDCA("DISPLAY", NULL, NULL, NULL); } else { pDC = ::GetDC(hwnd);//获取屏幕DC(0为全屏,句柄则为窗口) } int BitPerPixel = ::GetDeviceCaps(pDC, BITSPIXEL);//获得颜色模式 if (width == 0 && height == 0)//默认宽度和高度为全屏 { width = ::GetDeviceCaps(pDC, HORZRES); //设置图像宽度全屏 height = ::GetDeviceCaps(pDC, VERTRES); //设置图像高度全屏 } HDC memDC;//内存DC memDC = ::CreateCompatibleDC(pDC); HBITMAP memBitmap, oldmemBitmap;//建立和屏幕兼容的bitmap memBitmap = ::CreateCompatibleBitmap(pDC, width, height); oldmemBitmap = (HBITMAP)::SelectObject(memDC, memBitmap);//将memBitmap选入内存DC if (hwnd==::GetDesktopWindow()) { BitBlt(memDC,0, 0, width, height, pDC, left, top, SRCCOPY);//图像宽度高度和截取位置 } else { bool bret = ::PrintWindow(hwnd, memDC, PW_CLIENTONLY); if (!bret) { BitBlt(memDC, 0, 0, width, height, pDC, left, top, SRCCOPY);//图像宽度高度和截取位置 } } //以下代码保存memDC中的位图到文件 BITMAP bmp; ::GetObject(memBitmap, sizeof(BITMAP), &bmp);;//获得位图信息 FILE *fp; fopen_s(&fp, path, "w+b");//图片保存路径和方式 BITMAPINFOHEADER bih = { 0 };//位图信息头 bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小 bih.biCompression = BI_RGB; bih.biHeight = bmp.bmHeight;//高度 bih.biPlanes = 1; bih.biSize = sizeof(BITMAPINFOHEADER); bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小 bih.biWidth = bmp.bmWidth;//宽度 BITMAPFILEHEADER bfh = { 0 };//位图文件头 bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量 bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;//文件总的大小 bfh.bfType = (WORD)0x4d42; fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头 fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头 byte * p = new byte[bmp.bmWidthBytes * bmp.bmHeight];//申请内存保存位图数据 GetDIBits(memDC, (HBITMAP)memBitmap, 0, height, p, (LPBITMAPINFO)&bih, DIB_RGB_COLORS);//获取位图数据 fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);//写入位图数据 delete[] p; fclose(fp); HWND sBitHwnd = GetDlgItem(g_Hwnd, IDC_STATIC_IMG); /*返回内存中的位图句柄 还原原来的内存DC位图句柄 不能直接用 memBitmap我测试好像是不行不知道为什么*/ HBITMAP oleImage = (HBITMAP)::SelectObject(memDC, oldmemBitmap); oleImage = (HBITMAP)SendMessage(sBitHwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)oleImage); #if 0 /*这种方法也能把位图显示到picture 控件上*/ HDC bitDc = NULL; bitDc = ::GetDC(sBitHwnd); BitBlt(bitDc, 0, 0, bmp.bmWidth, bmp.bmHeight, memDC, 0, 0, SRCCOPY); //内存DC映射到屏幕DC ReleaseDC(sBitHwnd, bitDc); /*如果需要把位图转换*/ /* CImage image; image.Create(nWidth, nHeight, nBitPerPixel); BitBlt(image.GetDC(), 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY); ::ReleaseDC(NULL, hdcSrc); image.ReleaseDC(); image.Save(path, Gdiplus::ImageFormatPNG);//ImageFormatJPEG */ #endif DeleteObject(memBitmap); DeleteObject(oleImage); DeleteDC(memDC); ReleaseDC(hwnd,pDC); }