Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# GDI+ WinForm
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();
		}
	}
}
Posted 8-Oct-11 12:18pm
Edited 8-Oct-11 12:24pm
v2

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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);
        }
    }
}
  Permalink  
v2
Comments
   
I implemented your code, and while it solved the immediate problem, I'm still having issues which I think call for a separate question. I just can't get my head around this GDI stuff...
johannesnestler at 10-Oct-11 9:56am
   
Hi John, I'm glad it solved "this" problem. What other problems do you have?
   
I have them mostly resolved now. I've moved on to other parts of the code, but will probably revisit the remaining image weirdness in the future.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 475
1 Maciej Los 339
2 Richard MacCutchan 225
3 BillWoodruff 219
4 Suraj Sahoo | Coding Passion 155
0 OriginalGriff 8,759
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,639
3 Maciej Los 5,269
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web01 | 2.8.1411028.1 | Last Updated 8 Oct 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100