本示例截图区域为有焦点窗口区域
第一步注册热键
RegisterHotKey(m_hWnd,0x01,NULL,VK_SNAPSHOT);
第2步处理热键
LRESULT CTESTDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
if(message==WM_HOTKEY)
{
if(wParam==0x01)
{
CWnd* wnd1=GetDesktopWindow();
if(wnd1)
{
CWnd* wnd2= wnd1->GetForegroundWindow();
if(wnd2)
{
CString name;
wnd2->GetWindowText(name);
RECT rect;
wnd2->GetWindowRect(&rect);
HBITMAP hBitmap;
hBitmap=CopyScreenToBitmap(&rect);
SetForegroundWindow();
CFileDialog dlg(TRUE,".bmp",name,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY,"BMP 文件(*.bmp)|*.bmp||",this);
if(dlg.DoModal()== IDOK)
{
CString path=dlg.GetPathName();
if(dlg.GetFileExt()==_T(""))
path+=_T(".bmp");
SaveNewImage(hBitmap,path,32);
CString str;
str.Format(_T("已将窗口“%s”位图保存到:%s"),name,path);
MessageBox(str,_T("提示"),MB_OK);
}
}
}
}
}
return CDialog::WindowProc(message, wParam, lParam);
}
第3步 添加CopyScreenToBitmap函数,本函数的目的在于将指定区域的图片拷贝到位图中.
//lpRect 代表选定区域
HBITMAP CTESTDlg::CopyScreenToBitmap(LPRECT lpRect)
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap
(hScrDC, nWidth, nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
hScrDC, nX, nY, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
//得到屏幕位图的句柄
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 返回位图句柄
return hBitmap;
}
第4步 将位图保存为bmp格式
BOOL CTESTDlg::SaveNewImage(HBITMAP hbitmap, CString filename, int nColor)
{
BITMAP Bitmap;
HDC hDC;
DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
HANDLE fh, hDib, hPal,hOldPal=NULL;
if (nColor<= 8)
dwPaletteSize = (1<<nColor) *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 = nColor;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmBitsSize = ((Bitmap.bmWidth * nColor+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, Bitmap.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
(BITMAPINFO *)lpbi, DIB_RGB_COLORS);
if (hOldPal)
{
SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL,hDC);
}
fh = CreateFile(filename, GENERIC_WRITE,
0,//not be shared
NULL, //cannot be inherited
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;
//write file header
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
//write bmp data
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
DeleteObject(hbitmap);
return TRUE;
}