我试图找到一个(有点)简单的方法来在窗口上截图,并将得到的HBITMAP保存为JPEG.这里的棘手部分是,由于代码是C,我不能使用GDI,因为代码是一个更大的程序的模块,我不能使用外部lib(如libjpeg).
此代码需要截图并返回HBITMAP.将该位图保存到文件中很容易.问题是位图是2或3mb.
HDC hDCMem = CreateCompatibleDC(NULL); HBITMAP hBmp; RECT rect; HDC hDC; HGdioBJ hOld; GetWindowRect(hWnd,& rect); hBmp = NULL; { hDC = GetDC(hWnd); hBmp = CreateCompatibleBitmap(hDC,rect.right - rect.left,rect.bottom - rect.top); ReleaseDC(hWnd,hDC); } hOld = SelectObject(hDCMem,hBmp); SendMessage(hWnd,WM_PRINT,(WPARAM) hDCMem,PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED); SelectObject(hDCMem,hOld); DeleteObject(hDCMem); return hBmp;
任何想法如何做到这一点?
非常感谢,任何帮助都不胜感激
编辑:
由于我们进入GDI的方向,我以为我会发布代码iv C,可以使用截图,并将其转换为使用GDI的JPEG.如果有人知道如何使用FLAT GDI来实现这一点,我将不胜感激.
码:
#include <windows.h> #include <stdio.h> #include <gdiplus.h> using namespace Gdiplus; int GetEncoderClsid(WCHAR *format,CLSID *pClsid) { unsigned int num = 0,size = 0; GetImageEncodeRSSize(&num,&size); if(size == 0) return -1; ImageCodecInfo *pImageCodecInfo = (ImageCodecInfo *)(malloc(size)); if(pImageCodecInfo == NULL) return -1; GetImageEncoders(num,size,pImageCodecInfo); for(unsigned int j = 0; j < num; ++j) { if(wcscmp(pImageCodecInfo[j].MimeType,format) == 0){ *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; } } free(pImageCodecInfo); return -1; } int GetScreeny(LPWSTR lpszFilename,ULONG uQuality) // by Napalm { ULONG_PTR gdiplusToken; GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL); HWND hMyWnd = GetForegroundWindow(); // get my own window RECT r; // the area we are going to capture int w,h; // the width and height of the area HDC dc; // the container for the area int nBPP; HDC hdcCapture; LPBYTE lpCapture; int nCapture; int iRes; CLSID imageCLSID; Bitmap *pScreenShot; HGLOBAL hMem; int result; // get the area of my application's window //GetClientRect(hMyWnd,&r); GetWindowRect(hMyWnd,&r); dc = GetWindowDC(hMyWnd);// GetDC(hMyWnd) ; w = r.right - r.left; h = r.bottom - r.top; nBPP = GetDeviceCaps(dc,BITSPIXEL); hdcCapture = CreateCompatibleDC(dc); // create the buffer for the screenshot BITMAPINFO bmiCapture = { sizeof(BITMAPINFOHEADER),w,-h,1,nBPP,BI_RGB,}; // create a container and take the screenshot HBITMAP hbmCapture = CreateDIBSection(dc,&bmiCapture,DIB_PAL_COLORS,(LPVOID *)&lpCapture,NULL,0); // Failed to take it if(!hbmCapture) { DeleteDC(hdcCapture); DeleteDC(dc); GdiplusShutdown(gdiplusToken); printf("Failed to take the screenshot. err: %d\n",GetLastError()); return 0; } // copy the screenshot buffer nCapture = SaveDC(hdcCapture); SelectObject(hdcCapture,hbmCapture); BitBlt(hdcCapture,h,dc,SRCCOPY); RestoreDC(hdcCapture,nCapture); DeleteDC(hdcCapture); DeleteDC(dc); // save the buffer to a file pScreenShot = new Bitmap(hbmCapture,(HPALETTE)NULL); EncoderParameters encoderParams; encoderParams.Count = 1; encoderParams.Parameter[0].NumberOfValues = 1; encoderParams.Parameter[0].Guid = EncoderQuality; encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong; encoderParams.Parameter[0].Value = &uQuality; GetEncoderClsid(L"image/jpeg",&imageCLSID); iRes = (pScreenShot->Save(lpszFilename,&imageCLSID,&encoderParams) == Ok); delete pScreenShot; DeleteObject(hbmCapture); GdiplusShutdown(gdiplusToken); return iRes; }
好的,经过这么多的努力,这里的答案是:
原文链接:https://www.f2er.com/windows/370816.htmlint SaveJpeg(HBITMAP hBmp,LPCWSTR lpszFilename,ULONG uQuality) { ULONG *pBitmap = NULL; CLSID imageCLSID; EncoderParameters encoderParams; int iRes = 0; typedef Status (WINAPI *pGdipCreateBitmapFromHBITMAP)(HBITMAP,HPALETTE,ULONG**); pGdipCreateBitmapFromHBITMAP lGdipCreateBitmapFromHBITMAP; typedef Status (WINAPI *pGdipSaveImageToFile)(ULONG *,const WCHAR*,const CLSID*,const EncoderParameters*); pGdipSaveImageToFile lGdipSaveImageToFile; // load GdipCreateBitmapFromHBITMAP lGdipCreateBitmapFromHBITMAP = (pGdipCreateBitmapFromHBITMAP)GetProcAddress(hModuleThread,"GdipCreateBitmapFromHBITMAP"); if(lGdipCreateBitmapFromHBITMAP == NULL) { // error return 0; } // load GdipSaveImageToFile lGdipSaveImageToFile = (pGdipSaveImageToFile)GetProcAddress(hModuleThread,"GdipSaveImageToFile"); if(lGdipSaveImageToFile == NULL) { // error return 0; } lGdipCreateBitmapFromHBITMAP(hBmp,&pBitmap); iRes = GetEncoderClsid(L"image/jpeg",&imageCLSID); if(iRes == -1) { // error return 0; } encoderParams.Count = 1; encoderParams.Parameter[0].NumberOfValues = 1; encoderParams.Parameter[0].Guid = EncoderQuality; encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong; encoderParams.Parameter[0].Value = &uQuality; lGdipSaveImageToFile(pBitmap,lpszFilename,&encoderParams); return 1; }
>什么是hModuleThread?看看在here.你可以用GetModuleHandle()
>什么是GetEncoderClsid?看here.
现在的问题是,如何将编码的pBitmap(作为jpeg)保存到BYTE缓冲区?