MFC中顯示圖像的放大、縮小、移動功能


StretchBlt函數直接對圖片進行放大,縮小,顯示位置變換。
這個函數有兩種形態一種全局函數是這樣的: 
BOOL StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop);

一種是CDC的成員函數是這樣的:

BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop );

在實現時有兩點要注意

  1. 顯示模式,使用SetStretchBltMode來控制像素在拉伸,縮小時的像素運算。在拉伸位圖時一般不需要修改,在壓縮位圖顯示時,默認值會出現顏色失真,這時可以使用HALFTONE模式。
  2. 在StrectchBlt中xSrc,ySrc為拷貝設備的邏輯坐標,在拷貝位圖后在邊緣是有一個邏輯單位的空白的,這點在放大圖片對xSrc,ySrc進行設置容易被忽略。

目的描述

  1. 顯示位圖,鼠標點擊圖片,以所點擊圖片的位置為中心按照一定比例系數對圖片顯示進行放大縮小操作。
  2. 移動位圖顯示窗口,按下鼠標右鍵可以拖動位圖的顯示位置,對位圖的顯示區進行移動操作。

思路

  通過WM_LBUTTONDOWN或WM_LBUTTONCLICK來獲取鼠標的動作的坐標,通常是CClientDC的邏輯坐標,如果是采用文檔模式則一般CClientDC和顯示窗口是一致的。如果采用PictureControl在窗口應用程序當中顯示時,可以先獲得PictureControl區域的屏幕坐標再轉換成CClientDC的坐標。經過PicturenControl左上角坐標的計算,就可以得到鼠標點擊位置在PictureControl區域中的邏輯坐標。再通過該坐標計算出在原設備區中的邏輯坐標,通過該邏輯坐標就可以計算出鼠標所在點在位圖上的坐標。知道該位圖上坐標后,就可以對原設備區進行拉伸,縮小,移動的操作了。

實現

放大,縮小

CStatic m_sPreview;//PictureControl 控件
CPoint m_CurClientPoint;//當前鼠標位置所在客戶區的邏輯坐標
int m_iMultiple;//圖像縮放顯示倍數
enum PreviewType{enlarge,narrow,restore,move};
PreviewType m_nPrevewType;//命令模式
CPoint m_OriginSrcPoint;//顯示圖像右上角坐標
unsigned int iWidth,iHeight;//iWidth與iHeight是圖片的橫縱像素的數目
...
ClientToPictureControl(&m_sPreview,&m_CurClientPoint); PictureControlToBmp(m_nWidthDest,m_nHeightDest,m_nWidthSrc,m_nHeightSrc,&m_OriginSrcPoint,&m_CurClientPoint); m_nWidthSrc=iWidth/m_iMultiple; m_nHeightSrc=iHeight/m_iMultiple; Mutiply(m_nPreviewType,&m_OriginSrcPoint,&m_CurClientPoint,m_nWidthSrc,m_nHeightSrc); m_nYOriginSrc=m_OriginSrcPoint.y;//
m_nXOriginSrc=m_OriginSrcPoint.x;//
函數ClientToPictureControl功能為得到該點再控件坐標系的。
void ClientToPictureControl(CStatic *picControl,CPoint *point)//得到picControl在客戶區的邏輯位置
{
    CWnd *pWnd;
    pWnd=picControl;
    CRect tmp;
    pWnd->GetWindowRect(&tmp);//控件窗口位置
    ScreenToClient(&tmp);
    *point = *point - tmp.TopLeft();
}
函數PictureControlToBmp功能是為得到鼠標位置在圖像坐標系下的像素坐標 
void PictureControlToBmp(int nWidthDest,int nHeightDest,int nWidthSrc,int nHeightSrc,
CPoint *Origin,CPoint *point)
{
  point->x = point->x * nWidthSrc / nWidthDest+ Origin->x;
  point->y= point->y * nHeightSrc / nHeightDest+ Origin->y;
}
函數Mutiply//是調整顯示右上角坐標的。
void Mutiply(PreviewType type,CPoint *Origin,CPoint *point, int width,int height)
{
    switch (type)
    {
    case CAlphaDlg::enlarge:
        if(point->x-width/2>0)
        {
            if(m_pMyDevice->m_sFrInfo.iWidth > point->x+width/2){
                Origin->x=point->x-width/2;}
            else{
                Origin->x=m_pMyDevice->m_sFrInfo.iWidth-width;
            }
        }
        else
        {
            Origin->x=0;
        }
        if(point->y-height/2>0)
        {
            if(m_pMyDevice->m_sFrInfo.iHeight> point->y+height/2){
                Origin->y=point->y-height/2;}
            else{
                Origin->y=m_pMyDevice->m_sFrInfo.iHeight-height;
            }
        }
        else
        {
            Origin->y=0;
        }
        break;
    case CAlphaDlg::narrow:
        if(point->x-width/2>0)
        {
            if(m_pMyDevice->m_sFrInfo.iWidth > point->x+width/2){
                Origin->x=point->x-width/2;}
            else{
                Origin->x=m_pMyDevice->m_sFrInfo.iWidth-width;
            }
        }
        else
        {
            Origin->x=0;
        }
        if(point->y-height/2>0)
        {
            if(m_pMyDevice->m_sFrInfo.iHeight> point->y+height/2){
                Origin->y=point->y-height/2;}
            else{
                Origin->y=m_pMyDevice->m_sFrInfo.iHeight-height;
            }
        }
        else
        {
            Origin->y=0;
        }
        break;
    case CAlphaDlg::restore:
        Origin->x=0;
        Origin->y=0;
        break;
    case CAlphaDlg::move:        
        break;
    default:
        break;
    }
}

以上,是圖像放大縮小的步驟。

如果移動圖像和上面類似,直接響應WM_MOUSEMOVE消息

void OnMouseMove(UINT nFlags, CPoint point)
{
    if(m_bTool==TRUE&&m_nPreviewType==move)
    {SetCursor(LoadCursor(NULL,IDC_SIZEALL));   
        CRect rect;
switch (nFlags)
        {
        case MK_LBUTTON:
            if(m_CurClientPoint!=point)
            {
                if(m_nXOriginSrc+(-point.x+m_CurClientPoint.x)/m_iMultiple>0)
                {
                    if(m_nXOriginSrc+(-point.x+m_CurClientPoint.x)/m_iMultiple + m_nWidthSrc< m_pMyDevice->m_sFrInfo.iWidth)
                    m_nXOriginSrc=m_nXOriginSrc+(-point.x+m_CurClientPoint.x)/m_iMultiple;    
                }
                else
                {
                    m_nXOriginSrc=0;
                }
                if(m_nYOriginSrc+(-point.y+m_CurClientPoint.y)/m_iMultiple>0)
                {
                    if(m_nYOriginSrc+(-point.y+m_CurClientPoint.y)/m_iMultiple + m_nHeightSrc< m_pMyDevice->m_sFrInfo.iHeight)
                    m_nYOriginSrc=m_nYOriginSrc+(-point.y+m_CurClientPoint.y)/m_iMultiple;    
                }
                else
                {
                    m_nYOriginSrc=0;
                }
                m_CurClientPoint = point ;
            }            
            m_sPreview.GetClientRect(&rect);
            InvalidateRect(rect,1);
            break;
        default:
            break;
        }
    }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM