Use a KeyDown inside a Timer_Tick Event
Use a KeyDown inside a Timer_Tick Event
Me and my buddy have been working on this magnifier application and we cannot make it work the way we want it.
The way we would like it to work:
Right now once i hit enter, the window follows the mouse because it goes into a for loop where it grabs "Cursor.Position". I've tried to save the Cursor.Position value at the "OnkeyDown" event and use it inside the timer loop but that won't work since it "does not exist in current context".
Can anyone see how i can do this?
Thanks in advance!
/Morten
/* O-button zooms out
* I-button zooms in
* Esc-button exits app
* Enter moves magnifying window to new location (doesn't work)
*/
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Magnifier
public partial class Form1 : Form
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
PictureBox pictureBox1 = new PictureBox();
int zoom = 3; //zoom level
public bool NewZoomLocation = false;
public Form1()
InitializeComponent();
pictureBox1.Dock = DockStyle.Fill;
pictureBox1.BorderStyle = BorderStyle.FixedSingle;
Controls.Add(pictureBox1);
FormBorderStyle = FormBorderStyle.None;
Timer timer = new Timer();
timer.Interval = 100;
timer.Tick += timer_Tick;
timer.Start();
void timer_Tick(object sender, EventArgs e)
var position = Cursor.Position;
int xlocation = position.X;
int ylocation = position.Y;
try
var graphics = Graphics.FromImage(printscreen as Image);
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
GC.Collect(); // Force the garbage collector (deals with memory leak)
if (NewZoomLocation == true)
var lensbmp = new Bitmap(50, 50); //Bitmap for Zoom window
var i = 0;
var j = 0;
for (int row = xlocation - 25; row < xlocation + 25; row++)
j = 0;
for (int column = ylocation - 25; column < ylocation + 25; column++)
lensbmp.SetPixel(i, j, printscreen.GetPixel(row, column));
j++;
i++;
this.pictureBox1.Image = new Bitmap(lensbmp, lensbmp.Width * zoom, lensbmp.Height * zoom);
Size = pictureBox1.Image.Size;
Left = xlocation - 45 * (zoom); //Horisontal position of final zoom window
Top = ylocation + 30; //Vertical position of final zoom window
TopMost = true;
catch //(Exception ex)
//MessageBox.Show(ex.Message);
protected override void OnKeyDown(KeyEventArgs e)
if (e.KeyValue == 73) // I-button to zoom in
zoom++;
else if (e.KeyValue == 79) // O-button to zoom in
zoom--;
else if (e.KeyValue == 27) // Esc-button to exit
Close();
Dispose();
else if (e.KeyValue == 13) // Enter-button to choose zoon area
NewZoomLocation = true;
base.OnKeyDown(e);
NewZoomLocation
if (NewZoomLocation == true) DoYourWork(); NewZoomLocation = false;
1 Answer
1
I'm not really sure what you want to achieve here, however this should get you in a better place.
First thing first. The use of GC.Collect
its because you are trying to plug a memory leak, if you ever create an image, dispose of it.
GC.Collect
Given some globals
private readonly PictureBox pictureBox1 = new PictureBox();
private Bitmap _lastBmp = new Bitmap(300, 300);
private Point _position;
public bool NewZoomLocation;
private int zoom = 3; //zoom level
Constructor
public Form1()
InitializeComponent();
pictureBox1.Dock = DockStyle.Fill;
pictureBox1.BorderStyle = BorderStyle.FixedSingle;
Controls.Add(pictureBox1);
FormBorderStyle = FormBorderStyle.None;
KeyPreview = true;
Size = _lastBmp.Size;
TopMost = true;
var timer = new Timer();
timer.Interval = 100;
timer.Tick += timer_Tick;
timer.Start();
Cleanup
protected override void OnClosed(EventArgs e)
base.OnClosed(e);
_lastBmp.Dispose();
_lastBmp = null;
Keydown
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
base.OnPreviewKeyDown(e);
switch (e.KeyCode)
case Keys.Enter:
NewZoomLocation = true;
_position = Cursor.Position;
break;
case Keys.Up:
zoom++;
break;
case Keys.Down:
zoom--;
break;
case Keys.Escape:
Close();
break;
Timer
private void timer_Tick(object sender, EventArgs e)
if (NewZoomLocation)
var w = _lastBmp.Size.Width / zoom;
var h = _lastBmp.Size.Height / zoom;
var x = _position.X - w / 2;
var y = _position.Y - h / 2;
var size = new Size(w, h);
using (var screen = new Bitmap(size.Width, size.Height))
using (var g = Graphics.FromImage(screen))
g.CopyFromScreen(new Point(x, y), Point.Empty, size);
// resize
using (var g = Graphics.FromImage(_lastBmp))
g.DrawImage(screen, new Rectangle(new Point(), _lastBmp.Size), new Rectangle(0, 0, w, h), GraphicsUnit.Pixel);
pictureBox1.Image = _lastBmp;
There is a lot more that can be done with this, however it should get you started. There is no memory leak anymore, it only grabs a screen shot of what it needs so will be faster.
Good luck
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy
So, you don't want the magnifier to follow the cursor? Well, your
NewZoomLocation
variable is always true once it's set to true the first time. You need to set it to false after re-locating your "window". Something like this:if (NewZoomLocation == true) DoYourWork(); NewZoomLocation = false;
.– Ahmed Abdelhameed
Sep 15 '18 at 23:49