vc++ GDI+实现以鼠标为中心缩放图片(并且可以拖动)

    技术2022-07-11  86

    按以下步骤操作,即可实现。

    1. 首先创建一个基于对话框的MFC程序,然后把下面两个文件分别保存为.h文件和 .cpp文件

    //InitGdiplus.h #pragma once

    #include <GdiPlus.h> using namespace Gdiplus;

    class CInitGdiplus { public:     CInitGdiplus(void);     ~CInitGdiplus(void);

    private:     ULONG_PTR m_GdiplusToken;     GdiplusStartupInput gdiplusStartupInput; };  

    ---------------------------------------------------------------------------------------------------------------------

    //InitGdiplus.cpp #include "StdAfx.h" #include "InitGdiplus.h"

    CInitGdiplus::CInitGdiplus(void) {     GdiplusStartup(&m_GdiplusToken, &gdiplusStartupInput, NULL); }

    CInitGdiplus::~CInitGdiplus(void) {     GdiplusShutdown(m_GdiplusToken); }

     

    2. 然后在stdafx.h中包含上述头文件,在YourApp类中添加一个 CInitGdiplus m_InitGdiplus; 成员变量,完成GDI+的初始化;

    在有Dlg类中添加如下成员变量

     

    REAL m_zoom;  //缩放系数

    CRect m_Rect; //对话框的矩形区域

    REAL m_imgX; //图片左上角X轴偏移量 REAL m_imgY; //图片左上角Y轴偏移量

    PointF m_PtStart;    //按下鼠标左键,记录当前的m_imgX,m_imgY PointF m_mouseDown;  //按下鼠标左键时,鼠标在图片控件中的位置; bool m_mousepressed; //记录是否按下了鼠标左键

    3. 初始化成员变量:

    m_zoom = 1.0f;

    m_imgX = 0.0f; m_imgY = 0.0f; m_PtStart.X = 0.0f; m_PtStart.Y = 0.0f;

    m_mousepressed = false;  

    4. 在OnInitDialog()中添加

    GetClientRect(m_Rect); //在你的实际应用中,可能需要把这行添加到对话框的OnSize()中  

    5. 添加下面两个成员函数

    //双缓冲绘图 void CTestPic2Dlg::Invalidate() {              HDC hdc = ::GetDC(m_hWnd);         CDC dc;         dc.Attach(hdc);         CDC memDC;         CBitmap MemBitmap;         // 设备描述表初始化         memDC.CreateCompatibleDC(NULL);         // 建立与屏幕显示兼容的内存显示设备         MemBitmap.CreateCompatibleBitmap(&dc, m_Rect.Width(), m_Rect.Height());         // 选取空白位图         memDC.SelectObject(MemBitmap);         memDC.FillSolidRect(0, 0, m_Rect.Width(), m_Rect.Height(), RGB(255,255,255));         //画图         Draw(&memDC);         //拷贝到控件DC         dc.BitBlt(0, 0, m_Rect.Width(), m_Rect.Height(), &memDC, 0, 0, SRCCOPY);         MemBitmap.DeleteObject();         memDC.DeleteDC();         dc.Detach();         ::ReleaseDC(m_hWnd,hdc); }

    void CTestPic2Dlg::Draw(CDC *pDC) {     Image img(_T("003.jpg")); //注意,请设置你自己的图片     Graphics graph(pDC->GetSafeHdc());     graph.SetInterpolationMode(InterpolationModeHighQualityBilinear); //设置缩放质量     graph.ScaleTransform(m_zoom, m_zoom);                             //缩放     graph.DrawImage(&img, m_imgX, m_imgY);                            //m_imgX,m_imgY是原图应该偏移的量 }  

    6. 在OnPaint中添加Invalidate(); 完成初始化显示

    7. 分别给对话框添加下面四个消息响应

    WM_MOUSEMOVEWM_MOUSEWHEELWM_LBUTTONDOWNWM_LBUTTONUP

    8. 

    void CTestPic2Dlg::OnMouseMove(UINT nFlags, CPoint point) {     if(nFlags & MK_LBUTTON)     {         REAL deltaX = point.x - m_mouseDown.X; //x轴方向偏移         REAL deltaY = point.y - m_mouseDown.Y; //y轴方向偏移

            m_imgX =(m_PtStart.X + (deltaX/m_zoom)); //在原始图像中X坐标偏移,这里计算的是在原始图片中的位移,原因在上面已经说明,全局的仿射变换会影响实际的位移         m_imgY =(m_PtStart.Y + (deltaY/m_zoom)); //在原始图像中Y坐标偏移         Invalidate();                            //重绘     }     CDialogEx::OnMouseMove(nFlags, point); }

    BOOL CTestPic2Dlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) {     REAL oldzoom = m_zoom; //保存当前的缩放系数,用于计算当前滚动时的坐标     CPoint ppt = pt;     CRect rect;     if (zDelta == 120)     {         m_zoom += 0.4f;     }     if (zDelta == -120)     {         m_zoom = m_zoom - 0.4f;     }

        GetWindowRect(rect); //注意这里的区域是窗口相对于整个屏幕的,因为cpoint pt这个点是相对于屏幕的

        ppt.x -= rect.left; //计算该点在对话框中的位置     ppt.y -= rect.top;

        int x = ppt.x - m_Rect.left;     int y = ppt.y - m_Rect.top;

        REAL oldimagex = (x / oldzoom); //缩放前鼠标在原图中的位置     REAL oldimagey = (y / oldzoom);

        REAL newimagex = (x / m_zoom); //缩放后鼠标在原图中的位置     REAL newimagey = (y / m_zoom);

        m_imgX = newimagex - oldimagex + m_imgX; //计算原图应该的偏移     m_imgY = newimagey - oldimagey + m_imgY;

        Invalidate(); //绘图     return CDialogEx::OnMouseWheel(nFlags, zDelta, pt); }

    void CTestPic2Dlg::OnLButtonDown(UINT nFlags, CPoint point) {     if(nFlags & MK_LBUTTON)     {         if(!m_mousepressed)         {             m_mousepressed = true;             m_mouseDown.X = point.x;             m_mouseDown.Y = point.y;             m_PtStart.X = m_imgX;             m_PtStart.Y = m_imgY;         }              }

        CDialogEx::OnLButtonDown(nFlags, point); }

    void CTestPic2Dlg::OnLButtonUp(UINT nFlags, CPoint point) {     m_mousepressed = false;     CDialogEx::OnLButtonUp(nFlags, point); }  

    这样就实现了以鼠标为中心缩放图片

    Processed: 0.018, SQL: 9