欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

滚轮根据鼠标位置缩放所绘制图形的功能

程序员文章站 2024-01-19 13:26:10
...

我们经常会看到一些平面设计软件例如AutoCAD等,在软件界面可利用鼠标进行图形的缩放功能,关键是它的缩放还根据鼠标位置的不同而实现不同的缩放功能。具体关键细节有如下情况:
1、滚轮滚动有两个方向,一般一个方向用于放大、另一个用于缩小,但具体哪个方向是放大哪个缩小,其实都无所谓,不同软件都不太一样。
2、一般鼠标停留的在哪个位置进行滚动滚轮时,给人的感觉是整个软件界面以鼠标点为中心进行缩放的,也就是图形或图像上鼠标的点不动,其余位置成比例放大缩小。不管鼠标是否落在图像内或在图像外均体现出该功能。
如果在网上搜索滚动功能的代码,经常出现很多长篇大论,有的用SDK,或底层API来写,这样显得太麻烦。又不好理解。笔者想借助VS2010开发环境,利用VC本身已有的一些功能简单地将其实现出来,这样读者易懂,代码拿去参考修改也方便。
下面我们就在MFC中开发一个滚轮根据鼠标位置缩放图形的程序:
(1)首先建立一个MFC的对话框程序,在对话框的头文件(*.h)里加入一些宏定义用于绘制矩形:

#define WIDTH 100         //矩形的宽(初始状态)
#define HEIGHT 200        //矩形的长(初始状态)
#define UP_SCALE 1.1      //放大的比例值
#define DOWN_SCALE 0.9    //缩小的比例值
#define POSITION_SCALE 0.1//位置偏移比例  

以上参数可以改变,但是参数 UP_SCALE、DOWN_SCALE、POSITION_SCALE 存在一定关系, 一般情况下需满足:
UP_SCALE - 1 = 1 - DOWN_SCALE ;
POSITION_SCALE = UP_SCALE - 1 或者:POSITION_SCALE = 1 - DOWN_SCALE

(2)然后在定义一些变量,这个放在头文件或cpp文件里都可以,这里将需要绘制的矩形定义成全局变量:

CPoint startPoint;  //矩形起始点坐标(左上角点)     
CPoint endPoint;    //矩形终点坐标 (右下角点)
CRect rc;           //绘制的矩形
double scale=1.0;   //矩形缩放比例,初始比例1.0

(3)在对话框源文件(*.cpp)中的OnInitDialog()函数里添加初始化代码:

tartPoint.x=10;      //初始化矩形的起始点坐标(左上角点)
startPoint.y=20;
endPoint.x=startPoint.x+WIDTH;//初始化矩形的终点坐标(右下角点)
endPoint.y=startPoint.y+HEIGHT;

(4)然后在绘图函数OnPaint()函数里加入如下代码用于绘制图形:

CPaintDC dc(this); // 用于绘制的设备上下文
rc.SetRect(startPoint.x,startPoint.y,endPoint.x,endPoint.y);//设置矩形的两个角点
dc.FillRect( rc, 0 ); // 画比例改变后的矩形
dc.FillSolidRect(&rc,RGB(255,0,0));//给矩形填充颜色(红色)

(5)在类向导中添加鼠标滚轮消息WM_MOUSEWHELL的消息响应函数:OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)。说明:这里的参数zDelta代表滚轮滚动的方向,>0为正方形、<0为负方向;而pt则表示鼠标的方向,不过这里不能用pt ,因为它不是鼠标在窗口中的坐标而是鼠标在整个显示器内的坐标。在该函数内添加如下代码:

    CPoint mousePoint;                      //定义当前鼠标的坐标点
    GetCursorPos(&mousePoint);              //获取当前鼠标在窗框中的坐标值
    ScreenToClient(&mousePoint);
    int dx = mousePoint.x-(rc.TopLeft()).x; //计算鼠标坐标点到矩形起始点X方向的向量
    int dy = mousePoint.y-(rc.TopLeft()).y; //计算鼠标坐标点到矩形起始点Y方向的向量

    //根据鼠标滚轮滚动方向判断缩放 与 滚动格数计算缩放比例 
    if(zDelta>0)                              
    {
        startPoint.x = rc.TopLeft().x-(int)(dx*POSITION_SCALE);//计算放大后的矩形起始点坐标
        startPoint.y = rc.TopLeft().y-(int)(dy*POSITION_SCALE);
        scale *= UP_SCALE;                  //计算每次放大的比例值
    }
    else
    {
        startPoint.x = rc.TopLeft().x+(int)(dx*POSITION_SCALE);//计算缩小后的矩形起始点坐标
        startPoint.y = rc.TopLeft().y+(int)(dy*POSITION_SCALE);
        scale *= DOWN_SCALE;                //计算每次缩小的比例值
    }
    endPoint.x = startPoint.x+(int)(WIDTH*scale);  //计算缩放后的矩形终点坐标
    endPoint.y = startPoint.y+(int)(HEIGHT*scale);
    Invalidate();   //重新绘制图形

    return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);

(6)在使用滚轮程序时如果担心窗口失去焦点,一般我们需要在WM_LBUTTONDOWN消息中的响应函数OnLButtonDown添加获取焦点功能,如下:

SetFocus();

当在窗口中点一下鼠标左键,焦点即回到窗口中,滚轮程序就有效了。