位图处理

wz300192 2003-10-21 11:59:38
在Microsort Win32程序员参考大全第29章位图使用部分中有这样一段代码
hdcScreen=CreateDC("DISPLAY","NULL",NULL,NULL);
if (hdcScreen==0 )
{
a=GetLastError();
};

hdcCompatible=CreateCompatibleDC(hdcScreen);
b=GetDeviceCaps(hdcScreen,HORZRES);
c=GetDeviceCaps(hdcScreen,VERTRES);
hbmScreen=CreateCompatibleBitmap(hdcScreen,b,c);
ShowWindow(_hWnd,SW_HIDE);

if (!SelectObject(hdcCompatible,hbmScreen))
{
a=GetLastError();
};
GetObject(hbmScreen,sizeof(BITMAP),&bmp);

d=BitBlt(hdc,0,0,bmp.bmWidth ,bmp.bmHeight,
hdcCompatible,0,0,SRCCOPY);
ShowWindow(_hWnd,SW_SHOW);

按照书中的示意可以实现将Screen拷贝,显示在当前窗口中,但我反复测试出口都是空白(运行环境Win2000server)。将hbmScreen存成bmp文件后是一3M的空白图像。百思不解,请指点迷惊。
另CreateDC、CreateCompatibleDC、CreateCompatibleBitmap参照msdn能够知其意,但总感觉没能透彻理解,能否形象化的解释一下,或推荐学习材料,不胜感激。


...全文
54 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
csdnzhu 2003-10-23
  • 打赏
  • 举报
回复
给你提供一个把屏幕拷贝下来并保存成文件的函数



/////////////////////////////////////////////////////////////////////////////
//////////////*************//////////////////////////////////////////////////
//本函数实现把一个存在于内存中的代表一张位图的位图句柄给存到文件中去。
//第一个参数是位图句柄
//第二个参数是要保存的位图文件名,带全路径
//返回值为FALSE表示函数失败
//返回值为TRUE表示函数成功
BOOL SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName) //hBitmap 为屏幕位图句柄
{ //lpFileName 为位图文件名带全路径
HDC hDC; //设备描述表
int iBits;//当前显示分辨率下每个像素所占字节数
WORD wBitCount;//位图中每个像素所占字节数
//定义调色板大小, 位图中像素字节大小 位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0,dwBmBitsSize, dwDIBSize, dwWritten;
BITMAP Bitmap;//位图属性结构
BITMAPFILEHEADER bmfHdr;//位图文件头结构
BITMAPINFOHEADER bi;//位图信息头结构
LPBITMAPINFOHEADER lpbi;//指向位图信息头结构
HANDLE fh, hDib; //定义文件,分配内存句柄,调色板句柄
HPALETTE hPal,hOldPal=NULL;
//计算位图文件每个像素所占字节数
hDC = ::CreateDC("DISPLAY",NULL,NULL,NULL);
iBits = ::GetDeviceCaps(hDC, BITSPIXEL)* ::GetDeviceCaps(hDC, PLANES);
::DeleteDC(hDC);
if (iBits<=1)
wBitCount = 1;
else if (iBits <=4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else if (iBits<=24)
wBitCount = 24;
//计算调色板大小
if (wBitCount<= 8)
dwPaletteSize=(1<<wBitCount)*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 = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

dwBmBitsSize =((Bitmap.bmWidth*wBitCount+31)/32)* 4*Bitmap.bmHeight;
//为位图内容分配内存
hDib = ::GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = (HPALETTE)::GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, hPal, FALSE);
::RealizePalette(hDC);
}
// 获取该调色板下新的像素值
::GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
(LPBITMAPINFO )lpbi, DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
::SelectPalette(hDC, hOldPal, TRUE);
::RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//创建位图文件
fh = ::CreateFile(lpFileName, GENERIC_WRITE,0, NULL, 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;
// 写入位图文件头
::WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
::WriteFile(fh, (LPSTR)lpbi, dwDIBSize,&dwWritten, NULL);
//清除
::GlobalUnlock(hDib);
::GlobalFree(hDib);
::CloseHandle(fh);
return TRUE;
}
///////************************************************/////////
//本程序实现把位图句柄所指向的内存中的位图给贴到剪贴板
//参数一是位图句柄
//参数二是要向剪贴板粘图像的程序窗口句柄,默认为本窗口
//返回值:因为暂时没有排错机制,所以返回void
void CopyBitmapToClipboard(HBITMAP hBitmap,HWND hwnd=NULL)
{
if (::OpenClipboard(hwnd))//hwnd为程序窗口句柄
{
::EmptyClipboard();//清空剪贴板
//把屏幕内容粘贴到剪贴板上,hbitmap 为刚才的屏幕位图句柄
::SetClipboardData(CF_BITMAP, hBitmap);
::CloseClipboard();//关闭剪贴板
}
}
//此函数用到了上面的两个函数,用来实现把屏幕图像取下来,通过不同的参数设置将图像传往不同的地方
//第一个参数是要把屏幕图像显示在哪个窗口的句柄
//第二个参数具体指明了要把屏幕图像显示在哪里
//等于1时,只在窗口显示
//等于2时,只贴在剪贴板
//等于3时,只保存为文件
//等于4时,以上三种情况都实现
//第三个参数是图像要保存的文件名。
HBITMAP CatchScreen(HWND hwnd,int ToWhere,LPSTR FilePathName)
{
HDC ScreenDC=::GetDC(NULL);
HDC MyDC=::GetDC(hwnd);
HBITMAP newbitmap,oldbitmap;
HDC MemDC=::CreateCompatibleDC(ScreenDC);//创建与屏幕相对应的内存句柄
int x = ::GetSystemMetrics(SM_CXSCREEN) ;
int y = ::GetSystemMetrics(SM_CYSCREEN) ;//获得屏幕的长与宽
newbitmap=::CreateCompatibleBitmap(ScreenDC,x,y);//建一个与屏幕相关与大小相同的位图句柄,只有这样才能在内存中作图
oldbitmap = (HBITMAP)::SelectObject(MemDC, newbitmap);//把位图选入内存句柄,只有这样才能在内存中作图
::BitBlt(MemDC, 0, 0, x,y,ScreenDC,0,0, SRCCOPY);//把屏幕图像保存为内存位图
if(ToWhere==1 || ToWhere==4)
::BitBlt(MyDC,0,0,x,y,MemDC,0,0,SRCCOPY);//在指定窗口显示
if(ToWhere==2 || ToWhere==4)
{
newbitmap = (HBITMAP)::SelectObject(MemDC, oldbitmap);//把位图句选出,以备作其它的用处
CopyBitmapToClipboard(newbitmap);//贴在剪贴板
}
if(ToWhere==3 || ToWhere==4)
{
if(ToWhere==3)
newbitmap = (HBITMAP)::SelectObject(MemDC, oldbitmap);//把位图句选出,以备作其它的用处
SaveBitmapToFile(newbitmap, FilePathName);//存为文件
}
if(ToWhere<1 || ToWhere>4)
::MessageBox(hwnd,"输入错误,图形将不会显示,请再次参看函数说明","提示",MB_OK);
return newbitmap;


}

mct1025 2003-10-23
  • 打赏
  • 举报
回复
处理窗口的WM_PAINT消息
wz300192 2003-10-23
  • 打赏
  • 举报
回复
修改之后,hbmScreen已经得到了Screen的位图,我原先写的保存算法有错误,所以图没有显示出来,现在已能看到抓到的桌面。
我没有引用MFC,我在注册窗口类时选用了CS_VREDRAW|CS_HREDRAW 风格,这样应是重画了窗体,请问我应如何修改??
wz300192 2003-10-22
  • 打赏
  • 举报
回复
mct1025(macuntao)的修改方案与书上写法相同(上面我写法的错误是由于调试程序后没有完全改写正确),但仍不能拷贝桌面,表现与问题描述相同。
mct1025 2003-10-22
  • 打赏
  • 举报
回复
修改之后,hbmScreen已经得到了Screen的位图

问题可能是随后调用的ShowWindow(_hWnd,SW_SHOW);重画了窗口
你需要重载OnPaint或OnDraw,再BitBlt到窗口
foxmail 2003-10-21
  • 打赏
  • 举报
回复
应该是CreateBitmap(...,1,8,...);
忘了参数了
foxmail 2003-10-21
  • 打赏
  • 举报
回复
CreateCompatibleBitmap(..)和屏幕颜色位数一样的位图
CreateBitmap(8,1...)8位的位图
多Compatible也就是兼容当前显示模式的意思
mct1025 2003-10-21
  • 打赏
  • 举报
回复
因为,你的hbmScreen没有得到位图数据
把d=BitBlt(hdc,0,0,bmp.bmWidth ,bmp.bmHeight,
hdcCompatible,0,0,SRCCOPY);
改成d=BitBlt(hdcCompatible,0,0,bmp.bmWidth ,bmp.bmHeight,
hdcScreen,0,0,SRCCOPY);

19,468

社区成员

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

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