如何快速截屏?(目前的耗时大约为15ms,希望能控制在5ms以内)
以下是我写的一段截屏代码,截取的图片要求是位图的格式,现在截图时间大约要15ms,希望能进一步提高执行效率,最好能把耗时控制在5ms以内,不知道可不可以,谢谢。
CDC dc; CDC *pDC = &dc;//屏幕DC HWND hwnd = ::GetForegroundWindow(); HDC activeDC = ::GetWindowDC(hwnd); //获得当前活动窗口的hDC pDC->Attach(activeDC);//获取当前活动窗口的DC RECT rect; ::GetWindowRect(hwnd,&rect);//得到活动窗口的大小 UINT Width = rect.right - rect.left; UINT Height = rect.bottom - rect.top; CDC memDC;//内存DC memDC.CreateCompatibleDC(pDC); CBitmap memBitmap, *oldmemBitmap;//建立和屏幕兼容的bitmap memBitmap.CreateCompatibleBitmap(pDC, Width, Height); oldmemBitmap = memDC.SelectObject(&memBitmap);//将memBitmap选入内存DC memDC.BitBlt(0, 0, Width, Height, pDC, 0, 0, SRCCOPY);//复制屏幕图像到内存DC BITMAP bmp; memBitmap.GetBitmap(&bmp);//获得位图信息 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; BYTE * up = new BYTE[bmp.bmWidthBytes * bmp.bmHeight];//申请内存保存位图数据 GetDIBits(memDC.m_hDC, (HBITMAP) memBitmap.m_hObject, 0, Height, up, (LPBITMAPINFO) &bih, DIB_RGB_COLORS);//获取位图数据 //以下是保存图片的代码,略BOOL SaveHwndToBmpFile(HWND hWnd, LPCTSTR lpszPath){ HWND hDesktop = ::GetDesktopWindow(); ASSERT(hDesktop); if(NULL == hWnd) { hWnd = hDesktop; } RECT rect; ::GetWindowRect(hWnd, &rect); int nWidht = rect.right - rect.left; int nHeight = rect.bottom - rect.top; HDC hSrcDC = ::GetWindowDC(hWnd); ASSERT(hSrcDC); HDC hMemDC = ::CreateCompatibleDC(hSrcDC); ASSERT(hMemDC); HBITMAP hBitmap = ::CreateCompatibleBitmap(hSrcDC, nWidht, nHeight); ASSERT(hBitmap); HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap); ::BitBlt(hMemDC, 0, 0, nWidht, nHeight, hSrcDC, 0, 0, SRCCOPY); BITMAP bitmap = {0}; ::GetObject(hBitmap, sizeof(BITMAP), &bitmap); BITMAPINFOHEADER bi = {0}; BITMAPFILEHEADER bf = {0}; CONST int nBitCount = 24; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bitmap.bmWidth; bi.biHeight = bitmap.bmHeight; bi.biPlanes = 1; bi.biBitCount = nBitCount; bi.biCompression = BI_RGB; DWORD dwSize = ((bitmap.bmWidth * nBitCount + 31) / 32) * 4 * bitmap.bmHeight; HANDLE hDib = GlobalAlloc(GHND, dwSize + sizeof(BITMAPINFOHEADER)); LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); *lpbi = bi; ::GetDIBits(hMemDC, hBitmap, 0, bitmap.bmHeight, (BYTE*)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO*)lpbi, DIB_RGB_COLORS); try { CFile file; file.Open(lpszPath, CFile::modeCreate | CFile::modeWrite); bf.bfType = 0x4d42; dwSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); bf.bfSize = dwSize; bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); file.Write((BYTE*)&bf, sizeof(BITMAPFILEHEADER)); file.Write((BYTE*)lpbi, dwSize); file.Close(); } catch(CFileException* e) { e->ReportError(); e->Delete(); } GlobalUnlock(hDib); GlobalFree(hDib); ::SelectObject(hMemDC, hOldBitmap); ::DeleteObject(hBitmap); ::DeleteDC(hMemDC); ::ReleaseDC(hWnd, hSrcDC); return TRUE;}// 调用方法 HWND hWnd = GetSafeHwnd(); if(hWnd) { DWORD dwStart = GetTickCount(); SaveHwndToBmpFile(hWnd, _T("E://12.bmp")); DWORD dwValue = GetTickCount() - dwStart; CString strText(_T("")); strText.Format(_T("%d ms"), dwValue); AfxMessageBox(strText); }
[解决办法]
我来说点实质的修改点
1.
CDC memDC;//内存DC 放全局变量里
memDC.CreateCompatibleDC(pDC); // 这个页面初始化的时候就创建,不必每次都创建。
2. BITMAPINFOHEADER bih = {0};//大部分信息都是固定的,固定的就放全局,不变的放在函数里面
[解决办法]
3.memBitmap.CreateCompatibleBitmap(pDC, Width, Height);
oldmemBitmap = memDC.SelectObject(&memBitmap);//将memBitmap选入内存DC
这里也可以放到全局,反正都不变的,开局的时候初始化一次就可以了,因为你每次图片大小都一样的,而且MEM每次都选中这个的
[解决办法]
好久不来 发现CSDN的水平下滑严重啊
最快速的截屏方式应该是 镜像驱动, 很多远程桌面共享 软件都采用这种方式
就用VNC里面的吧,很好很方便
http://www.uvnc.com/features/driver.html