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);









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



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

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)