MFC+GDI简化坐标缩放

MFC实现鼠标中键滑动WM_MOUSEWHEEL响应,使得图形缩放 MFC实现鼠标中键滑动WM_MOUSEWHEEL响应,使得图形缩放 已经实现,没有问题 CRenderView基类是CView,实现显示操作三维模型。 实现鼠标滚轮缩放简单步骤如下: (1)响应视图类的WM_MOUSEWHEEL消息 (2)在响应函数里面实现:       有滚动引起的缩放比例变化;       刷新视图区域,图形缩放显示;      设置滑竿位置,刷新滑竿所在类的 阅读详情

0.背景

0.1问题的由来

视图里画图经常会有负坐标或者很大数值的坐标(地图),在处理的时候需要清楚DC的各种视口的意义,看了几天,头脑越看越混,视口啊,坐标零点啊什么的,一团乱麻,索性按照自己的想法来个简单的解决方案。

0.2几个概念

几个概念在下面几张图里表述
这是调整前的逻辑关系图,有负坐标,有超出客户区的坐标。
调整后
这是调整后的逻辑关系图,经过坐标平移和缩放,在客户区可以完整的显示整个图形。

0.3图形的数据

数据的excel图
这是本例使用的数据在excel里画出来的图形。数据文件在这里可以下载。

0.4默认的结果

默认的结果
这是默认的不处理的结果,只有正值。

1.思路

1.1读取数据

读取所有坐标,存入CArray里去。

    CStdioFile sfile;
    CString s,sx,sy;
    CPoint pt;

    nXmin = 0;
    nYmin = 0;
    nXmax = 0;
    nYmax = 0;
    nXW = 0;
    nYH = 0;

    sfile.Open(_T("testdata.txt"),CFile::modeRead);
    while(sfile.ReadString(s))
    {
        AfxExtractSubString(sx,s,0,'\t');
        AfxExtractSubString(sy,s,1,'\t');
        pt.x = _wtoi(sx);
        pt.y = _wtoi(sy);
        m_PTArray.Add(pt);
        if (pt.x > nXmax)
        {
            nXmax = pt.x;
        }
        if (pt.x< nXmin)
        {
            nXmin = pt.x;
        }
        if (pt.y > nYmax)
        {
            nYmax = pt.y;
        }
        if (pt.y < nYmin)
        {
            nYmin = pt.y;
        }
    }
    nXW = nXmax - nXmin;
    nYH = nYmax - nYmin;

1.2缩放

根据图形的范围和客户区的范围xy的比例确定缩放比例,所有坐标按这个比例缩小。

    CRect rc;
    GetClientRect(&rc);
    if ((double)nXW / (double)rc.Width() > (double)nYH / (double)rc.Height())
    {
        dRatio = (double)rc.Width() / (double)nXW ;
    }
    else
    {
        dRatio = (double)rc.Height() / (double)nYH ;

    }

1.3平移

先把所有负坐标变为正,方法是所有坐标减去最小的负坐标。同时求得图形范围。

    for (int i=0;i<m_PTArray.GetSize();i++)
    {
        m_PTArray.GetAt(i).x += -nXmin; 
        m_PTArray.GetAt(i).x *= dRatio;
        m_PTArray.GetAt(i).y += -nYmin; 
        m_PTArray.GetAt(i).y *= dRatio;

    }

1.4留出空白

所有坐标加上空白的宽度数值就可以。

2.工程设置及其他代码

2.1设置

1.MFC单文档工程
2.视图从ScrollView派生

2.2双缓冲绘图

定义

    CDC* m_pMemoryDC; 
    CBitmap * m_pBitmap; 

视图类构造函数里初始化

    m_pMemoryDC = new CDC();  
    m_pBitmap = new CBitmap();  

视图类析构函数里析构

    delete m_pBitmap;  
    delete m_pMemoryDC; 

响应视图类的OnPaint消息

    CDC* pDC = GetDC();
        CPoint m_ScrolPt = GetScrollPosition();
        CRect rc;
        GetClientRect(&rc);
        m_pMemoryDC->CreateCompatibleDC(pDC); 
        m_pBitmap->CreateCompatibleBitmap(m_pMemoryDC,rc.Width(),rc.Height());
        CBitmap * pOldbmp = m_pMemoryDC->SelectObject(m_pBitmap); 

        m_pMemoryDC->PatBlt(0,0,rc.right, rc.bottom,WHITENESS);//white background


        m_pMemoryDC->MoveTo((m_PTArray.GetAt(0).x - m_ScrolPt.x) * m_dScale,
            (m_PTArray.GetAt(0).y - m_ScrolPt.y) * m_dScale);
        for (int i=1;i<m_PTArray.GetSize();i++)
        {
            m_pMemoryDC->LineTo((m_PTArray.GetAt(i).x - m_ScrolPt.x) * m_dScale,
                (m_PTArray.GetAt(i).y - m_ScrolPt.y) * m_dScale);
        }


        pDC->BitBlt(0, 0, rc.right, rc.bottom, m_pMemoryDC, 0, 0, SRCCOPY);   
        m_pMemoryDC->SelectObject(pOldbmp);   
        m_pBitmap->DeleteObject();  
        m_pMemoryDC->DeleteDC(); 

2.3设置滚动条

    SetScrollSizes(MM_TEXT, CSize(nXW * m_dScale * dRatio,nYH * m_dScale * dRatio));

2.4鼠标中键滚动缩放

定义缩放比尺

double m_dScale ;

初始化为1.0。
响应视图类的

    BOOL CCoordinateView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    // TODO: Add your message handler code here and/or call default
    m_dScale += 0.05 * zDelta/ 120;
    if(m_dScale <= 0.02)  
    {   
        m_dScale = 0.02;            
    }         
    if(m_dScale >= 4.0)  
    {
        m_dScale = 4.0; 
    }
    SetScrollSizes(MM_TEXT, CSize(nXW * m_dScale * dRatio,nYH * m_dScale * dRatio));
    Invalidate();
    return TRUE;/*CScrollView::OnMouseWheel(nFlags, zDelta, pt)*/;
}

3.结果

结果1
无缩放情况
结果2
缩放的情况

4.继续改进

GDI里画图的坐标只能是int型,但在很多图像里画的都是float型,解决方法就是使用Direct2D。后续结合2者进行程序设计。

MFC实现自动适配win窗口缩放比例(附完整源码) 阅读详情

相关推荐

VC6 MFC工程:纯GDI实现五角星绘制与坐标映射演示

一个可在Visual C++ 6.0中直接打开编译运行的MFC图形示例工程,不依赖第三方库,完全基于Windows GDI完成五角星绘制。程序采用标准文档/视图结构,核心绘图逻辑封装在WJXView.cpp中,通过极坐标计算五个顶点位置,再结合CDC::SetMapMode和逻辑坐标映射,将数学坐标准确转换为客户区屏幕坐标,最后用MoveTo/LineTo连线成形。支持窗口缩放、重绘自动刷新,适配不同DPI下的显示一致性。工程包含完整资源文件(图标、位图、RC脚本)、头文件、实现代码及调试中间产物,结构清晰

stem5的博客 225

[MFC]OnMouseMove移动位置和OnMouseWheel缩放实现

OnMouseMove响应鼠标移动 实现原理是:相对静止---鼠标和对象相对位置不变,鼠标的偏移量,就是我们对象的偏移量 OnMouseWheel响应鼠标中键的滚动 实现原理是:相对移动---鼠标和所在对象点位置不变,鼠标所在对象点的周围 长和宽 成比例的缩放

春夜喜雨的专栏 2万+

使用GDI+实现MFC单文档图像视图的旋转和缩放

在重写OnDraw函数后,程序员可以根据需要绘制出各种自定义的图形和数据表示。这通常包括以下几个步骤:获取绘图上下文:OnDraw函数的参数CDC指针提供了绘图的上下文环境。定义绘图区域:通过CDC的函数设置绘图参数,如笔的颜色、填充色、字体、布局等。执行绘制操作:使用CDC提供的函数如MoveToLineToDrawTextEllipse等进行实际的绘制。处理绘图逻辑:根据应用的需求,实现数据的读取、计算、图形和文本的组织、绘制的调度等逻辑。

weixin_29935511的博客 974

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

原文点击打开链接 在开始之前我们先了解一下GDI+中的坐标系统: 世界坐标(World Coordinate) 是用来制作特定绘图自然模型的坐标。 页面坐标(Page Coordinate) 则是指绘图接口(例如窗体或控件) 使用的坐标系统。 设备坐标(Device Coordinate) 是在其上进行绘图的实体装置(例如屏幕或纸张) 所使用的坐标。 “世界变换”会将世界坐标转换为页面坐

Hyman的博客 1万+

MFC图片缩放实战:GDI+插值、双缓冲与坐标换算全解析

图片缩放是图像处理与界面开发中的基础操作,其核心在于平衡缩放质量、渲染性能与交互流畅度。在Windows平台,MFC框架下常用GDI+或StretchBlt实现,前者提供多种插值模式(如HighQualityBicubic),可显著改善放大后的边缘锯齿;后者速度快但画质有限。实际工程中还需引入双缓冲技术避免连续重绘引发的闪烁,并维护精确的坐标换算关系(客户区坐标=图片坐标×缩放比例+偏移量),以支持鼠标滚轮缩放、框选放大等交互。该技术广泛应用于图像标注工具、照片查看器以及工业检测界面。本文结合MFC实战,详

weixin_42554151的博客 340

MFC图片缩放实战:从GDI到GDI+与双缓冲优化

图像缩放是计算机图形学中的基础操作,其核心在于插值算法与坐标映射。通过双线性或双三次插值,可在放大时平滑边缘、缩小时减少失真,从而提升视觉质量。在MFC框架下,结合GDI+的高质量重采样与双缓冲绘制技术,能有效消除闪烁并优化性能。这些技术广泛应用于图像查看器、预览工具等场景。本文深入探讨MFC图片缩放的关键技术,涵盖GDI StretchBlt、GDI+插值模式及手动重采样,并分享滚轮交互与内存管理的工程实践,助你解决缩放模糊与卡顿问题。

weixin_33910191的博客 225

项目【MFC】(四)——鼠标滚轮缩放图像

初始状态: 放大后: 功能: 鼠标需放在图片控件窗口,然后通过滚轮实现图片缩放,并实时显示当前分辨率和缩放倍数。 实现: 1、首先需要判断,鼠标是否停留在图片窗口,若是则响应滚轮事件;否则不响应。 2、判断是缩小,还是放大。 3、缩放时按一定步长缩放,步长可为:0.01,0.02.....等等。 4、显示更新分辨率、缩放倍数。 选中控件右击——>选择【类向导】——》【消息选择】->【滚轮】。如下: 然后跳转至消息代码,添加程序: //...

小武的博客 9280

MFC图片缩放实战:GDI+双缓冲与滚轮锚点缩放

图像缩放是图形编程中的基础操作,其核心在于坐标变换与插值算法。通过双缓冲技术可消除重绘闪烁,而GDI+提供的高质量插值模式能显著提升缩放画质。在MFC框架下,结合鼠标滚轮消息与锚点计算,可实现以光标为中心的平滑缩放体验。这些技术广泛应用于图片查看器、地图浏览等场景。本文深入探讨MFC图片缩放的关键实现,涵盖双缓冲、GDI+插值及滚轮锚点缩放等热词技术,助你打造流畅的图片查看功能。

weixin_42536058的博客 263

MFC 鼠标选定显示范围,图片放大缩小,带左右滚动条显示

MFC中图片缩放,随意使用鼠标画一个方形框,立刻放大显示选择框内的内容,左右2侧滚动条可以随意拖动整体放大后的图像。项目使用vs2013编译。Debug 目录下有demo exe 。

MFC图片缩放实战:GDI与GDI+选型、双缓冲及避坑指南

图像缩放是计算机图形学中的基础操作,其核心在于插值算法与坐标映射。在Windows平台,GDI的StretchBlt和GDI+的DrawImage是两种常用技术,前者依赖SetStretchBltMode设置采样模式,后者通过InterpolationMode控制画质。合理选择插值模式(如HALFTONE或HighQualityBicubic)能显著提升图像质量,而双缓冲技术可有效避免闪烁。这些技术在工控、医疗等领域的MFC老项目维护中尤为重要,尤其是处理大图预览、滚轮交互和内存管理时。本文深入探讨了MFC

weixin_29191081的博客 224

MFC图片缩放实战:GDI/GDI+插值、双缓冲与性能调优

图像缩放是桌面应用开发中的高频需求,其核心在于缩放算法对画质、性能与交互体验的平衡。在MFC框架下,开发者通常面对GDI与GDI+两条技术路径:GDI的StretchBlt以位图块拷贝方式工作,性能开销低但放大画质有限;GDI+的DrawImage则通过插值模式重建像素,细节表现更好但耗时更高。理解两种方案的原理与性能边界,有助于按场景选择合适策略。实际工程中,还需结合CImage简化位图管理,利用双缓冲消除闪烁,并通过动态切换插值模式兼顾流畅度与清晰度。针对放大模糊、内存句柄泄漏、坐标偏移等典型问题,本文

weixin_27066963的博客 152

MFC鼠标中键拖动、同时滚轮缩放(根据鼠标位置)绘制的图形

1、VS2010开发的MFC对话框程序; 2、可利用中键拖动绘制的图形; 3、滚轮根据当前鼠标的位置缩放绘制的图形; 4、与AutoCAD及其他平面设计软件的鼠标功能相同。 5、可作为具有类似应用开发的模板、关键代码均提供详细的注释。

MFC中滚轮根据鼠标位置缩放绘制的图形

利用VS2010,基于MFC的对话框程序; 可根据鼠标位置滚动鼠标滚轮时自动调节图形位置且成比例缩放所绘制的图形; 类似AutoCAD等平面设计软件中滚轮的功能; 提供所有源代码,且每行程序注释得清清楚楚,可作为有类似需求开发的很好模板。

MFC中的GDI绘图

一.关于GDI的基本概念什么是GDI         Windows绘图的实质就是利用Windows提供的图形设备接口GDI(Graphics Device Interface)将图形绘制在显示器上。    在Windows操作系统中,动态链接库C:/WINDOWS/system32/gdi32.dll(GDI Client DLL)中定义了GDI函数,实现与设备无关的包括屏幕上输出像素、在打印机上输出硬拷贝以及绘制Windows用户界面功能。在Visual C++6.0中的头文件C:/Program Fi

RNAMatrix的专栏 4118

MFC实现图形放大缩小

通过对MFC库函数StretchBlt的使用来实现了对图像位图的局部细节的放大功能

GDI+绘制矩形,并且实现可旋转、缩放、移动功能(基于MFC对话框)

绘制矩形并且能够交互实现缩放、旋转、移动。里面还有绘制椭圆、箭头等功能,只是其他交互功能还未完善待续。。。。

37_MFC自绘UI你离不开GDI绘图

GDI (Graphics Device Interface)是图形设备接口的英文缩写,处理Windows程序的图形和图像输出。程序员不需要关心硬件设备及设备驱动,就可以将应用程序的输出转换为硬件设备上的输出,实现应用程序与硬件设备的隔离,大大简化程序开发工作。在Windows操作系统中,图形界面应用程序通常离不开GDI,利用GDI所提供的众多函数可以方便地在屏幕、打印机以及其他输出设备上实现输出文本、图形等操作。

成长需要沉淀。 1855

VisionPro九点标定实战:从相机拍照到机器人精准抓取的完整流程

本文详细介绍了VisionPro九点标定技术在工业自动化中的应用,从相机拍照到机器人精准抓取的完整流程。通过硬件配置、标定步骤和实战技巧的解析,帮助工程师实现高精度视觉引导系统,提升生产效率。特别适合需要解决二维图像坐标与物理空间转换问题的自动化项目。

weixin_30664051的博客 406
上一篇: CMFCToolTipCtrl 应用详解
下一篇: JS操作sqlite数据库
洗洗睡去
博客等级 码龄19年 277粉丝 90原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值