I have a class project that uses Windows Forms to create a GUI that controls a second form. The second form is a DrawingForm with a bitmap. Using a backgroundworker, I am drawing random, continuous Bezier curves all over the bitmap. It is a simple program, so it is able to draw them quickly, hundreds per second. I would like to add a slider bar that would allow me to control how fast the lines paint. In other words, I dont want to set up each curve to be drawn on a timer, which would cause it to appear to stop and start hundreds of times a second. I have exhausted myself searching google, any tips on how to do this would be awesome. Thanks!
Edit: Here is a code snippet. This code is in my class for my drawing form. Its constructor is called from my main GUI/user control class.
// this is the code executed by the background thread
// it can run continously without hanging the user interface thread
// except that it draws to a bitmap (with the bMapDC) instead of to the form
private void backgroundWorkerDrawing_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 100000000; i++)
{
if (scribbleOn == true)
{
curveColor = changeColor(curveColor);
Pen pen = new Pen(curveColor, penThickness);
if (i == 0) // initial curve should start in center, the rest of the points will be random
{
lastX = GUI.rand.Next(0, bMapWidth); //used to store the x coordinate where the curve ends
lastY = GUI.rand.Next(0, bMapHeight); //used to store the y coordinate where the curve ends
bMapDC.DrawBezier(pen, initialX, initialY, GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight),
GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight), lastX, lastY);
}
if (i > 0) // used for all curves after the first one.
{
int tempX = GUI.rand.Next(0, bMapWidth); //used to store the x coordinate where the curve ends
int tempY = GUI.rand.Next(0, bMapHeight); //used to store the y coordinate where the curve ends
bMapDC.DrawBezier(pen, lastX, lastY, GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight),
GUI.rand.Next(0, bMapWidth), GUI.rand.Next(0, bMapHeight), tempX, tempY);
lastX = tempX; // sets the last x coordinate of the last curve for next loop
lastY = tempY; // sets the last y coordinate of the last curve for next loop
}
pen.Dispose(); // free up resources from the pen object
}
else i = 0;
}
}
// timer event handler causes the form to be repreatedly invalidated
// This causes the paint event handler to keep going off,
// which causes the bMap that is continously being drawn to
// by the background thread to be continously redisplayed in the form.
// We will see other ways to do this that may be better.
private void timerInvalidate_Tick(object sender, EventArgs e)
{
Invalidate();
}
private void DrawingForm_Shown(object sender, EventArgs e)
{
lock (bMap)
{
bMapHeight = bMap.Height; // set the vars that keep track of the size of the bMap
bMapWidth = bMap.Width;
initialX = bMapWidth / 2; // start the curve at the center of the bMap
initialY = bMapHeight / 2;
bMapDC = Graphics.FromImage(bMap); // setup the DC (device context) to allow drawing to the bMap)
backgroundWorkerDrawing.RunWorkerAsync(); // start the background thread
timerInvalidate.Enabled = true; // start the timer that will cause periodic Invalidates
}
}
You can make thread and use sleep
private Thread SimulaciaArts;
public Animation(){
public SpleepValue { get; set;}
SimulaciaArts = new Thread(new ThreadStart(simuluj));
}
public void simuluj(){
//anything
Thread.Sleep(SleepValue);
}
and in gui you must use delegate
delegate void Invoker();
private void setSpeed()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new Invoker(setSpeed));
return;
}
Simulation.SleepValue=Speed;
}
Hope it is good.
Related
I have made a Form that moves across the screen to the left, but all of the components on the Form are blank.
I put the code for the movement in comments and everything was fine, so the problem is in my movement code, but I don't know what the problem is.
System.Threading.Thread thread;
private void Form1_Load(object sender, EventArgs e)
{
thread = new System.Threading.Thread(loop);
thread.Start();
}
void loop()
{
this.BeginInvoke((Action)delegate () {
int x = 0;
int y = 0;
int MoveRate = 1;
Point TopLeft = this.Location;
Point TopRight = new Point (this.Location.X + this.Width, this.Location.Y);
while (true)
{
x = x + MoveRate;
this.Location = new Point(x, 150);
System.Threading.Thread.Sleep(10);
}
});
}
This should make the form move to the left, however the components on the Form are blank.
Let's look at the loop() method:
void loop()
{
this.BeginInvoke((Action)delegate () {
int x = 0;
int y = 0;
int MoveRate = 1;
Point TopLeft = this.Location;
Point TopRight = new Point (this.Location.X + this.Width, this.Location.Y);
while (true)
{
x = x + MoveRate;
this.Location = new Point(x, 150);
System.Threading.Thread.Sleep(10);
}
});
}
This code immediately invokes a delegate back on the main UI thread. The delegate runs a while(true) loop that never exits. As soon as the loop begins to execute, the UI thread is completely hosed with no hope of ever responding to other event messages, including paint events.
Try this instead:
void loop()
{
int x = 0;
int MoveRate = 1;
while(true)
{
x += MoveRate;
this.BeginInvoke((Action)delegate () { this.Location = new Point(x, 150); });
System.Threading.Thread.Sleep(16);
}
}
It's all the same code (except for the stuff that wasn't doing anything), but now arranged so the delegate is invoked inside the loop. The UI thread is only blocked for a brief time, and then control returns back to the loop thread, which will Sleep for a little while before bothering the UI again. The invoke even simple enough I was able to rewrite it as single line.
Notice I also increased the sleep time, because that still gives you 60 frames per second.
An Async variation of the same process, to test something different.
(The main reason why your thread wasn't working as expected has already been explained. If you use a thread and then invoke the UI thread in a close loop, it's more or less like not having your code run in a different thread at all: a Form doesn't have time to update itself or its controls).
This method add a termination to the scrolling procedure, when the Form is scrolled outside the current Screen bounds. When this condition is met, the while loop is exited and the Task ends, moving the Form in the center of the screen.
The Task is started in the Shown event. I think it's more appropriate than the Load event (the Form is ready to be presented, here).
Note that neither this Task or the Thread add any check on the Form.FormClosing event, to cancel the asynchronous proc: if the Form is closed while the scrolling is performed, you will most likely have a exception (the Form has been disposed, thus no more handle).
private async Task Scroller(int ScreenWidth)
{
int x = 0;
int MoveRate = 2;
while (true)
{
x += MoveRate;
this.BeginInvoke(new MethodInvoker(() => { this.Location = new Point(x, 150);}));
await Task.Delay(10);
if (x > ScreenWidth) break;
};
}
private async void Form_Shown(object sender, EventArgs e)
{
int ScreenWidth = Screen.FromHandle(this.Handle).Bounds.Width;
await this.Scroller(ScreenWidth);
this.Location = new Point((ScreenWidth - this.Width) / 2 , 150);
}
right now I'm making a game and a character in it to move the player. I'm just a beginner about programming.
There are 8 buttons, and each button goes to a direction. For example, this my program for
private void btnUp_Click(object sender, EventArgs e)
{
//move up
y = y - 1;
MovePlayer();
UpdateLabelLocation();
}
public void MovePlayer()
{
picPlayer.Location = new Point(x, y);
}
public void UpdateLabelLocation()
{
lblLocation.Text = "Location: (" + x + ", " + y + ")";
}
I want to make it move when I press up, down, left or right keys. Also, if possible I want to make it so that when I press right and up at the same time, it triggers this:
private void btnRightUp_Click(object sender, EventArgs e)
{
//move player
y = y - 1;
x = x + 1;
MovePlayer();
UpdateLabelLocation();
}
I appreciate the help.
What you're essentially doing is creating your own simple game engine. As commentors have noted, you're better off using an existing game engine such as Unity. It's far easier and more liberating than going about it with WinForms.
That said, if you really want to continue with this, I strongly suggest you move the code in the Click handlers to a method. This reduces code duplication. i.e.
private void DownButton_Click(...)
{
MovePlayer(0, 1);
}
private void UpButton_Click(...)
{
MovePlayer(0, -1);
}
public void MovePlayer(float xStep, float yStep)
{
x += xStep;
y += yStep;
MovePlayer();
UpdateLabelLocation();
}
To move down and left you'd call MovePlayer(-1, 1);
To move up and right you'd call MovePlayer(1, -1);
Next you'll need to respond to KeyPress events. i.e.
public void Form_KeyPress(object sender, KeyPressEventArgs args)
{
switch (args.KeyChar) {
case 'a': // Left
args.Handled = true;
MovePlayer(-1, 0);
break;
case 'd': // Right
args.Handled = true;
MovePlayer(1, 0);
break;
case 'w': // Up
args.Handled = true;
MovePlayer(0, -1);
break;
case 's': // Down
args.Handled = true;
MovePlayer(0, 1);
break;
}
}
Note that if you have another control that accepts keyboard input(such as a TextBox), it will intercept the key press. To get around this, use KeyPreview to force the window to preview the input first. args.Handled = true prevents the event from routing to child controls after your code.
Unfortunately WinForms doesn't record multiple keys pressed at the same time, so using KeyPress alone isn't enough to handle corner movement. You can work around this by hooking onto KeyDown and KeyUp, but it's more trouble than it's worth.
Here's a more robust solution. Bear in mind the following isn't thread safe, so if you plan on introducing other threads you'll need to use appropriate locking.
HashSet<KeyCode> state = new HashSet<KeyCode>();
float speed = 120; // 120 pixels/second.
private void Form_KeyDown(object sender, KeyEventArgs args)
{
var key = args.KeyCode;
state.Add(key);
// Fire pressed when a key was up.
if (!state.Contains(key)) {
state.Add(key);
OnKeyPressed(key);
}
}
private void Form_KeyUp(object sender, KeyEventArgs args)
{
var key = args.KeyCode;
state.Remove(key);
// Fire release when a key was down.
if (state.Contains(key)) {
state.Remove(key);
OnKeyReleased(key);
}
}
// Runs when key was up, but pressed just now.
private void OnKeyPressed(KeyCode key)
{
// Trigger key-based actions.
}
// Runs when key was down, but released just now.
private void OnReleased(KeyCode key)
{
// Trigger key-based actions, but on release instead of press.
}
private bool IsDown(KeyCode key)
{
return state.Contains(key);
}
// Trigger this periodically, at least 20 times a second(ideally 60).
// An option to get you started is to use a windows timer, but
// eventually you'll want to use high precision timing instead.
private void Update()
{
var deltaTime = // Calculate the seconds that have passed since the last update.
// Describing it is out of the scope of this answer, but see the links below.
// Determine horizontal direction. Holding both
// A & D down cancels movement on the x-axis.
var directionX = 0;
if (IsDown(KeyCode.A)) {
directionX--;
}
if (IsDown(KeyCode.D)) {
directionX++;
}
// Determine vertical direction. Holding both
// W & S down cancels movement on the y-axis.
var directionY = 0;
if (IsDown(KeyCode.W)) {
directionY--;
}
if (IsDown(KeyCode.S)) {
directionY++;
}
// directionX & directionY should be normalized, but
// I leave that as an exercise for the reader.
var movement = speed * deltaTime;
var offsetX = directionX * movement;
var offsetY = directionY * movement;
MovePlayer(offsetX, offsetY);
}
As you can see, there's quite a bit involved. If you want more fine-grained timing, look into this article. Eventually you'll want to transition to a game loop, but that's yet another topic out of the scope of this answer.
I have an app with 2 forms. Form1 have the pictureBox and buttons, Form2 has a code that, when i call the form:
private void button1_Click(object sender, EventArgs e)
{
new Form2().Show();
}
it turns is a Zoom Lens, that i can use in Form1 pictureBox.
Problem is, when Form2(lens) is runing and i click ESC to close the form2, it closes but keep increasing consuming memory. Even the errors that form2(lens) has is triggering, like move mouse too far at the border, even after call close to form2.
Here is the code to the Lens form2:
PictureBox pictureBox1 = new PictureBox(); // Have a picture box
int zoom = 1; // Variable for zoom value
public Form1()
{
pictureBox1.Dock = DockStyle.Fill; // Occupy the full area of the form
pictureBox1.BorderStyle = BorderStyle.FixedSingle; // Have a single border of clear representation
Controls.Add(pictureBox1); // Add the control to the form
FormBorderStyle = FormBorderStyle.None; // Make the form borderless to make it as lens look
Timer timer = new Timer(); // Have a timer for frequent update
timer.Interval = 100; // Set the interval for the timer
timer.Tick += timer_Tick; // Hool the event to perform desire action
timer.Start(); //Start the timer
printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); // Have a bitmap to store the image of the screen
}
void timer_Tick(object sender, EventArgs e)
{
var graphics = Graphics.FromImage(printscreen as Image); // Get the image of the captured screen
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size); // Get the copy of screen
var position = Cursor.Position; // Get the position of cursor
var lensbmp = new Bitmap(50, 50); // Have a bitmap for lens
var i = 0; // Variable for row count
var j = 0; // Variable for column count
for (int row = position.X - 25; row < position.X + 25; row++) // Indicates row number
{
j = 0; // Set column value '0' for new column
for (int column = position.Y - 25; column < position.Y + 25; column++) // Indicate column number
{
lensbmp.SetPixel(i, j, printscreen.GetPixel(row, column)); // Place current region pixel to lens bitmap
j++; // Increase row count
}
i++; // Increase column count
}
this.pictureBox1.Image = new Bitmap(lensbmp, lensbmp.Width * zoom, lensbmp.Height * zoom); // Assign lens bitmap with zoom level to the picture box
Size = pictureBox1.Image.Size; // Assign optimal value to the form
Left = position.X + 20; // Place form nearer to cursor X value
Top = position.Y + 20; // Place form nearer to cursor Y value
TopMost = true; // Keep the form top level
}
// Override OnKeyDown for zoom in and zoom out actions
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyValue == 73) // Set "i" as the key for Zoom In.
zoom++; // Increase zoom by 1 item greater
else if (e.KeyValue == 79) // Set "o" as the key for Zoom Out
zoom--; // Decrease zoom by 1 item smaller
else if (e.KeyValue == 27) // Set "Esc" to close the magnifier
{
Close(); // Close the form
Dispose(); // Dispose the form
}
base.OnKeyDown(e);
}
Is that a way to close this form2 and stop all methods while form1 keep runing? It keep increasing memory consume like 1mb for sec.
You have a dangerous timer because it isn't declared at the form scope, so it can still keep running.
Declare it at the form level instead:
PictureBox pictureBox1 = new PictureBox();
int zoom = 1;
Timer timer = new Timer();
public Form1()
{
pictureBox1.Dock = DockStyle.Fill; // Occupy the full area of the form
pictureBox1.BorderStyle = BorderStyle.FixedSingle; // Have a single border of clear representation
Controls.Add(pictureBox1); // Add the control to the form
FormBorderStyle = FormBorderStyle.None; // Make the form borderless to make it as lens look
timer.Interval = 100; // Set the interval for the timer
timer.Tick += timer_Tick; // Hool the event to perform desire action
timer.Start(); //Start the timer
printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); // Have a bitmap to store the image of the screen
}
Also, make sure you dispose of your image and graphic objects, too, when they aren't being used anymore.
I'm doing an 8 Puzzle solver that ultimately stores each node (int[] of elements 0-8) in the path to put the blocks in order in a stack. I have a WPF GUI that displays an int[,]
foreach (var node in stack)
{
int[,] unstrung = node.unstringNode(node); // turns node of int[] into board of int[,]
blocks.setBoard(unstrung); // sets the board to pass in to the GUI
DrawBoard(); // Takes the board (int[,]) and sets the squares on the GUI to match it.
Thread.Sleep(500);
}
The GUI displays the initial board, and then after I click solve, the final (in order) board is displayed correctly. What I want to do is display each node on the board for some amount of time, ultimately arriving at the in-order board. With Thread.Sleep, the GUI will simply pause for the set amount of time before displaying the final node. Any ideas as to why it this code wouldn't display the board at each node every 500ms?
For reference, here's an example output from Console.Write for the nodes:
4,2,3,6,1,0,7,5,8
4,2,0,6,1,3,7,5,8
4,0,2,6,1,3,7,5,8
4,1,2,6,0,3,7,5,8
4,1,2,0,6,3,7,5,8
0,1,2,4,6,3,7,5,8
1,0,2,4,6,3,7,5,8
1,2,0,4,6,3,7,5,8
1,2,3,4,6,0,7,5,8
1,2,3,4,0,6,7,5,8
1,2,3,4,5,6,7,0,8
1,2,3,4,5,6,7,8,0
Edit:
Since my original answer was downvoted for using a Thread instead of a Timer, here is an example using a timer.
The code for using a Thread was just shorter and I wanted to give him a solution quickly.
Also, using a Thread instead of a timer meant he didn't need to pass parameters differently or restructure his loop.
This is why it is a good idea to discuss pros/cons of alternate solutions instead of simply insisting that there is only one right way.
Use the timer_Tick function to update the position.
You might notice that this complicates the original code since you will have to pass parameters differently and restructure your loop.
public partial class Form1 : Form
{
private Point pos = new Point(1,1);
private float[] vel = new float[2];
private Size bounds = new Size(20,20);
private Timer ticky = new Timer(); //System.Windows.Forms.Timer
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ticky.Interval = 20;
ticky.Tick += ticky_Tick;
vel[0] = 4; vel[1] = 0;
ticky.Start();
}
void ticky_Tick(object sender, EventArgs e)
{
updatePosition();
//This tells our form to repaint itself (and call the OnPaint method)
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillEllipse(new SolidBrush(Color.LightBlue), new Rectangle(pos, bounds));
}
private void updatePosition()
{
pos = new Point(pos.X + (int)vel[0], pos.Y + (int)vel[1]);
vel[1] += .5f; //Apply some gravity
if (pos.X + bounds.Width > this.ClientSize.Width)
{
vel[0] *= -1;
pos.X = this.ClientSize.Width - bounds.Width;
}
else if (pos.X < 0)
{
vel[0] *= -1;
pos.X = 0;
}
if (pos.Y + bounds.Height > this.ClientSize.Height)
{
vel[1] *= -.90f; //Lose some velocity when bouncing off the ground
pos.Y = this.ClientSize.Height - bounds.Height;
}
else if (pos.Y < 0)
{
vel[1] *= -1;
pos.Y = 0;
}
}
}
Results:
You can use timers to do all sorts of delayed form drawing:
Original Solution:
//Create a separate thread so that the GUI thread doesn't sleep through updates:
using System.Threading;
new Thread(() => {
foreach (var node in stack)
{
//The invoke only needs to be used when updating GUI Elements
this.Invoke((MethodInvoker)delegate() {
//Everything inside of this Invoke runs on the GUI Thread
int[,] unstrung = node.unstringNode(node); // turns node of int[] into board of int[,]
blocks.setBoard(unstrung); // sets the board to pass in to the GUI
DrawBoard(); // Takes the board (int[,]) and sets the squares on the GUI to match it.
});
Thread.Sleep(500);
}
}).Start();
Solution in 2022:
await Task.Delay(500);
Things really are better these days.
I have this code where i click control + m :
void gkh_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == System.Windows.Forms.Keys.LControlKey) || (e.KeyCode == System.Windows.Forms.Keys.RControlKey))
{
controlDown = true;
}
if (e.KeyCode == System.Windows.Forms.Keys.M && controlDown)
{
backgroundWorker1.RunWorkerAsync();
Then the backgroundworker do work event:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (mf1 == null)
{
mf1 = new MagnifierForm(mConfiguration, System.Windows.Forms.Cursor.Position);
mf1.Show();
}
}
I used a breakpoint and its getting to the MagnifierForm constructor and do everything there but when i click continue i never see this MagnifierForm form . Why ?
EDIT**
The reason i wanted to use backgroundworker to show the new form is that in the main form where i show the new form i have a timer tick event and for some reason this timer when its running only when its running making the new form to be show on a different location from the mouse cursor and the the form is moving/sliding to where the mouse cursor is.
When the timer is not working there is no problems i show the new form and its showing it exactly where the mouse cursor is.
I dont know why this timer event make the problem and the timer is not connected by anything to the new form i want to show.
This is the timer event i have in the main form:
private void timer2_Tick(object sender, EventArgs e)
{
label1.Visible = true;
if (counter == 200)
{
timer2.Enabled = false;//counter = 0;
return;
}
counter += 1;
distance = (float)counter;
CloudEnteringAlert.cloudalert(bitmapwithclouds, distance);
pictureBox1.Invalidate();
Now i found that if i remove for the test the line:
CloudEnteringAlert.cloudalert(bitmapwithclouds, distance);
And the timer is working there is no problem. The new form is show exactly where the mouse cursor is.
This is the cloudalert method that making the problem and i dont know why:
public static List<PointF> cloudalert(Bitmap bmp, float kilometers)
{
AddDistanceToPoints = new List<PointF>();
Color c1 = Color.White;
Color c2 = Color.FromArgb(c1.A,
(int)(c1.R * 1), (int)(c1.G * 1), (int)(c1.B * 1));
Load();
float distance = kilometers / (float)1.09;
clouds = new List<PointF>();
clouds1 = new List<PointF>();
file = Path.GetDirectoryName(Application.LocalUserAppDataPath) + "\\Data" + "\\Data.txt";
OptionsFile setting_file = new OptionsFile(file);
LoadPoints_X = setting_file.GetListFloatKey("Points Coordinates X");
LoadPoints_Y = setting_file.GetListFloatKey("Points Coordinates Y");
for (int i = 0; i < PointsFloat.Count; i++)
{
//clouds1.Add(new PointF(LoadPoints_X[i] - distance, LoadPoints_Y[i]));
AddDistanceToPoints.Add(new PointF(PointsFloat[i].X - distance, PointsFloat[i].Y));
}
bmp = FastComparison(bmp, Properties.Resources.clean_radar_image);
newbitmap = bmp;
for (int x = 0; x < AddDistanceToPoints.Count; x++)//clouds1.Count; x++)
{
if (AddDistanceToPoints[x].X > 0)//clouds1[x].X > 0)
{
//Color color = bmp.GetPixel((int)clouds1[x].X, (int)clouds1[x].Y);
Color color = bmp.GetPixel((int)AddDistanceToPoints[x].X, (int)AddDistanceToPoints[x].Y);
int dR = (int)color.R;
int dG = (int)color.G;
int dB = (int)color.B;
if (dR == 0 && dG == 0 && dB == 0)
{
}
else
{
//clouds.Add(new PointF(clouds1[x].X, clouds1[x].Y));
clouds.Add(new PointF(AddDistanceToPoints[x].X, AddDistanceToPoints[x].Y));
//newbitmap.SetPixel((int)clouds1[x].X, (int)clouds1[x].Y, Color.White);
newbitmap.SetPixel((int)AddDistanceToPoints[x].X, (int)AddDistanceToPoints[x].Y, Color.White);
}
}
}
//newbitmap.Save(#"d:\test\newbitmap.jpg");
if (clouds.Count == 0)
{
cloudsfound = false;
cloudsdistance.Text = distance.ToString();
//clouds = null;
return clouds
;
}
else
{
cloudsfound = true;
for (int i = 0; i < clouds.Count; i++)
{
pointtocolor.Add(clouds[i]);
cloudsdistance.Text = distance.ToString();
}
}
return clouds;
}
And in the main form im showing the new form by button click for example:
private void button1_Click(object sender, EventArgs e)
{
if (mf1 == null)
{
mf1 = new MagnifierForm(mConfiguration, System.Windows.Forms.Cursor.Position);
mf1.Show();
}
}
Then why this timer tick event or more why this method cloudalert making the form mf1 to be show on a different location for a second and then the form slide/moving to where the mouse cursor is. But when this method i remove it or stop the timer and show the new form so there is no problems the form is show right where the mouse cursor is.
And the new form i show it at any place on the screen i dont show it only over the main form i show it where ever the mosue cursor is. The mouse can be on the taskbar or at 0,0 of the screen or anyplace and then i click button1 or i have global keys hook so i make Ctrl + M
And when the timer is running with this method cloudalert the form is show at some different location then move slide to the place of where the mouse cursor is.
You can get the new form im trying to show that is a magnifying glass here:
http://www.codeproject.com/Articles/18235/Simple-Magnifier
What im trying to do is not using this magnifier menu it have but using my button click event or the ctrl + m keys to show the magnifier glass form. But i have this problem.
If im using this magnifier menu and timer is working with the method there is no problems.
Strange cant figure out where is the problem with my timer2/method cloudalert.
First - do not work with UI from multiple threads. If you want to display something when worker completes execution, then handle RunWorkerCompleted event (this handler runs on main thread):
void backgroundWorker1_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{
if (mf1 == null)
{
mf1 = new MagnifierForm(mConfiguration, Cursor.Position);
mf1.Show();
}
}
Second - your code is not working, because background thread exits. If you would change mf1.Show() to mf1.ShowDialog() then you'll see your form.
DoWork is run in a worker thread. You shouldn't try to change your UI from there, but only from your main UI thread.