GDI +问题-缩放/重新绘制 [英] GDI+ Question - Scaling/Redrawing

查看:94
本文介绍了GDI +问题-缩放/重新绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个自定义控件,允许我渲染图像.该图像应该是可伸缩的,这是通过使用上/下控件执行的.图像缩放比例很好,但是当缩放时,它会将原始图像及其重新缩放的版本留在屏幕上.我尝试了多种方法来摆脱原始(未缩放)的图像,但是没有任何效果.如何摆脱呢?

代码如下:

I''ve created a custom control that allows me to render an image. This image is supposed to be scalable, which is performed by using an up/down control. The image scales just fine, but when it does, it leaves the original image on the screen along with the rescaled version of it. I''ve tried a number of ways to get rid of the original (unscaled) image, but nothing has worked. How do I get rid of it?

Here''s the code:

using System;
//using System.Collections.Generic;
//using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
//using System.Data;
//using System.Linq;
//using System.Text;
using System.Windows.Forms;

namespace BitmapTest
{
	public partial class CPCanvas : UserControl
	{
		public Bitmap OriginalBitmap  { get; set; }
		public Bitmap CurrentBitmap   { get; set; }

		private bool m_moving             = false;
		private bool m_backgroundRendered = false;
		private Rectangle m_bmpRect;
		private int   m_moveOffsetX = 0;
		private int   m_moveOffsetY = 0;
		private Point m_bmpOrigin   = new Point(0,0);
		private float m_bmpScale    = 0f;
		private float m_bmpAngle    = 0f;
		
		//--------------------------------------------------------------------------------
		public CPCanvas()
		{
			CommonInit();
		}

		//--------------------------------------------------------------------------------
		public CPCanvas(Bitmap background, Bitmap weapon)
		{
			CommonInit();
			BackgroundImage = background;
			OriginalBitmap  = weapon;
			CloneOriginal();
			GetBitmapRectangle();
		}

		//--------------------------------------------------------------------------------
		public CPCanvas(Bitmap weapon)
		{
			CommonInit();
			m_backgroundRendered = true;
			OriginalBitmap       = weapon;
			CloneOriginal();
			GetBitmapRectangle();
		}

		//--------------------------------------------------------------------------------
		private void GetBitmapRectangle()
		{
			m_bmpRect = new Rectangle(m_bmpOrigin.X, 
									  m_bmpOrigin.Y, 
									  OriginalBitmap.Width, 
									  OriginalBitmap.Height);
		}

		//--------------------------------------------------------------------------------
		protected void CommonInit()
		{
			OriginalBitmap       = null;
			CurrentBitmap        = null;
			BackgroundImage      = null;
			m_bmpOrigin            = new Point(0,0);
			m_bmpScale             = 100f;
			m_bmpAngle             = 0f;
			m_backgroundRendered = false;

			InitializeComponent();
			SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
			Dock                  = DockStyle.Top | DockStyle.Left;
			BackgroundImageLayout = ImageLayout.Stretch;
		}

		//--------------------------------------------------------------------------------
		private void CloneOriginal()
		{
			CurrentBitmap = OriginalBitmap.Clone() as Bitmap;
		}

		//--------------------------------------------------------------------------------
		protected override void OnPaint(PaintEventArgs e)
		{
			RenderOverlay(e);
		}

		//--------------------------------------------------------------------------------
		private void RenderOverlay(PaintEventArgs e)
		{
			try
			{
				e.Graphics.DrawImage(CurrentBitmap, m_bmpOrigin);
			}
			catch (Exception ex)
			{
				if (ex != null) {}
			}
		}

		//--------------------------------------------------------------------------------
		protected override void OnPaintBackground(PaintEventArgs e)
		{
			if (!m_backgroundRendered)
			{
				base.OnPaintBackground(e);
			}
		}

		//--------------------------------------------------------------------------------
		protected override void OnMouseUp(MouseEventArgs e)
		{
			m_moving = false;
			base.OnMouseUp(e);
		}

		//--------------------------------------------------------------------------------
		protected override void OnMouseDown(MouseEventArgs e)
		{
			if (m_bmpRect.Contains(e.Location))
			{
				m_moveOffsetX = e.Location.X - m_bmpRect.X;
				m_moveOffsetY = e.Location.Y - m_bmpRect.Y;
				m_moving = (e.Button == System.Windows.Forms.MouseButtons.Left);
				m_moving = true;
				base.OnMouseDown(e);
			}
		}

		//--------------------------------------------------------------------------------
		protected override void OnMouseMove(MouseEventArgs e)
		{
			if (m_moving)
			{
				MoveImage(e.Location);
			}
			base.OnMouseMove(e);
		}

		//--------------------------------------------------------------------------------
		public void MoveImage(Point pt)
		{
			m_bmpOrigin.X = (pt.X - m_moveOffsetX);
			m_bmpOrigin.Y = (pt.Y - m_moveOffsetY);
			m_bmpRect.X = m_bmpOrigin.X;
			m_bmpRect.Y = m_bmpOrigin.Y;
			Refresh();
		}

		public void ScaleImage(float percent)
		{
			// this doesn't work
			//using (Graphics g = this.CreateGraphics())
			//{
			//    ColorMatrix matrix = new ColorMatrix();
			//    matrix.Matrix33 = 0f;
			//    using (ImageAttributes attributes = new ImageAttributes())
			//    {
			//        attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
			//        g.DrawImage(OriginalBitmap, m_bmpRect, 0, 0, OriginalBitmap.Width, OriginalBitmap.Height, GraphicsUnit.Pixel, attributes);
			//    }
			//}

			// if I don't do this, EVERY scaled version of the bitmap 
			// remains on the screen
			CurrentBitmap.Dispose();
			CurrentBitmap = null;
			CloneOriginal();

			this.m_bmpScale = percent * 0.01f;
			using (Graphics g = Graphics.FromImage(CurrentBitmap))
			{
			    g.ScaleTransform(m_bmpScale, m_bmpScale);
			    g.DrawImage(this.CurrentBitmap, 0,0);
			    m_bmpRect.Width  = this.CurrentBitmap.Width;
			    m_bmpRect.Height = this.CurrentBitmap.Height;
			}
			Refresh();
		}
	}
}

推荐答案

约翰,

我认为您不应该这样做.您从图片中创建一个Graphics对象,然后将图片重画到同一对象,这就是为什么您仍然看到旧"图片(它们仍在图形上)的原因.我会避免这样的问题:只需删除Scale Image的完整克隆和绘制部分,就像这样:

Hi John,

I think you shouldn''t do it like this. You create a Graphics object out of your picture and then redraw the picture to the same object, this is why you still see the "old" pictures (they are still on the graphics). I''d avoid the problem like this: just remove the complete cloning and drawing part of Scale Image like this:

public void ScaleImage(float percent)
 {
     this.m_bmpScale = percent * 0.01f;

     Refresh();
 }



并在绘制方法中在绘制之前进行缩放:



and in your draw method just scale before drawing:

private void RenderOverlay(PaintEventArgs e)
 {
     try
     {
         e.Graphics.ScaleTransform(m_bmpScale, m_bmpScale);
         e.Graphics.DrawImage(CurrentBitmap, m_bmpOrigin);
     }
     catch (Exception ex)
     {
         if (ex != null) { }
     }
 }



在移动图像时,您还有另一个问题,因为您没有考虑当前的比例尺.
我会像这样做整个事情:



You have another problem when moving the image because you don''t consider the current scale.
I''d do the whole thing like this:

using System;
using System.Windows.Forms;
using System.Drawing;

namespace Common.Controls
{
    public class PictureContainer : UserControl
    {
        bool bMoving;
        Point ptOffsetFromImagePosition; // used for moving

        public Image BackgroundImage { get; set; }
        public Image Picture { get; set; }
        public float PictureScale { get; set; }
        public Point PicturePosition { get; set; }

        public PictureContainer() : this(null, null) { }
        public PictureContainer(Image imagePicture) : this(imagePicture, null) { }
        public PictureContainer(Image imagePicture, Image imageBackground)
        {
            SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

            Picture = imagePicture;
            BackgroundImage = imageBackground;

            PictureScale = 1f; // set default scale
        }

        public Rectangle CurrentPictureRectangle
        {
            get
            {
                return Picture != null ?
                    new Rectangle(PicturePosition.X, PicturePosition.Y,
                        (int)(PictureScale * Picture.Width), (int)(PictureScale * Picture.Height)) :
                    new Rectangle();
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (Picture != null)
            {
                e.Graphics.ScaleTransform(PictureScale, PictureScale);
                e.Graphics.DrawImage(Picture, PicturePosition);
            }

            base.OnPaint(e);
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            if (BackgroundImage != null)
                e.Graphics.DrawImage(BackgroundImage, ClientRectangle);
            else
                base.OnPaintBackground(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left &&
                CurrentPictureRectangle.Contains(e.Location))
            {
                ptOffsetFromImagePosition = new Point(e.X - PicturePosition.X, e.Y - PicturePosition.Y);
                bMoving = true;
            }

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
                bMoving = false;

            base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (bMoving)
            {
                PicturePosition = new Point(e.X - ptOffsetFromImagePosition.X, e.Y - ptOffsetFromImagePosition.Y);
                Refresh();
            }

            base.OnMouseMove(e);
        }
    }
}


这篇关于GDI +问题-缩放/重新绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆