下面要实现的程序是:从磁盘上读取一个jpg,bmp,或者gif图像,然后在程序中用鼠标画出一个矩形,表示图像的显示范围
//打开文件对话框,记下路径名
void CMyView::OnFile()
{
// TODO: Add your command handler code here
CFileDialog dlg(TRUE);
dlg.m_ofn.lpstrFilter="All Files(*.*)\0*.*\0textfiles(*.txt)\0*.txt\0\0";
if(dlg.DoModal()==IDOK)
{
bmpname=dlg.GetPathName();
Isput=TRUE;
}
}
//左键单击处理
void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
if(Isput==TRUE){
if(pushnumb==0)
{
oldpoint=point;
oripoint=point;
pushnumb=1;
SetCapture();
}
else
{
ReleaseCapture();
float x1=min(oripoint.x,point.x);
float y1=min(oripoint.y,point.y);
float x2=max(oripoint.x,point.x);
float y2=max(oripoint.y,point.y);
//绘制图像
this->DrawJpg(&dc,x1,y1,x2-x1,y2-y1);
//this->DrawBmp1(&dc,x1,y1,
// x2-x1,y2-y1,bmpname,1);
pushnumb=0;
}
}
CView::OnLButtonDown(nFlags, point);
}
//鼠标移动消息处理
void CMyView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(Isput==TRUE&&pushnumb==1)
{
CClientDC dc(this);
dc.SelectStockObject(NULL_BRUSH);
//绘制橡皮线矩形
dc.SetROP2(R2_NOT);
dc.Rectangle(oripoint.x,oripoint.y,oldpoint.x,oldpoint.y);
dc.Rectangle(oripoint.x,oripoint.y,point.x,point.y);
oldpoint=point;
}
CView::OnMouseMove(nFlags, point);
}
//绘制图像的过程
void CMyView::DrawJpg(CDC *pDC,int x,int y,int width,int high)
{
IPicture *pDic;
IStream *pStm;
CFileStatus fstatus;
CFile file;
LONG cb;
BOOL bSuccess = TRUE;
// 打开文件并获得文件的真实大小
if(file.Open(bmpname,CFile::modeRead) && file.GetStatus(bmpname,fstatus)
&& ((cb=fstatus.m_size)!=-1))
{
// 从堆中分配指定数量字节的一整块,这时系统无法提供零零碎碎的局部或全局的堆
HGLOBAL hglobal=::GlobalAlloc(GMEM_MOVEABLE,cb);
LPVOID pvData=NULL;
if(hglobal != NULL)
{
// 锁定全局内存对象并返回它的首地址
if((pvData=::GlobalLock(hglobal))!=NULL)
{
// 把文件内容读进全局内存对象的地址空间中
file.ReadHuge(pvData,cb);
// GlobalUnlock函数把以GMEM_MOVEABLE方式分配的内存对象的锁定计数器减1
::GlobalUnlock(hglobal);
// 从全局内存中创建stream对象,第二个参数指定当stream释放时是否自动释放全局内存
::CreateStreamOnHGlobal(hglobal,TRUE,&pStm);
// 创建一个新的picture对象并用stream对象中的内容初始化
if(SUCCEEDED(::OleLoadPicture(pStm,fstatus.m_size,
TRUE,IID_IPicture,(LPVOID*)&pDic)))
{
// 释放不要的stream对象并清空stream指针(千万不能省略,否则有内存没释放掉)
pStm->Release();
pStm = NULL;
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
pDic->get_Width(&hmWidth);
pDic->get_Height(&hmHeight);
int nImageWidth = MulDiv(hmWidth, ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSX), 2540);
int nImageHeight = MulDiv(hmHeight,::GetDeviceCaps(pDC->m_hDC, LOGPIXELSY), 2540);
// 注意倒数几个参数的选择,可能出现翻转
if(FAILED(pDic->Render(pDC->m_hDC,x,y,nImageWidth ,nImageHeight ,0,hmHeight,
hmWidth,-hmHeight,NULL)))
AfxMessageBox("Failed!");
pDic->Release();
}
else
AfxMessageBox("Error Loading Picture from stream");
}
}
}
else
AfxMessageBox("cann't open image file!");
}
更新:
如果要获得象素大小,而不是上面的OLE_YSIZE_HIMETRIC ,可以用下面的方法转换:
int width = MulDiv(hmWidth, ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSX), 2540);
int hight = MulDiv(hmHeight,::GetDeviceCaps(pDC->m_hDC, LOGPIXELSY), 2540);
当然如果只是导入bmp格式的不用那么麻烦,编写下面这个函数就可以了
void CMyView::DrawBmp1(CDC *pDC, int x, int y, int width, int high, CString fName, int DrawMode)
{
CDC dc;
dc.CreateCompatibleDC(pDC);
//从外部文件导入
HBITMAP b=(HBITMAP)::LoadImage(NULL,fName,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);
CBitmap bitmap;
bitmap.Attach(b);
BITMAP bm;
bitmap.GetBitmap(&bm);
dc.SelectObject(&bitmap);
//显示图像
pDC->StretchBlt(x,y,width,high,&dc,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
bitmap.Detach();
}
其他理论文章导读:
http://www.diybl.com/course/3_program/vc/vc_js/2008831/138954.html
评论