信息產業部電子第二十二研究所青島分所 郎銳
一、 引言 當我們想仔細觀察某個細微的東西時,一般都會使用放大鏡。而要看清顯示在計算機屏幕上的圖片或文字時通常也 可以借助于Windows操作系統附帶的放大程序來實現。但該程序只能以固定的放大倍數去進行觀看,有時并不能滿足我們 的需要。本文就通過MFC基本類庫提供的StretchBlt函數來實現對屏幕圖象的局部放大,并且可以隨意放大、縮小,選取 到合適的放大倍數來對圖像的細節進行觀察。 二、 設計與實現 本程序主要用來對圖像的局部進行可調倍數的放大,應當具有以下主要功能: 1. 移動MOUSE放大顯示圖像的不同部位 2. 左擊增加放大倍率、右擊減少放大倍率。 從光學角度來看,對物體的放大成像是通過把較小的真實物體顯示成尺寸較大的虛像來實現的。因此我們可以用類 似的原理,把圖像中待放大的區間從較小的顯示范圍拉伸到一個比較大的顯示范圍即可達到圖像放大的效果,兩個區間 的比值也就是圖像的放大倍率。可以通過縮小源區間的范圍或擴大放大區間的范圍來實現放大倍率的調整。在MFC基本類 庫中提供有CDC類的StretchBlt函數可以將一幅位圖從一個源矩形以一定的光柵操作拷貝到另外一個不同大小的目標矩形 中去,因此可以用此函數來實現圖象放大的功能,其函數原形聲明如下: BOOL StretchBlt( int x, int y, //目標矩形的坐標原點 int nWidth, int nHeight, //目標矩形的長度和寬度 CDC* pSrcDC, //源設備環境句柄 int xSrc, int ySrc, //源矩形的坐標原點 int nSrcWidth, int nSrcHeight, //源矩形的長度和寬度 DWORD dwRop ); //光柵操作標志 當指定的源和目標矩形的寬度或高度不一樣時,StretchBlt函數將創建一個位圖的鏡像。如果是寬度有變化,就沿x軸 創建鏡像;如果是高度上有變化就沿y軸創建鏡像。而且該函數可以在內存中對源圖象做拉伸或壓縮處理后再拷貝到目標矩 形中去。 要放大圖像首先要把圖像顯示出來,一般可以從文件動態裝載或者直接從資源中用LoadBitMap讀取位圖資源。下面的代 碼放在視類的OnDraw函數中,用以在第一次調用時將位圖裝載并顯示出來,以后再被調用只是負責重畫: …… static bool load; if (!load) { BITMAP bm; load = !load; //裝載位圖到 m_pBitmap m_pBitmap->LoadBitmap(IDB_BITMAP1); //創建相關的設備環境 m_pdcMem->CreateCompatibleDC(pDC); //將位圖從m_ pBitmap中裝載到m_pdcMem中 m_pdcMem->SelectObject(m_pBitmap); m_pBitmap->GetObject(sizeof(bm),&bm); m_sizeSource.cx = bm.bmWidth; m_sizeSource.cy = bm.bmHeight; m_sizeDest = m_sizeSource; //把位圖從m_pdcMem中裝載到當前正在使用的設備環境中 pDC->StretchBlt(0,0,m_sizeSource.cx,m_sizeSource.cy,m_pdcMem,0,0,m_sizeSource.cx,m_sizeSource.cy,mana); } else { //重畫圖像 pDC->StretchBlt(0,0,m_sizeSource.cx,m_sizeSource.cy,m_pdcMem,0,0,m_sizeSource.cx,m_sizeSource.cy,mana); SetCursor(NULL);//隱藏鼠標 } 要實現前面提到的第一個功能:移動MOUSE放大顯示圖像的不同部位,顯然首先要在WM_MOUSEMOVE消息的響應函數里編寫 代碼。以整形變量s和d來分別表示所選取的源和目標區域的大小,再通過消息響應函數OnMouseMove的入口參數point來確定當 前的鼠標位置就可以計算出我們要選取的源和目標區域在圖像的位置。放大的工作只需通過StretchBlt函數將源區域中所在的 圖像拉伸到目標矩形那么大,并拷貝給目標區域即可實現所選區域的放大效果,下面是部分主要代碼: …… //確定目標區域、源區域的坐標位置 CRect srect,drect,mrect; srect.left = point.x - s; srect.top = point.y - s; srect.right = point.x + s; srect.bottom = point.y + s; drect.left = point.x - d; drect.top = point.y - d; drect.right = point.x + d; drect.bottom = point.y + d; mrect.left = oldx - d; mrect.top = oldy - d; mrect.right = oldx + d; mrect.bottom = oldy + d; dd = 2*d; //獲取可用設備環境句柄 CDC * pDC = GetDC(); OnPrepareDC(pDC); if (recover) { pDC->BitBlt(mrect.left,mrect.top,dd,dd,m_pdcMem,mrect.left,mrect.top,mana); } //隱藏鼠標 SetCursor(NULL); //拉伸放大 pDC->StretchBlt(drect.left,drect.top,drect.Width(),drect.Height(),m_pdcMem,srect.left,srect.top,srect.Width(),srect.Height(),SRCCOPY); //保存當前鼠標位置備用 oldx = point.x; oldy = point.y; //釋放設備環境句柄 ReleaseDC(pDC); recover = true; …… 為了實現第二個功能:左擊增加放大倍率、右擊減少放大倍率,可以分別在消息WM_LBUTTONDOWN和消息WM_RBUTTONDOWN中添加改 變選取區域大小的代碼來實現。如果選取源矩形不變而改變目標矩形的大小會隨著放大倍數的增大,顯示區域也不斷增大,當放大到 一定程度的時候會另人無法忍受,因此選取通過縮放源矩形大小來控制放大倍數的方案: void CZoomInView::OnRButtonDown(UINT nFlags, CPoint point) { if (s < 60) { SetCursor(NULL); s+=3; OnMouseMove(nFlags, point); } CView::OnRButtonDown(nFlags, point); } …… void CZoomInView::OnLButtonDown(UINT nFlags, CPoint point) { if(s>5) { s-=3; SetCursor(NULL); OnMouseMove(nFlags, point); } CView::OnLButtonDown(nFlags, point); } 小結:本文通過對MFC庫函數StretchBlt的使用來實現了對圖像位圖的局部細節的放大功能。本程序只是通過了一個簡單的例子做了講 解,重點放在StretchBlt函數的應用上,功能上也只實現了對本程序客戶區圖象的放大,如要對屏幕上其他程序和桌面進行放大則還需 要引入系統鉤子(HOOK)的技術來實現,并且需要把處理代碼放到動態連接庫中才可以實現全局鉤子。本程序在Windows 98下,以 Microsoft Visual C++ 6.0編譯通過。
|