如何把父窗口的图像存Bitmap里?

幻灵小龙 2011-08-22 02:09:52
用GDI+,有时需要贴父窗口的图像,不知道如何父窗口的图像存一个Bitmap里,这样就可以随时DrawImage了。
...全文
125 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
Eleven 2011-08-22
  • 打赏
  • 举报
回复
http://blog.csdn.net/visualeleven/article/details/6202796
shenzhiyong2008 2011-08-22
  • 打赏
  • 举报
回复
先到窗口中,再拿图。一步一步找到逻辑。。
worldy 2011-08-22
  • 打赏
  • 举报
回复
[Quote=引用楼主 tilongzs 的回复:]
用GDI+,有时需要贴父窗口的图像,不知道如何父窗口的图像存一个Bitmap里,这样就可以随时DrawImage了。
[/Quote]

HANDLE hMemDC=CreateCompatibleDC(hDC);
RECT Rect;
BOOL GetWindowRect(hWnd, &Rect);
int w=Rect.Right-Rect.Left;
int h=Rect.Bottom-Rect.Top;
BITMAP hBmp=CreateCompatibleBitmap(hDC,w,h);
SelectObject(hMemDC,hBmp);

Bitblt(hMemDC,0,0,w,h,hDC,0,0,13369376);//hDC中的位图拷贝到了hBmp中了
幻灵小龙 2011-08-22
  • 打赏
  • 举报
回复
楼上要能明白CBitmap和Bitmap的区别就好了。
hnzlk 2011-08-22
  • 打赏
  • 举报
回复

HBITMAP hbmp;
CBitmap bmp;
bmp.Attach(hbmp);
hnzlk 2011-08-22
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 tilongzs 的回复:]

我只是想把数据存到一个Bitmap对象里,楼上几位把位图输出的方法写那么详细……
谁能来点简单的方法。
[/Quote]
自己提炼一下,很简单的。
幻灵小龙 2011-08-22
  • 打赏
  • 举报
回复
我只是想把数据存到一个Bitmap对象里,楼上几位把位图输出的方法写那么详细……
谁能来点简单的方法。
hnzlk 2011-08-22
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 tompaz 的回复:]

引用 7 楼 hnzlk 的回复:

C/C++ code

void CaaaDlg::OnBnClickedButton4()
{
// 目标窗体不能最小化
HWND src_hWnd = ::FindWindowW(NULL, L"计算器");
RECT rc;
::GetWindowRect(src_hWnd, &rc);

// 24位图的BITM……
[/Quote]
最小化不行
tompaz 2011-08-22
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 hnzlk 的回复:]

C/C++ code

void CaaaDlg::OnBnClickedButton4()
{
// 目标窗体不能最小化
HWND src_hWnd = ::FindWindowW(NULL, L"计算器");
RECT rc;
::GetWindowRect(src_hWnd, &rc);

// 24位图的BITMAPINFO
BI……
[/Quote]
这个最小化也能么?不可思议
hnzlk 2011-08-22
  • 打赏
  • 举报
回复

void CaaaDlg::OnBnClickedButton4()
{
// 目标窗体不能最小化
HWND src_hWnd = ::FindWindowW(NULL, L"计算器");
RECT rc;
::GetWindowRect(src_hWnd, &rc);

// 24位图的BITMAPINFO
BITMAPINFO *pBITMAPINFO = (BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER));
memset(pBITMAPINFO, 0, sizeof(BITMAPINFOHEADER));
BITMAPINFOHEADER *pInfo_Header = (BITMAPINFOHEADER *)pBITMAPINFO;
pInfo_Header->biSize = sizeof(BITMAPINFOHEADER);
pInfo_Header->biWidth = rc.right - rc.left;
pInfo_Header->biHeight = rc.bottom - rc.top;
pInfo_Header->biPlanes = 1;
pInfo_Header->biBitCount = 24;
pInfo_Header->biCompression = BI_RGB;

// 创建兼容DC 打印目标窗体
HDC src_hdc = ::GetWindowDC(src_hWnd);
HBITMAP hBitmap = ::CreateCompatibleBitmap(src_hdc,
pInfo_Header->biWidth, pInfo_Header->biHeight);
HDC hdcCompatible = CreateCompatibleDC(src_hdc);
::SelectObject(hdcCompatible, hBitmap);
::PrintWindow(src_hWnd, hdcCompatible, 0);
CDC *pdcCompatible = CDC::FromHandle(hdcCompatible);
::ReleaseDC(src_hWnd, src_hdc);


// 把兼容DC贴到DC上
CDC *pCurDC = this->GetDC();
pCurDC->BitBlt(0,0,pInfo_Header->biWidth, pInfo_Header->biHeight,pdcCompatible,0,0,SRCCOPY);

// 获得数据buf
DWORD bufSize = (pInfo_Header->biWidth * 3 + 3) / 4 * 4 * pInfo_Header->biHeight;
BYTE * pBuffer = new BYTE[bufSize];
if(GetDIBits(hdcCompatible, hBitmap, 0, pInfo_Header->biHeight, pBuffer,
pBITMAPINFO, DIB_RGB_COLORS) == 0)
{
AfxMessageBox(L"GetDIBits");
}

// 建立文件
CFile file;
file.Open(L"D:\\新图.bmp", CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);

// 写文件头
BITMAPFILEHEADER File_Header;
File_Header.bfType = 0x4d42;
File_Header.bfOffBits = sizeof(BITMAPFILEHEADER) + pInfo_Header->biSize;
File_Header.bfSize = File_Header.bfOffBits + bufSize;
File_Header.bfReserved1 = 0;
File_Header.bfReserved2 = 0;
file.Write(&File_Header, sizeof(BITMAPFILEHEADER));

// 写数据头
file.Write(pInfo_Header, sizeof(BITMAPINFOHEADER));

// 写数据
file.Write(pBuffer, bufSize);

// 关闭文件 释放内存
file.Close();
delete []pBuffer;
free(pBITMAPINFO);
::DeleteObject(hdcCompatible);
::DeleteObject(hBitmap);
this->ReleaseDC(pCurDC);
}

可以获取被隐藏的窗口图像。
buyong 2011-08-22
  • 打赏
  • 举报
回复
1、把图像放入内存DC,就是DDB
2、DDB->DIB
3、保存DIB为bitmap
后两步参考msdn的DDB转DIB,有源码。
Casbin开源社区 2011-08-22
  • 打赏
  • 举报
回复
GetWindowDC得到DC

PrintWindow打印窗口

ReleaseDC撤消DC

其中关键是PrintWindow函数,这是一个未被Windows.h正式引入的API函数,需要特殊声明

只要窗口没有最小化或者设置SW_HIDE,都可以截到,包括遮挡或者在屏幕外

这是主要的代码:

BOOL CBitmapDialog::SaveImage(HBITMAP hbitmap, LPSTR 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;
}

HBITMAP CBitmapDialog::GetWindowBitmap(HWND hWnd)
{
RECT rect;
::GetWindowRect(hWnd, &rect);

HDC hScrDC = ::GetDC(hWnd); //创建屏幕DC
HDC hMemDC = CreateCompatibleDC(hScrDC); //创建内存DC
HBITMAP bitmap = ::CreateCompatibleBitmap(hScrDC, rect.right - rect.left, rect.bottom - rect.top); //创建兼容位图
HBITMAP OldBitmap = (HBITMAP) ::SelectObject(hMemDC, bitmap); //把位图选进内存DC

MyPrintWindow(hWnd, hMemDC, 0);

int iX, iY;
for (iX = 0; iX < 5; iX ++)
{
for (iY = 0; iY < 5; iY ++)
{
if (GetPixel(hMemDC, iX, iY) == RGB(0, 0, 0))
{
SetPixel(hMemDC, iX, iY, RGB(255, 0, 255));
}
if (GetPixel(hMemDC, rect.right - rect.left - 1 - iX, iY) == RGB(0, 0, 0))
{
SetPixel(hMemDC, rect.right - rect.left - 1 - iX, iY, RGB(255, 0, 255));
}
if (GetPixel(hMemDC, iX, rect.bottom - rect.top - 1 - iY) == RGB(0, 0, 0))
{
SetPixel(hMemDC, iX, rect.bottom - rect.top - 1 - iY, RGB(255, 0, 255));
}
if (GetPixel(hMemDC, rect.right - rect.left - 1 - iX, rect.bottom - rect.top - 1 - iY) == RGB(0, 0, 0))
{
SetPixel(hMemDC, rect.right - rect.left - 1 - iX, rect.bottom - rect.top - 1 - iY, RGB(255, 0, 255));
}
}
}



::SelectObject(hMemDC, OldBitmap);

::DeleteDC(hMemDC) ; //删除内存DC
::ReleaseDC(NULL, hScrDC) ; //释放屏幕DC

return bitmap;
}
tompaz 2011-08-22
  • 打赏
  • 举报
回复
遮挡的话是取不到的
幻灵小龙 2011-08-22
  • 打赏
  • 举报
回复
麻烦说详细些。
hnzlk 2011-08-22
  • 打赏
  • 举报
回复
通过bitblt取得父窗口的图像,然后转换在Bitmap,然后drawimage

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧