我试图找到一个(有点)简单的方法来在窗口上截图,并将得到的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;
}
好的,经过这么多的努力,这里的答案是:
int 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缓冲区?