Time Tick consumes 100% CPU

U

utkarsh

Hi,

I am using the following code to the update a section of the image
which is drawn on a panel.


this.m_Timer = new System.Windows.Forms.Timer(this.components);
this.m_Timer.Tick += new System.EventHandler(this.m_Timer_Tick);
this.m_Timer.Enalbled = true;

private void m_Timer_Tick(object sender, System.EventArgs e)
{
RepaintMagnifier();
}

private void RepaintMagnifier()
{
Graphics g = this.pnlBody.CreateGraphics();
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode =
System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

if(img != null)
g.DrawImage(img, new Rectangle(0, 0, this.pnlBody.Width,
this.pnlBody.Height), new
Rectangle(iXpos,iYpos,(int)(this.pnlBody.Width*((float)this.iZoomFactor/100)),(int)(this.pnlBody.Height*((float)this.iZoomFactor/100))),
GraphicsUnit.Pixel);
}

The image file size is around 0.5 MB which is being drawn on the panel
control.

Above code is taking 100% CPU cycle.

I am using the above approach for repainting the screen to avoid the
flickering.

It there any other way to perform this action or should i use the a
secondary thread instead of timer to repaint the screen.


Thanks,
Utkarsh
 
G

Guest

Hi utkarsh,
if you want to avoid flickering and you are using a panel to display an
image I would override the OnPaintBackground method to do nothing - to reduce
flickering caused by painting the background, then override the OnPaint
method to paint a bitmap image you have stored internally in the panel, on
the paint method don't do anything apart from painting. you would then have
another method you woud call to update the image properties outside of the on
paint method. Something like:


private Image _bufferedImage;
private int _x = 0;
private int _y = 0;
private float _scaleFactor = 1.0f;

//You call this explicitly to update the buffered image
public void ReDraw()
{
//assume there is another method like LoadImage which will
load
//an image into the _bufferedImage member variable


Graphics g = Graphics.FromImage(_bufferedImage);

GraphicsContainer gcOrig = g.BeginContainer();

//do some processing, i.e. change x and y and scale
//of the image
g.TranslateTransform(_x, _y);
g.ScaleTransform(_scaleFactor, _scaleFactor);


g.DrawImage(_image,5,5);

g.EndContainer(gcOrig);
this.Refresh();
}

protected override void OnPaint(PaintEventArgs e)
{
//simply paint your buffered image to the control - do not
do any
//processing
if(_bufferedImage != null)
{
e.Graphics.DrawImage(_bufferedImage, 0 ,0);
}
}

protected override void OnPaintBackground(PaintEventArgs pevent)
{
//do nothing here so that image does not have to repaint the background
}

Hope that helps
Mark R Dawson
http://www.markdawson.org
 
U

utkarsh

Thanks Mark for your code and so much help!! :)

But my problem is little bit different.
I have two screen left and right. In left panel I have loaded a Image
in picture box. When user move the mouse on the left panel, a
maginified view of a image section, near by the cursor, should be
visible in the right panel.

I have to do the similar work like the windows magnifier ( Programs ->
Accessories -> Accessibility -> Magnifier)

So I have loaded the same image in both the screens and I have to
update the right screen as mouse move in left. I have removed the
flickering by using the timer tick event. But only problem left is,
timer is consuming the 100% CPU.

Thanks again,
Utkarsh Panwar
 
G

Guest

Hi Utkarsh,
I made a little app that mimics the magnifier behaviour you talked about,
with an image on the left and a magnified version on the right. I loaded a
3MB file and it seems to take about 50% of the CPU on my home computer when I
move the mouse very rapidly, but with no flickering.

I have 3 files:
1. ZoomSelectorPictureBox.cs -> displays an image with a red rectangle
around the mouse indicating where the zoomed in portion of the image will be
displayed. This inherits from PictureBox (although it doesn't really need to)

2. ZoomMagnifierPictureBox which shows a zoomed in version of the selected
region in ZoomSelectorPictureBox, this also inherits from picturebox

3. Form1.cs -> creates instances of the above classes. you will need to
modify the Form1_Load method to load an image on your computer.

I have pasted all three files below, but the formatting will be messed up in
these windows. If you like you can download the entire source from
http://www.markdawson.org/software/csharp/magnifier.zip which may be easier
than getting the text code out from below.


//FORM1.cs

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsApplication4
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(800, 469);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_Load(object sender, System.EventArgs e)
{
ZoomSelectorPictureBox selectorPictureBox = new ZoomSelectorPictureBox();
selectorPictureBox.Image = Image.FromFile(@"c:\test.bmp");

this.Controls.Add(selectorPictureBox);
selectorPictureBox.Left = 0;
selectorPictureBox.Top = 0;
selectorPictureBox.Width = 400;
selectorPictureBox.Height = 400;

ZoomMagnifierPictureBox zoomMagnifier = new
ZoomMagnifierPictureBox(selectorPictureBox);
this.Controls.Add(zoomMagnifier);
zoomMagnifier.Left = 400;
zoomMagnifier.Top = 0;
zoomMagnifier.Width = 400;
zoomMagnifier.Height = 400;
}
}
}







//ZoomMagnifierPictureBox.cs

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

namespace WindowsApplication4
{
public class ZoomMagnifierPictureBox : PictureBox
{
private Rectangle _zoomRegion;
private Image _originalImage;

public ZoomMagnifierPictureBox(ZoomSelectorPictureBox zoomSelector) : base()
{
_originalImage = zoomSelector.Image;
zoomSelector.ZoomRectangleChanged += new
WindowsApplication4.ZoomSelectorPictureBox.ZoomRectangleLocationChangedEventHandler(zoomSelector_ZoomRectangleChanged);
}

protected override void OnPaintBackground(PaintEventArgs pevent)
{
//base.OnPaintBackground (pevent);
}

protected override void OnPaint(PaintEventArgs e)
{
//base.OnPaint (e);


e.Graphics.DrawImage(_originalImage, new Rectangle(0,0, this.Width,
this.Height), _zoomRegion.X, _zoomRegion.Y, _zoomRegion.Width,
_zoomRegion.Height, GraphicsUnit.Pixel);
}

private void zoomSelector_ZoomRectangleChanged(Rectangle zoomRectangle)
{
_zoomRegion = zoomRectangle;
this.Refresh();
}
}
}








//ZoomSelectorPictureBox.cs

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

namespace WindowsApplication4
{
public class ZoomSelectorPictureBox : PictureBox
{
private Rectangle _zoomRegion;
private bool _mouseIsOver = false;

public delegate void ZoomRectangleLocationChangedEventHandler(Rectangle
zoomRectangle);
public event ZoomRectangleLocationChangedEventHandler ZoomRectangleChanged;

public ZoomSelectorPictureBox() : base()
{
//create zoom region rectangle
_zoomRegion = new Rectangle(0, 0, 50, 50);

//set up event handlers
this.MouseMove += new MouseEventHandler(ZoomSelectorPictureBox_MouseMove);
this.MouseLeave += new EventHandler(ZoomSelectorPictureBox_MouseLeave);
this.MouseEnter += new EventHandler(ZoomSelectorPictureBox_MouseEnter);
}

protected override void OnPaintBackground(PaintEventArgs pevent)
{
//base.OnPaintBackground (pevent);
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint (e);

//only do this if the mouse is over the control
if(_mouseIsOver)
{
using(Pen p = new Pen(Color.Red, 5))
{
e.Graphics.DrawRectangle(p, _zoomRegion);
}
}
}

private void ZoomSelectorPictureBox_MouseMove(object sender,
MouseEventArgs e)
{
//make the mouse in the center of the zoom region
_zoomRegion.X = e.X - _zoomRegion.Width / 2;
_zoomRegion.Y = e.Y - _zoomRegion.Width / 2;

//raise the event to listeners to refresh their
//zoomed view
if(ZoomRectangleChanged != null)
{
ZoomRectangleChanged(_zoomRegion);
}

//force image to be redrawn
this.Refresh();
}

private void ZoomSelectorPictureBox_MouseLeave(object sender, EventArgs e)
{
_mouseIsOver = false;

//force image to redraw without the rectangle
this.Refresh();
}

private void ZoomSelectorPictureBox_MouseEnter(object sender, EventArgs e)
{
_mouseIsOver = true;
}
}
}


Hope that helps
Mark R Dawson
http://www.markdawson.org
 
N

Nick Z.

A timer is really not a good idea, take Marks advice on the
OnPaintBackground and OnPaint methods and add an OnMouseMove event
handler to the left panel. In that handler add something like
rightPanel.Invalidate(). This will force the right panel to be repainted
when the mouse moves over the left panel.

Nick Z.
 
U

utkarsh

Thank you very much Mark for such a great help !!!

:)

I looked at the code it is perfectly fine. CPU goes high till 50%, if
mouse movement is faster. But there is absolutly no flickering.


Thanks Again,
Utkarsh Panwar
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top