位图处理

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能够知其意,但总感觉没能透彻理解,能否形象化的解释一下,或推荐学习材料,不胜感激。


...全文
52 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);
我将带领大家来系统学习Windows的窗口编程,包括消息、窗口、GDI绘图、游戏开发等。本课程比较基础,非常适合初学者入门,读者可以边学习边实践。具体的章节目录和课程内容如下所示:---------------------------------------------Windows游戏编程系列之1:GUI界面编程及游戏入门实战1、Windows创建第一个窗口 WinMain入口函数 5进行Windows编程的调试手法 6窗口从哪里来? 7窗口编程的步骤 7窗口编程需要的主要结构 8窗口编程需要的主要API 92、Windows的窗口过程与消息机制 如何留住窗口? 121)Windows的消息与消息循环 142)消息处理函数与常用消息 17)Windows的窗口过程函数 19 3、GDI编程之设备上下文 1)GDI的通用编程框架 222)GDI的绘图步骤 253)GDI获取设备句柄 254、GDI编程之绘制几何图形 画点、线 28颜色COLORREF 29矩形 29画圆、饼图、弦图 305、GDI编程之自定义画笔画刷画笔简介 32画刷简介 33画笔案例 33画刷案例 346、GDI编程之绘制文字 DrawText函数 35TextOut 函数 (wingdi.h) 36CreateFont函数 37绘制文本案例 377、GDI编程之绘制位图 位图简介 381)在资源中添加位图资源 392)从资源中加载位图: LoadBitmap 393)创建一个与当前DC相匹配的DC(内存DC) 394)将bitmap放入匹配的DC中:SelectObject 405)成像(1:1 比例 ) 406)取出位图 407)释放位图 418)释放匹配的DC 41绘制位图案例 41   8、Windows鼠标键盘消息 一、键盘消息 421、键盘消息 422、消息参数: 423、消息的使用: 424、键盘消息的案例代码 43二、鼠标消息 441、基本鼠标消息 442、双击消息 443、滚轮消息 454、不响应双击消息 45 9、Windows定时器消息 定时器消息介绍 47创建定时器 47关闭定时器 47定时器消息案例代码 4810、GDI游戏之跳舞动画 11、GDI游戏之走路动画 12、GDI贪吃蛇游戏实战  

19,468

社区成员

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

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