在对话框上应用带缩放功能的CScrollView

一.定义cscrollview派生类和document派生类

 声明:
DlgView.h:

//----------------------------------------------------------------------------------

class CCraftCxPreviewDlg;
class CDlgDocument : public CDocument
{
    friend class CCraftCxPreviewDlg;
protected:
    CDlgDocument();           // protected constructor used by dynamic creation
    DECLARE_DYNCREATE(CDlgDocument)

    // Attributes
public:

    // Operations
public:

    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CDlgDocument)
public:
    virtual void Serialize(CArchive& ar);   // overridden for document i/o
protected:
    virtual BOOL OnNewDocument();
    //}}AFX_VIRTUAL

    // Implementation
public:
    virtual ~CDlgDocument();
#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif

    // Generated message map functions
protected:
    //{{AFX_MSG(CDlgDocument)
    // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};


class CCraftCxPreviewDlg;
/////////////////////////////////////////////////////////////////////////////
// CDlgView view
class CDlgView : public CScrollView
{
    friend class CCraftCxPreviewDlg;
protected:
    CDlgView();           // protected constructor used by dynamic creation
    DECLARE_DYNCREATE(CDlgView)

    // Attributes
public:
    
    // Operations
public:

    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CDlgView)
protected:
    virtual void OnDraw(CDC* pDC);      // overridden to draw this view
    virtual void OnInitialUpdate();     // first time after construct
    //}}AFX_VIRTUAL

    // Implementation
protected:
    virtual ~CDlgView();
#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif

    // Generated message map functions
    //{{AFX_MSG(CDlgView)
    // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
public:
    afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message);
    afx_msg void OnDestroy();

    void OnZoomIn();
    void OnZoomOut();
    
protected:
    virtual void PostNcDestroy();

private:
    void InitDC(CDC *pDC);

    float m_zoomScale;
    CSize m_size;    
};

定义:

DlgView.cpp:
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDlgDocument

IMPLEMENT_DYNCREATE(CDlgDocument, CDocument)

CDlgDocument::CDlgDocument()
{
}

BOOL CDlgDocument::OnNewDocument()
{
    if (!CDocument::OnNewDocument())
        return FALSE;
    return TRUE;
}

CDlgDocument::~CDlgDocument()
{
}


BEGIN_MESSAGE_MAP(CDlgDocument, CDocument)
    //{{AFX_MSG_MAP(CDlgDocument)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDlgDocument diagnostics

#ifdef _DEBUG
void CDlgDocument::AssertValid() const
{
    CDocument::AssertValid();
}

void CDlgDocument::Dump(CDumpContext& dc) const
{
    CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDlgDocument serialization

void CDlgDocument::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {
        // TODO: add storing code here
    }
    else
    {
        // TODO: add loading code here
    }
}



/////////////////////////////////////////////////////////////////////////////
// CDlgView

IMPLEMENT_DYNCREATE(CDlgView, CScrollView)

CDlgView::CDlgView()
{
    m_zoomScale = 1.0;
    m_dbHorzScale = 1.0;
    m_dbVertScale = 1.0;
}

CDlgView::~CDlgView()
{
}


BEGIN_MESSAGE_MAP(CDlgView, CScrollView)
    //{{AFX_MSG_MAP(CDlgView)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //}}AFX_MSG_MAP
    ON_WM_MOUSEACTIVATE()
    ON_WM_DESTROY()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDlgView drawing

void CDlgView::OnInitialUpdate()
{
    CScrollView::OnInitialUpdate();
    CSize sizeTotal;
    sizeTotal.cx = sizeTotal.cy = 30;
    SetScrollSizes(MM_TEXT, sizeTotal);
    m_size =sizeTotal;//成员变量m_size保存视图的原始大小
}

void CDlgView::SetPreBitmap(Bitmap *PreBitmap, double dbVert, double dbHorz)
{
    m_Bitmap = PreBitmap;

    m_dbHorzScale = (dbVert > dbHorz) ? dbVert / dbHorz: 1;
    m_dbVertScale = (dbVert > dbHorz) ? 1 : dbHorz / dbVert;


}

void CDlgView::OnDraw(CDC* pDC)
{
    InitDC(pDC);//设置pDC为新的模式

    int nHeight = m_Bitmap->GetHeight();
    int nWidth = m_Bitmap->GetWidth();

    // 放大位图
    CDC dc;
    dc.CreateCompatibleDC(pDC);
    
    CBitmap bitmap;
    CBitmap* pOldBitmap;
    bitmap.CreateCompatibleBitmap(pDC, nWidth, nHeight);
    pOldBitmap = dc.SelectObject(&bitmap);

    Graphics g(dc.m_hDC);
    g.DrawImage(m_Bitmap, 0, 0);
    
    nWidth *= m_dbHorzScale;
    nHeight *= m_dbVertScale;
    pDC->StretchBlt(0, 0, nWidth, nHeight, &dc, 0, 0, nWidth, nHeight, SRCCOPY);

    dc.SelectObject(pOldBitmap);    

    CRect m_Rect;
    GetClientRect(&m_Rect);
    m_Rect.bottom += 100;
    CSize sizeTotal;

    sizeTotal.cx = nWidth * m_zoomScale;
    sizeTotal.cy = nHeight * m_zoomScale;
    SetScrollSizes(MM_TEXT, sizeTotal);

}

int CDlgView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
    return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
}

/////////////////////////////////////////////////////////////////////////////
// CDlgView diagnostics

#ifdef _DEBUG
void CDlgView::AssertValid() const
{
    CScrollView::AssertValid();
}

void CDlgView::Dump(CDumpContext& dc) const
{
    CScrollView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDlgView message handlers
//////////////////////////////////////////////////////////////////////////

void CDlgView::OnDestroy()
{
    CWnd::OnDestroy();
}

void CDlgView::PostNcDestroy()
{
    CWnd::PostNcDestroy();
}

void CDlgView::OnZoomIn()
{
    if (m_zoomScale > 31)
        return;

    CSize size = m_size;
    m_zoomScale++;//成员变量float m_zoom ;放大倍率加1
    size.cx *= m_zoomScale;
    size.cy *= m_zoomScale;
    size.cx += 2;
    size.cy += 2;//可能是计算误差的原因总是看不到最后几个象素
    this->SetScrollSizes(MM_TEXT, size); //设置放大后视图的大小
    this->Invalidate();//重画视图
}//一个菜单事件进行缩放倍率设置

void CDlgView::OnZoomOut()
{
    if (m_zoomScale == 1)
        return;
    
    CSize size = m_size;
    m_zoomScale--;//成员变量float m_zoom ;放大倍率加1
    size.cx *= m_zoomScale;
    size.cy *= m_zoomScale;
    size.cx += 2;
    size.cy += 2;//可能是计算误差的原因总是看不到最后几个象素
    this->SetScrollSizes(MM_TEXT, size); //设置放大后视图的大小
    this->Invalidate();//重画视图
}//一个菜单事件进行缩放倍率设置


void CDlgView::InitDC(CDC *pDC)
{
    
    CSize size(1000,1000);//定义原始图的大小,可以自己随意定
    //但不能太小,数字越大放大的精度就越高
    //举个例子,若数字为1,放大1.5倍,int(1*1.5)=1 等于没放大
    CSize newSize(1000 * m_zoomScale, 1000 * m_zoomScale);//放大后的图大小

    OnPrepareDC(pDC);//pDC设置为绑定逻辑视图
    CPoint point(0,0);//逻辑视图的0点
    pDC->LPtoDP(&point); //转化为设备坐标因为SetViewportOrg的参数需要设备坐标

    pDC->SetMapMode(MM_ANISOTROPIC);// 设置为单位可变模式
    pDC->SetViewportOrg(point);//视口原点为逻辑视图原点
    pDC->SetViewportExt(newSize); //原窗口1000单位 对应到缩放后的单位

    pDC->SetWindowOrg(0,0);
    pDC->SetWindowExt(size);//
}//对画图dc进行设置


二.调用

BOOL CCraftCxPreviewDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    CWnd *pWnd = this->GetDlgItem(IDC_STATIC_PRE_BMP);
    CRect RectTargetCtrl;
    pWnd->GetWindowRect(RectTargetCtrl);
    pWnd->DestroyWindow();
    this->ScreenToClient(RectTargetCtrl);

    CCreateContext pContext;
    CWnd* pFrameWnd = this;
    pContext.m_pCurrentDoc = new CDlgDocument;
    pContext.m_pNewViewClass = RUNTIME_CLASS(CDlgView);
    
    m_pZoomView =(CDlgView *) ((CFrameWnd*)pFrameWnd)->CreateView(&pContext);
    ASSERT(m_pZoomView);
    m_pZoomView->m_nMapMode = MM_TEXT;
    m_pZoomView->OnInitialUpdate();
    m_pZoomView->SetPreBitmap(m_pPreBitmap, m_dbDensityVert, m_dbDensityHorz);

    m_pZoomView->ShowWindow(SW_NORMAL);
    m_pZoomView->MoveWindow(RectTargetCtrl);

    return TRUE;  
}


void CCraftCxPreviewDlg::OnBnClickedButtonZoomout()
{
    m_pZoomView->OnZoomOut();
}

void CCraftCxPreviewDlg::OnBnClickedButtonZoomin()
{
    m_pZoomView->OnZoomIn();
}



原文地址:https://www.cnblogs.com/madlas/p/1383871.html