如何实现对PictureBox中的图象进行放大和缩小

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何实现对PictureBox中的图象进行放大和缩小相关的知识,希望对你有一定的参考价值。

图像没跟着变只有一个原因,SizeMode不为Zoom。

微软有提供现成的方法满足你的需要。你唯一需要知道的是一个Control的Position是相对于其父容器的边缘而言的,它叫ClientPoint坐标,并非屏幕坐标ScreenPoint。


下面是一个小方法,用来将任意Control的位置置于屏幕正中间。

     void SetCenterScreen(Control control)
        
            int screenWidth = Screen.PrimaryScreen.WorkingArea.Width;
            int screenHeight = Screen.PrimaryScreen.WorkingArea.Height;
            int targetLocationLeft;
            int targetLocationTop;
            targetLocationLeft = (screenWidth - control.Width) / 2;
            targetLocationTop = (screenHeight - control.Height) / 2;
            if (control.Parent != null)
                control.Location = control.Parent.PointToClient(new Point(targetLocationLeft, targetLocationTop));
            else
                control.Location = new Point(targetLocationLeft, targetLocationTop);
        

  

 关于缩放的问题。所有的Control都有Scale方法,接受一个SizeF作为比例因子。

  所以你的picturebox事件里应该这样写(每次放大到1.1倍):

  pictureBox1.SuspendLayout();
            pictureBox1.Scale(new SizeF  Width = 1.1f, Height = 1.1f );
            SetCenterScreen(pictureBox1);
            pictureBox1.ResumeLayout();


其中,SuspendLayout()是挂起布局引擎,这样会暂时阻止它进行外观和布局上的变更(但是会在自己的Graphics上偷偷画好),直到调用ResumeLayout()时才会一次性的迅速的显示出来。


此外,SizeMode只需要被设置一次,没有必要每次都赋值。


最后补一句,Zoom是“按比例缩放图片”,Strech才是“填满容器”,当然,如果picturebox大小比例和图像宽高比不一致,strech会让图片变形。

参考技术A Pegasus的ImagXpress 8.0控件,支持各种格式文件的加载。控件封装了右键局部区域放大的功能,要实现图片的缩放,把AutoResize属性设置为PegasusImaging.WinForms.ImagXpress8.AutoResizeType.CropImage,修改
ZoomFactor的值就可以了。
以下是简单的图片缩放

Public Class Form1

Dim MapWidth As Integer
Dim MapHeight As Integer

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'设置窗体自动添加滚动条
Me.AutoScroll = True
'设置图片框内的图片自动拉伸
PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
'加载位图
Dim MapImage As New Bitmap(Application.StartupPath & "\ch4.png", True)
'图片框加载图片
PictureBox1.Image = MapImage
'设置图片框大小
PictureBox1.Size = New Size(MapImage.Width, MapImage.Height)
'记录原始大小
MapWidth = MapImage.Width
MapHeight = MapImage.Height
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
PictureBox1.Width = PictureBox1.Width * 2
PictureBox1.Height = PictureBox1.Height * 2
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
PictureBox1.Width = PictureBox1.Width / 2
PictureBox1.Height = PictureBox1.Height / 2
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
PictureBox1.Width = MapWidth
PictureBox1.Height = MapHeight
End Sub
End Class

在放大和缩小时在imageview上移动对象

在imageview上有一个可拖动的对象,它已在android中设置为背景。当背景图像视图缩放时,我希望对象保持与之前相同的位置。例如,如果它位于该图像中的“微笑”文本之上,那么即使在缩放后它也应该保持在那里。

我希望图像像谷歌地图一样工作,当我们将标记添加到地图标记根据放大和缩小移动时。

答案

使用下面的Framlayout类,它将缩放其中的所有内容。

public class ZoomableLayout extends FrameLayout {

    public ZoomableLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }

    public ZoomableLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    public ZoomableLayout(final Context context) {
        super(context);
    }

    /**
     * Zooming view listener interface.
     *
     * @author karooolek
     *
     */
    public interface ZoomViewListener {

        void onZoomStarted(float zoom, float zoomx, float zoomy);

        void onZooming(float zoom, float zoomx, float zoomy);

        void onZoomEnded(float zoom, float zoomx, float zoomy);
    }

    // zooming
    float zoom = 1.0f;
    float maxZoom = 2.0f;
    float smoothZoom = 1.0f;
    float zoomX, zoomY;
    float smoothZoomX, smoothZoomY;
    private boolean scrolling; //

    // minimap variables
    private boolean showMinimap = false;
    private int miniMapColor = Color.WHITE;
    private int miniMapHeight = -1;
    private String miniMapCaption;
    private float miniMapCaptionSize = 10.0f;
    private int miniMapCaptionColor = Color.WHITE;

    // touching variables
    private long lastTapTime;
    private float touchStartX, touchStartY;
    private float touchLastX, touchLastY;
    private float startd;
    private boolean pinching;
    private float lastd;
    private float lastdx1, lastdy1;
    private float lastdx2, lastdy2;

    // drawing
    private final Matrix m = new Matrix();
    private final Paint p = new Paint();

    // listener
    ZoomViewListener listener;

    private Bitmap ch;

    public float getZoom() {
        return zoom;
    }

    public float getMaxZoom() {
        return maxZoom;
    }

    public void setMaxZoom(final float maxZoom) {
        if (maxZoom < 1.0f) {
            return;
        }

        this.maxZoom = maxZoom;
    }

    public void setMiniMapEnabled(final boolean showMiniMap) {
        this.showMinimap = showMiniMap;
    }

    public boolean isMiniMapEnabled() {
        return showMinimap;
    }

    public void setMiniMapHeight(final int miniMapHeight) {
        if (miniMapHeight < 0) {
            return;
        }
        this.miniMapHeight = miniMapHeight;
    }

    public int getMiniMapHeight() {
        return miniMapHeight;
    }

    public void setMiniMapColor(final int color) {
        miniMapColor = color;
    }

    public int getMiniMapColor() {
        return miniMapColor;
    }

    public String getMiniMapCaption() {
        return miniMapCaption;
    }

    public void setMiniMapCaption(final String miniMapCaption) {
        this.miniMapCaption = miniMapCaption;
    }

    public float getMiniMapCaptionSize() {
        return miniMapCaptionSize;
    }

    public void setMiniMapCaptionSize(final float size) {
        miniMapCaptionSize = size;
    }

    public int getMiniMapCaptionColor() {
        return miniMapCaptionColor;
    }

    public void setMiniMapCaptionColor(final int color) {
        miniMapCaptionColor = color;
    }

    public void zoomTo(final float zoom, final float x, final float y) {
        this.zoom = Math.min(zoom, maxZoom);
        zoomX = x;
        zoomY = y;
        smoothZoomTo(this.zoom, x, y);
    }

    public void smoothZoomTo(final float zoom, final float x, final float y) {
        smoothZoom = clamp(1.0f, zoom, maxZoom);
        smoothZoomX = x;
        smoothZoomY = y;
        if (listener != null) {
            listener.onZoomStarted(smoothZoom, x, y);
        }
    }

    public ZoomViewListener getListener() {
        return listener;
    }

    public void setListner(final ZoomViewListener listener) {
        this.listener = listener;
    }

    public float getZoomFocusX() {
        return zoomX * zoom;
    }

    public float getZoomFocusY() {
        return zoomY * zoom;
    }

    @Override
    public boolean dispatchTouchEvent(final MotionEvent ev) {
        // single touch
        if (ev.getPointerCount() == 1) {
            processSingleTouchEvent(ev);
        }

        // // double touch
        if (ev.getPointerCount() == 2) {
            processDoubleTouchEvent(ev);
        }

        // redraw
        getRootView().invalidate();
        invalidate();

        return true;
    }

    private void processSingleTouchEvent(final MotionEvent ev) {

        final float x = ev.getX();
        final float y = ev.getY();

        final float w = miniMapHeight * (float) getWidth() / getHeight();
        final float h = miniMapHeight;
        final boolean touchingMiniMap = x >= 10.0f && x <= 10.0f + w
                && y >= 10.0f && y <= 10.0f + h;

        if (showMinimap && smoothZoom > 1.0f && touchingMiniMap) {
            processSingleTouchOnMinimap(ev);
        } else {
            processSingleTouchOutsideMinimap(ev);
        }
    }

    private void processSingleTouchOnMinimap(final MotionEvent ev) {
        final float x = ev.getX();
        final float y = ev.getY();

        final float w = miniMapHeight * (float) getWidth() / getHeight();
        final float h = miniMapHeight;
        final float zx = (x - 10.0f) / w * getWidth();
        final float zy = (y - 10.0f) / h * getHeight();
        smoothZoomTo(smoothZoom, zx, zy);
    }

    private void processSingleTouchOutsideMinimap(final MotionEvent ev) {
        final float x = ev.getX();
        final float y = ev.getY();
        float lx = x - touchStartX;
        float ly = y - touchStartY;
        final float l = (float) Math.hypot(lx, ly);
        float dx = x - touchLastX;
        float dy = y - touchLastY;
        touchLastX = x;
        touchLastY = y;

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchStartX = x;
                touchStartY = y;
                touchLastX = x;
                touchLastY = y;
                dx = 0;
                dy = 0;
                lx = 0;
                ly = 0;
                scrolling = false;
                break;

            case MotionEvent.ACTION_MOVE:
                if (scrolling || (smoothZoom > 1.0f && l > 30.0f)) {
                    if (!scrolling) {
                        scrolling = true;
                        ev.setAction(MotionEvent.ACTION_CANCEL);
                        super.dispatchTouchEvent(ev);
                    }
                    smoothZoomX -= dx / zoom;
                    smoothZoomY -= dy / zoom;
                    return;
                }
                break;

            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_UP:

                // tap
                if (l < 30.0f) {
                    // check double tap
                    if (System.currentTimeMillis() - lastTapTime < 500) {
                        if (smoothZoom == 1.0f) {
                            smoothZoomTo(maxZoom, x, y);
                        } else {
                            smoothZoomTo(1.0f, getWidth() / 2.0f,
                                    getHeight() / 2.0f);
                        }
                        lastTapTime = 0;
                        ev.setAction(MotionEvent.ACTION_CANCEL);
                        super.dispatchTouchEvent(ev);
                        return;
                    }

                    lastTapTime = System.currentTimeMillis();

                    performClick();
                }
                break;

            default:
                break;
        }

        ev.setLocation(zoomX + (x - 0.5f * getWidth()) / zoom, zoomY
                + (y - 0.5f * getHeight()) / zoom);

        ev.getX();
        ev.getY();

        super.dispatchTouchEvent(ev);
    }

    private void processDoubleTouchEvent(final MotionEvent ev) {
        final float x1 = ev.getX(0);
   

以上是关于如何实现对PictureBox中的图象进行放大和缩小的主要内容,如果未能解决你的问题,请参考以下文章

winform 如何实现鼠标位置获取picturebox的焦点,然后焦点放大

使Print方法在Form_Load事件中起作用,如何对窗体的属性进行设置?

放大和缩小时Chrome中的表行高度和列表行高问题

react-native-maps :如何在放大和缩小时获取动态 latitudeDelta 和 longitudeDelta 值

C#怎么让画在picturebox中的图随鼠标滚轮放大缩小?

在放大和缩小时在imageview上移动对象