下面要實現的程序是:從磁盤上讀取一個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
posted on 2013-04-07 20:07
聶文龍 閱讀(759)
評論(0) 編輯 收藏 引用