这是第二次发帖子额!
最近我做了个截图的程序,已经实现的功能是双击选择区域后自动保存。但是本人想改进为双击后截图显示在自动新建的文档上,然后保存。我的程序通过CopyScreenToBitmap(LPRECT lpRect)得到了截图的句柄HBITMAP hMap = CopyScreenToBitmap(&rect)。(rect是截图的矩形区域) 新建文档还是很好实现的 ,问题关键是怎么把图显示在它上面。由于我这个程序中用的是别人现成的DIB的封装,view中的OnDraw函数如下:
void CMy51View::OnDraw(CDC* pDC)
{
//获取文档类指针
CMy51Doc* pDoc = GetDocument(); //返回m_dib的指针
ImgCenterDib *pDib=pDoc->GetPDib(); //获取DIB的尺寸
CSize sizeFileDib = pDib->GetDimensions(); //显示DIB
pDib->Draw(pDC, CPoint(0, 0), sizeFileDib);
}其中的pDC就是设备环境指针。我现在得到的只是个位图的句柄(HBITMAP hMap ),位图数据也只是在内存里而已,不是一个位图文件的,感觉这与显示一副现成的位图文件是不一样的。封装的DIB类中有DIB的显示函数Draw( )。我就想在取得pDC后,调用Draw(pDC, CPoint(0, 0), sizeFileDib)来显示的。前些天有高手指点,建议写个OnEraseBkgnd(CDC* pDC),如下:
CBitmap * m_pBitmap //背景位图的指针
BOOL CScreenDlg::OnEraseBkgnd(CDC* pDC)
{
BITMAP bmp;
m_pBitmap->GetBitmap(&bmp); CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC); dcCompatible.SelectObject(m_pBitmap); CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY); return TRUE;
}
但本人不知如何用调用它。另外我的对话框类里还没有OnDraw和OnPaint函数,请问有必要建吗?请各位想想办法,最好有详细的代码,本人新手!麻烦大家了!
最近我做了个截图的程序,已经实现的功能是双击选择区域后自动保存。但是本人想改进为双击后截图显示在自动新建的文档上,然后保存。我的程序通过CopyScreenToBitmap(LPRECT lpRect)得到了截图的句柄HBITMAP hMap = CopyScreenToBitmap(&rect)。(rect是截图的矩形区域) 新建文档还是很好实现的 ,问题关键是怎么把图显示在它上面。由于我这个程序中用的是别人现成的DIB的封装,view中的OnDraw函数如下:
void CMy51View::OnDraw(CDC* pDC)
{
//获取文档类指针
CMy51Doc* pDoc = GetDocument(); //返回m_dib的指针
ImgCenterDib *pDib=pDoc->GetPDib(); //获取DIB的尺寸
CSize sizeFileDib = pDib->GetDimensions(); //显示DIB
pDib->Draw(pDC, CPoint(0, 0), sizeFileDib);
}其中的pDC就是设备环境指针。我现在得到的只是个位图的句柄(HBITMAP hMap ),位图数据也只是在内存里而已,不是一个位图文件的,感觉这与显示一副现成的位图文件是不一样的。封装的DIB类中有DIB的显示函数Draw( )。我就想在取得pDC后,调用Draw(pDC, CPoint(0, 0), sizeFileDib)来显示的。前些天有高手指点,建议写个OnEraseBkgnd(CDC* pDC),如下:
CBitmap * m_pBitmap //背景位图的指针
BOOL CScreenDlg::OnEraseBkgnd(CDC* pDC)
{
BITMAP bmp;
m_pBitmap->GetBitmap(&bmp); CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC); dcCompatible.SelectObject(m_pBitmap); CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY); return TRUE;
}
但本人不知如何用调用它。另外我的对话框类里还没有OnDraw和OnPaint函数,请问有必要建吗?请各位想想办法,最好有详细的代码,本人新手!麻烦大家了!
解决方案 »
- vc对话框里装在bmp位图,点击2个按钮,可以浏览上一幅或下一幅位图
- Process32First、Process32Next函数的疑难问题
- 如何获取橡皮筋矩形的坐标
- VCM 问题! ICCompress 或者ICSeqcompressFrame函数 怎么能让他们每间隔10个或者20就产生一个KeyFrame呢!
- 控件mscomm中怎么获得其校验位的值,用什么命令(VC)
- 关于ime消息的问题
- 为何我无法在静态拆分窗口中加入CFormView派生的类?!
- 非模态窗口的问题
- WH_GETMESSAGE钩子的问题[SDK]刚才那个不知道为什么打不开!
- 我的VC6在98下不能用了,症状如下:Linking...Error spawning link.exe star.exe - 1 error(s), 0 warning(s),可是放入VC++的安装光盘就可以编译,这是怎么回事
- 周末散个分。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
- 近期想往杭州找份工作,请老鸟谈谈经验!
==>在消息中,添加WM_PAINT消息事件
就可以了
{
HDC hDC;
//设备描述表
int iBits;
//当前显示分辨率下每个像素所占字节数
WORD wBitCount;
//位图中每个像素所占字节数
//定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;
BITMAP Bitmap;
//位图属性结构
BITMAPFILEHEADER bmfHdr;
//位图文件头结构
BITMAPINFOHEADER bi;
//位图信息头结构
LPBITMAPINFOHEADER lpbi;
//指向位图信息头结构指针
HANDLE fh, hDib, hPal;
HPALETTE 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;
else
wBitCount = 32;
//计算调色板大小
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;
//为位图内容分配内存/*xxxxxxxx计算位图大小分解一下(解释一下上面的语句)xxxxxxxxxxxxxxxxxxxx
//每个扫描行所占的字节数应该为4的整数倍,具体算法为:
int biWidth = (Bitmap.bmWidth*wBitCount) / 32;
if((Bitmap.bmWidth*wBitCount) % 32)
biWidth++; //不是整数倍的加1
biWidth *= 4;//到这里,计算得到的为每个扫描行的字节数。
dwBmBitsSize = biWidth * Bitmap.bmHeight;//得到大小
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
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,(UINT)Bitmap.bmHeight,(LPBYTE)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)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, (LPBYTE)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPBYTE)lpbi, sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize , &dwWritten, NULL);
//m_pImgData指向位图数据起始位置
m_pImgData=(LPBYTE)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize; //清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
那应该在对话框的程序里添加Onpaint啦!可是总感觉不是画吧 因为图像数据就在内存里啊,怎么画啊?晕啦
void CMy51View::OnDraw(CDC* pDC)
{
BITMAP bmp;
m_pBitmap->GetBitmap(&bmp); CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC); dcCompatible.SelectObject(m_pBitmap); CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);}
为什么还要那么麻烦地放入文档视图内?
那样 的话你必须把裁得的区域数据进行传递。在
CMy51View内加入一个成员
CBitmap * m_pBitmap //背景位图的指针比如你在原来的Dialog内响应双击后,得到了CMy51View的操作指针 pView
pView->m_pBitmap = this->m_pBitmap [color=#008000]//把得到的位图数据放入View内的成员
之后就是按9楼代码处理。[/color]统一用基于Dialog的MFC程序,新建一个DialogA,
通过指针传递来操作DialogA内的OnPaint 进行代码移植。
这个奸人 大家留言骂他
我的程序是在基于对话框的板块中啊!放在文档里是为了好保存成文件的,以后要处理这截取的图像。依你的意思看,从简单易实现的角度来看,我应该怎么做呢?你说在View里的OnDraw中添加那些代码是在原有的基础上(帖子上有,最上面)添加吗? 我来试试啊! 麻烦你回帖子啦!谢谢啦!我有不懂处再问你啊!
CBitmap * m_pBitmap //背景位图的指针
但是Dialog内响应双击后,得到了CMy51View的操作指针 pView
pView->m_pBitmap = this->m_pBitmap 中m_pBitmap 就没定义了啊! 怎么办?
this->m_pBitmap 指的是你的MDI工程中,截图对话框模块的成员。
可用
m_pBitmap = CBitmap::FromHandle(CopyScreenToBitmap(&rect));保存入m_pBitmap内。
为了防止出错,等建议不要关闭截图对话框,
通过ShowWindow
截图时显示
其它时候隐藏
在CMainFrame内进行控制。
m_pBitmap = CBitmap::FromHandle(CopyScreenToBitmap(&rect)); 就会报错,m_pBitmap没有定义。
我不知指针传递怎么的,请详细指点下! 我现在的目的很简单,就是显示出来就可以了。
指针传递的问题你要自己看书学习你的截图Dialog内定义
CBitmap * m_pBitmapRect。View内 定义CBitmap * m_pBitmapView。截图Dialog内响应双击后,得到了CMy51View的操作指针 pView
pView->m_pBitmapView = m_pBitmapRect;//如此传递
如果还报错,请把具体内容帖出来。
我已按照你说的去添加了代码,但是对于以下代码的添加之处有点不清楚
void CMy51View::OnDraw(CDC* pDC)
{
BITMAP bmp;
m_pBitmap->GetBitmap(&bmp); CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC); dcCompatible.SelectObject(m_pBitmap); CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);}
添加OnDraw里会运行会出错的,原来OnDraw里的代码是不能删的,到底添加在哪儿合适呢?请指点下啊!
{
CClockDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
// 加在这里,另外,请注意BitBlt的用法。
}
我现在的代码OnDraw里面已经是如下了: 这是别人修改过的,因为我用了别人封装好的DIB了。所以再把那代码加上去,就直接运行报错了。OnDraw就是显示嘛,我感觉把要显示的数据传递到这儿应该就可以显示了呀!是不是应该另外建个函数的?
void CMy51View::OnDraw(CDC* pDC)
{
//获取文档类指针
CMy51Doc* pDoc = GetDocument();//返回m_dib的指针
ImgCenterDib *pDib=pDoc->GetPDib();//获取DIB的尺寸
CSize sizeFileDib = pDib->GetDimensions();//显示DIB
pDib->Draw(pDC, CPoint(0, 0), sizeFileDib);
}
对此我也不熟悉,
你要自己看明白别人的类的
每个函数、变量的含义。一个View内只能有一个
OnDraw(CDC* pDC)
除非你重载出另外一个。如果是我之前给你推荐的那个QQ 截图程序,按9楼的代码就没问题。
对!我用的是别人封装好的DIB,可以打开,读取bmp图像,因为后面用到的一些算法实现都是以此为基类派生的,所以OnDraw里面已经改动过了。如果删去的话,估计连打开图像就不可以了。你看现在怎么办啊?
void CScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CRect rect;
rect.left =(this->startPt.x<this->endPt.x)?this->startPt.x:this->endPt.x;
rect.top = (this->startPt.y<this->endPt.y)?this->startPt.y:this->endPt.y;
rect.right =(this->endPt.x>this->startPt.x)?this->endPt.x:this->startPt.x;
rect.bottom =(this->endPt.y>this->startPt.y)?this->endPt.y:this->startPt.y;
HBITMAP hMap = CopyScreenToBitmap(&rect);
m_pBitmap=CBitmap::FromHandle(CopyScreenToBitmap(&rect)); CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd);
//发送一个新建文件的消息,创建一个新的文档-视图
pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW); //获取新建视图指针
CMy51View* pView=(CMy51View*)pFrame->MDIGetActive()->GetActiveView(); //获取相关联的新的文档类指针
CMy51Doc* pDocNew=pView->GetDocument(); //获取新文档中的ImgCenterDib类对象指针
ImgCenterDib *dibNew=pDocNew->GetPDib(); pView->m_pBitmapView = m_pBitmap; CDC* pDC;
pDC = this->GetDC();
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC); dcCompatible.SelectObject(m_pBitmap); GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY); //文档数据置脏,提示存盘信息
pDocNew->SetModifiedFlag(TRUE); //各视图刷新显示
pDocNew->UpdateAllViews(pView); dibNew->SaveBitmapToFile(hMap,"C:\\截屏.bmp");
this->EndDialog(0); CDialog::OnLButtonDblClk(nFlags, point);
}
一个主程序里的View类里只能有一个OnDraw,里面的内容是不能变的,因为涉及到很多子功能都要沿用这一个基类的。可不可以不改动OnDraw里,而实现显示呢?我认为应该可行啊!
我现在编这个截图的程序是单独编的,没有和总程序挂上钩,以后还是要嵌入到其中,不知能不能成功的,到时候有问题的话,我再请教你啊!
那么你必须要有显示的容器才可能,
也可以考虑截图后,New一个新的对话框,把截图得到的BMP内存数据复制过去,并显示。
之后就可以CDialog::OnLButtonDblClk(nFlags, point);// 放在第一句…… // 相关内容this->EndDialog(0);//放在最后一句// 为什么是这个顺序,自己思考一下
}
我的意思是在不改动我现有的OnDraw函数的前提下,能否依然显示在文档里面。OnDraw函数改动了,那么打开显示别的任意的图片就不得行了啊!你看还有没有别的方法?
{
//获取文档类指针
CMy51Doc* pDoc = GetDocument();//返回m_dib的指针?
//m_dib是什么类型?
//ImgCenterDib是什么类型?ImgCenterDib *pDib=pDoc->GetPDib();//获取DIB的尺寸
CSize sizeFileDib = pDib->GetDimensions();//显示DIB
pDib->Draw(pDC, CPoint(0, 0), sizeFileDib);
}以上是我的疑问,我认为你还是仔细理解人家的DIB类后再作决策。1. 关键在于明确ImgCenterDib *pDib 与 CBitmap* m_pBitmapView
之间的关系后,才可以移植组合入同一个View内进行显示。2. 不然,就让文档分工显示。
你所言极是,有些地方还是有点看不懂的。我把代码传到我的资源里去了,如果你有时间的话,可以看看的啊!ImgCenterDib是一个DIB类,m_dib是它的一个对象。ImgCenterDib *pDib=pDoc->GetPDib();这句话是获取DIB的指针。
http://download.csdn.net/source/2343300
我上传的图像截取的下载地址 http://download.csdn.net/source/2343300
SetStretchBltMode(pDC->m_hDC,BLACKONWHITE|WHITEONBLACK);
StretchDIBits(pDC->m_hDC, 0, 0, w, h, 0, 0, Width, Height,
pDoc->pDataL[nLayer], pDoc->pBitmapInfoL[nLayer], DIB_RGB_COLORS, SRCCOPY);
pData为数据区首指针
pBitmapInfo为信息头指针
既然你获得了图片句柄,这个是很容易获得的。在对话框中显示,要重载OnPaint。
可以添加一个CStatic,得到CWnd类指针后,GetDC(),然后绘图
我不是想在对话框里显示,是在新建文档里显示的。你看看我的程序吧!http://download.csdn.net/source/2343300
To YANDONGLIANG:不好意思,这代码不是我的,我无权赠予,而且这个也和矢量图无关,有兴趣的话你可以向楼主索要
http://download.csdn.net/source/2343300 你去下载嘛
CDIB 直接用Draw函数啊。不用别人的类用API也是一样。
另外请问楼主是不是做遥感的啊?
我看到了的,你加了个OnPaint消息处理函数,设置为私有的。但是为什么加上这个函数后,就不能打开bmp图像了呢?请指点下啊!