I can't make a function so that during the movement of the picturebox which happens with a while loop.
I executed a script on certain coordinates, I tried to do it using the switch statement, but the function simply does not work
When you run it, nothing happens, as if this line of code does not exist.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace shadowfiend_minigame
{
public partial class Form1 : Form
{
private int _first_shadowrazeX = 404, _first_shadowrazeY = 204;
private int _second_shadowrazeX = 724, _second_shadowrazeY = 204;
private int _third_shadowrazeX = 1106, _third_shadowrazeY = 204;
private int zeus_hp = 1000;
private int shadow_fiend_hp = 2800;
Point point = new Point(1106, 204);
Point point2 = new Point(724, 204);
Point point3 = new Point(404, 204);
private int speed_zeus, damage_zeus;
private int shadow_fiend_damage;
Thread thread = new Thread(ShadowRaze_Click);
public Form1()
{
InitializeComponent();
this.KeyDown += new KeyEventHandler(ShadowRaze_Click);
KeyPreview = true;
}
bool CheckedBox()
{
bool checked1 = checkBox1.Checked;
bool checked2 = checkBox2.Checked;
bool checked3 = checkBox3.Checked;
if (checked1 == false && checked2 == false && checked3 == false)
{
return false;
}
else return true;
}
private async void Start_Click(object sender, EventArgs e)
{
Thread thread = new Thread(Zeus);
if (CheckedBox() == false)
{
MessageBox.Show("Выберите сложность игры!");
}
else
{
Start.Visible = false;
checkBox1.Visible = false;
checkBox2.Visible = false;
checkBox3.Visible = false;
thread.Start();
}
}
private async void Zeus()
{
Thread thread = new Thread(Zeus);
while (shadow_fiend_hp != 0)
{
for (int i = 0; i < 50; i++)
{
var x = _zeus.Location.X;
this.Invoke(new Action(() => _zeus.Location = new Point(_zeus.Location.X - 20, _zeus.Location.Y)));
Thread.Sleep(speed_zeus);
switch (_zeus.Location.X)
/*
* Here it is necessary that when the picturebox reaches a certain point while moving, the function is executed
*/
{
case 1106:
zeus_hp = zeus_hp - 200;
this.Invoke(new Action(() => label4.Text = "zeus_hp: " + zeus_hp));
break;
case 724:
zeus_hp = zeus_hp - 200;
this.Invoke(new Action(() => label4.Text = "zeus_hp: " + zeus_hp));
break;
case 404:
zeus_hp = zeus_hp - 200;
this.Invoke(new Action(() => label4.Text = "zeus_hp: " + zeus_hp));
break;
}
}
Zeus_Attack(damage_zeus);
if (shadow_fiend_hp == 0)
{
MessageBox.Show("You lose");
this.Invoke(new Action(() => Start.Visible = true));
this.Invoke(new Action(() => checkBox1.Visible = true));
this.Invoke(new Action(() => checkBox2.Visible = true));
this.Invoke(new Action(() => checkBox3.Visible = true));
}
else if (zeus_hp == 0)
{
MessageBox.Show("You win");
this.Invoke(new Action(() => Start.Visible = true));
this.Invoke(new Action(() => checkBox1.Visible = true));
this.Invoke(new Action(() => checkBox2.Visible = true));
this.Invoke(new Action(() => checkBox3.Visible = true));
}
for (int i = 0; i < 50; i++)
{
this.Invoke(new Action(() => _zeus.Location = new Point(_zeus.Location.X + 20, _zeus.Location.Y)));
Thread.Sleep(speed_zeus);
}
}
thread.Join();
ResetAll();
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
checkBox3.Checked = false;
checkBox1.Checked = false;
speed_zeus = 30;
damage_zeus = 200;
}
private void checkBox3_CheckedChanged(object sender, EventArgs e)
{
checkBox1.Checked = false;
checkBox2.Checked = false;
speed_zeus = 10;
damage_zeus = 400;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
checkBox3.Checked = false;
checkBox2.Checked = false;
speed_zeus = 50;
damage_zeus = 100;
}
private async void Zeus_Attack(int damage)
{
shadow_fiend_hp = shadow_fiend_hp - damage;
this.Invoke(new Action(() => hp.Text = "HP: " + shadow_fiend_hp));
}
private async void ShadowFiend_Attack()
{
zeus_hp = zeus_hp - 200;
this.Invoke(new Action(() => label4.Text = "HP: " + shadow_fiend_hp));
}
private void ResetAll()
=> this.Invoke(new Action(() => hp.Text = "HP: 2800"));
private async void ShadowRaze_Click(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Z:
shock.Location = new Point(_first_shadowrazeX, _first_shadowrazeY);
shock.Visible = true;
this.Update();
Thread.Sleep(100);
shock.Visible = false;
break;
case Keys.X:
shock.Location = new Point(_second_shadowrazeX, _second_shadowrazeY);
shock.Visible = true;
this.Update();
Thread.Sleep(100);
shock.Visible = false;
break;
case Keys.C:
shock.Location = new Point(_third_shadowrazeX, _third_shadowrazeY);
shock.Visible = true;
this.Update();
Thread.Sleep(100);
shock.Visible = false;
break;
}
}
}
}
Here's some pretty simple code to move a picture box around the screen using async and await. It's not based on your code - yours is far from being a Minimal Reproduceable Example. This is.
I dropped a few coptrols my form:
A combo box
Two textboxes (Offset and Period)
Two Buttons (Go and Stop)
A PictureBox (I made this public and gave it an obvious background color
Then I created this enum to state the direction I wanted to move the picture box:
public enum Direction
{
SouthEast,
East,
NorthEast,
North,
NorthWest,
West,
SouthWest,
South,
}
Then I created this worker class:
internal class PictureBoxMover
{
public bool enabled = true;
Direction _direction;
int _offset;
int _period;
Form1 _theForm;
private static Dictionary<Direction, (int deltaX, int deltaY)> _deltaRules = new Dictionary<Direction, (int deltaX, int deltaY)> {
{ Direction.North, (0, -1) },
{ Direction.South, (0, 1) },
{ Direction.East, (1, 0) },
{ Direction.West, (-1, 0) },
{ Direction.NorthEast, (1, -1) },
{ Direction.NorthWest, (-1, -1) },
{ Direction.SouthEast, (1, 1) },
{ Direction.SouthWest, (-1, 1) },
};
public PictureBoxMover (Form1 parentForm, Direction direction, int offset, int period)
{
_theForm = parentForm;
_direction=direction;
_offset=offset;
_period=period;
}
public void Disable()
{
enabled = false;
}
public async Task Run()
{
var directionRule = _deltaRules[_direction];
var offsetXY = (directionRule.deltaX * _offset, directionRule.deltaY * _offset);
while (enabled)
{
_theForm.pictureBox1.Location = new Point(_theForm.pictureBox1.Location.X + offsetXY.Item1, _theForm.pictureBox1.Location.Y + offsetXY.Item2);
await Task.Delay(_period);
}
}
}
The static _deltaRules dictionary makes sense of the Directions. The ( 1, -1 ) denotes a tuple of two integers (i.e., _deltaRules is a dictionary with a Direction as key and a two integer tuple as value
The main reason for instance of this class is to allow them to be easily cancellable (/disablable).
In the form's constructor, I bind the Direction dropdown combobox to the possible values of Direction:
DirectionDropDown.DataSource = Enum.GetNames<Direction>();
The rest of the form's class looks like this:
private PictureBoxMover? _currentPictureBoxMover = null;
private async void GoBtn_Click(object sender, EventArgs e)
{
if (Enum.TryParse<Direction>(DirectionDropDown.SelectedItem.ToString(), out var direction) &&
int.TryParse(OffsetTxt.Text, out var offset) &&
int.TryParse(PeriodTxt.Text, out var period))
{
if (_currentPictureBoxMover != null)
{
_currentPictureBoxMover.Disable();
}
_currentPictureBoxMover = new PictureBoxMover(this, direction, offset, period);
await _currentPictureBoxMover.Run();
}
}
private void StopBtn_Click(object sender, EventArgs e)
{
if (_currentPictureBoxMover != null)
{
_currentPictureBoxMover.Disable();
}
_currentPictureBoxMover = null;
}
I keep track of the _currentPictureBoxMover so that I can disable it when I start moving in a new direction. Otherwise the code is pretty self-explanatory.
Note that because everything is done with async and await, I have no threading issues, and no timers to worry about.
One thing to note: part of the reason for having the period/offset controls is to show (and prove to myself) that the form is fully functional while things are moving around
Related
This question already has an answer here:
Interaction between forms — How to change a control of a form from another form?
(1 answer)
Closed 6 years ago.
On one Form, the Quiz form, I have an integer score which keeps track of the user's score. On another Form, the Game Over form, I need to print out the score of the user, but even after hours of me attempting to do so, I still can't manage to do it. I know my code could be improved by A LOT but I just need help to solve this problem and would appreciate it. I just started out on C# and I just wanted to experiment on things.
namespace Quiz_Application
{
public partial class Quiz : Form
{
static Random gen = new Random();
int[] rand = Enumerable.Range(1, 5).OrderBy(q => gen.Next()).ToArray();
int i = 0;
int score = 0;
int[] goArray = new int[1];
public void Question1()
{
questionText.Text = "What is the capital city of Spain?";
optionA.Text = "Barcelona";
optionB.Text = "Madrid";
optionC.Text = "Seville";
optionD.Text = "Zarazoga";
}
public void Question2()
{
questionText.Text = "What is the biggest island on Earth?";
optionA.Text = "Luzon";
optionB.Text = "Singapore";
optionC.Text = "Greenland";
optionD.Text = "Hawaii";
}
public void Question3()
{
questionText.Text = "What is the world's longest river?";
optionA.Text = "Nile";
optionB.Text = "Amazon";
optionC.Text = "Mississipi";
optionD.Text = "Congo";
}
public void Question4()
{
questionText.Text = "Which country is Prague in?";
optionA.Text = "Czech Republic";
optionB.Text = "Slovakia";
optionC.Text = "Austria";
optionD.Text = "Poland";
}
public void Question5()
{
questionText.Text = "What is the diameter of Earth?";
optionA.Text = "6,779km";
optionB.Text = "3,474km";
optionC.Text = "12,742km";
optionD.Text = "8,721km";
}
static void Wait(double sec)
{
Task.Delay(TimeSpan.FromSeconds(sec)).Wait();
}
public Quiz()
{
InitializeComponent();
}
private void Quiz_Load(object sender, EventArgs e)
{
}
public void label1_Click(object sender, EventArgs e)
{
scoreNum.ResetText();
score = 0;
int goScore = goArray[0];
this.Hide();
Form1 f1 = new Form1();
f1.ShowDialog();
this.Close();
}
private void optionClick(object sender, EventArgs e)
{
startButton.Enabled = false;
Button l = (Button)sender;
int[] goArray = new int[1];
goArray[0] = score;
if (l.Text == "Madrid" || l.Text == "Greenland" || l.Text == "Amazon" || l.Text == "Czech Republic" || l.Text == "12,742km")
{
score++;
scoreNum.Text = score.ToString();
correctOrWrong.Image = Resources.correct; Wait(1); correctOrWrong.Image = null;
}
else
{
correctOrWrong.Image = Resources.wrong; Wait(1); correctOrWrong.Image = null;
}
l.BackColor = System.Drawing.Color.Maroon;
optionA.Enabled = false; optionB.Enabled = false; optionC.Enabled = false; optionD.Enabled = false;
startButton.Enabled = true;
}
private void startButton_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
optionA.Enabled = true; optionB.Enabled = true; optionC.Enabled = true; optionD.Enabled = true;
if (i == 5)
{
scoreNum.ResetText();
score = 0;
int goScore = goArray[0];
b.Text = "Finish";
this.Hide();
Game_Over go = new Game_Over();
go.ShowDialog();
this.Close();
}
try
{
switch (rand[i])
{
case 1:
Question1();
i++;
break;
case 2:
Question2();
i++;
break;
case 3:
Question3();
i++;
break;
case 4:
Question4();
i++;
break;
case 5:
Question5();
i++;
break;
case 6:
Wait(2);
this.Hide();
Game_Over go = new Game_Over();
go.ShowDialog();
this.Close();
break;
}
if (i == 5)
{
b.Text = "Finish";
}
}
catch { }
if (i != 5)
b.Text = "Next";
b.Enabled = false;
}
private void mouseEnter(object sender, EventArgs e)
{
this.Cursor = Cursors.Hand;
}
private void mouseLeave(object sender, EventArgs e)
{
this.Cursor = Cursors.Default;
}
public int get(int i)
{
return i;
}
}
and my Game Over form
namespace Quiz_Application
{
public partial class Game_Over : Form
{
public Game_Over()
{
InitializeComponent();
}
private void Game_Over_Load(object sender, EventArgs e)
{
Quiz q = new Quiz();
}
private void playAgain_Click(object sender, EventArgs e)
{
Quiz q = new Quiz();
this.Hide();
q.ShowDialog();
this.Close();
}
private void mainMenu_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
this.Hide();
f1.ShowDialog();
this.Close();
}
}
Create a public class and store the value in it, you can access the value across the code.
class Globals
{
public static int Score = 0;
}
// In the window you can assign value for the variable like below
Globals.Score=<Your score>;
In the Game_Over form, add a label to display the score if you haven't done so already. I will call it myScoreLabel Then, when you show the form i.e. here:
case 6:
Wait(2);
this.Hide();
Game_Over go = new Game_Over();
go.ShowDialog();
this.Close();
break;
add this line before go.ShowDialog:
go.yourScoreLabel.Text = "Score: " + score.ToString();
I'm having problems with playing sound using System.Windows.Media.MediaPlayer, what is weird is how it works the first time around, however on the second time it throws an exception with the message of The calling thread cannot access this object because a different thread owns it.
This is my code below, look at m_BackgroundWorker_DoWork specifically which is where it actually plays the sound where the sound file location is different to the last stored one:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
using System.Timers;
using System.Media;
namespace RPGInventor
{
public partial class GameMapPanel : UserControl
{
protected Point m_Size;
protected bool m_bGrid;
protected CMap m_Map;
protected System.Timers.Timer m_Timer;
//protected SoundPlayer m_SoundPlayer;
protected System.Windows.Media.MediaPlayer m_SoundPlayer;
protected string m_szLastMedia;
protected bool m_bRepeatBGS;
public GameMapPanel()
{
InitializeComponent();
this.Width = 0;
this.Height = 0;
m_Size = new Point(0, 0);
m_Timer = new System.Timers.Timer(1000 / 60);
m_Timer.Elapsed += m_Timer_Elapsed;
//m_SoundPlayer = new SoundPlayer();
m_SoundPlayer = new System.Windows.Media.MediaPlayer();
m_szLastMedia = "";
}
void m_Timer_Elapsed(object sender, ElapsedEventArgs e)
{
Invalidate();
}
public void setupGrid(int nCols, int nRows)
{
this.Width = nCols * 32;
this.Height = nRows * 32;
m_Size = new Point(nCols, nRows);
m_Map.setGridSize(nCols, nRows);
GameDialog parent = (GameDialog)this.Parent;
parent.updateScrollBars();
}
public void setMap(CMap map)
{
this.m_Map = map;
MainForm mf = (MainForm)CUtil.findForm("RPG Inventor");
//m_BackgroundWorker.RunWorkerAsync();
m_BackgroundWorker_DoWork(null, null);
for (int i = 0; i < getMap().getEvents().Count; ++i)
{
CEvent cevent = (CEvent)getMap().getEvents()[i];
if (cevent.getType() == (int)CEvent.EventType.TRANSFER)
{
CTransferEvent transferEvent = (CTransferEvent)cevent;
if (CResources.getLoadedMap(transferEvent.getMapName()) == null)
{
CMap temp = new CMap("", 0, 0);
CMap Loadmap = temp.retrieve(mf.m_Database, transferEvent.getMapName());
CResources.addLoadedMap(Loadmap);
}
CLayer layer = (CLayer)getMap().getMapLayers()[1];
CTransferObject transferObj = new CTransferObject(transferEvent);
transferObj.setLocation(new Point(transferEvent.getGridLoc().X * 32,
transferEvent.getGridLoc().Y * 32));
layer.addObject(transferObj, 2);
}
if (cevent.getType() == (int)CEvent.EventType.DOOR)
{
CDoorEvent doorEvent = (CDoorEvent)cevent;
if (CResources.getLoadedMap(doorEvent.getMapName()) == null)
{
CMap temp = new CMap("", 0, 0);
CMap Loadmap = temp.retrieve(mf.m_Database, doorEvent.getMapName());
CResources.addLoadedMap(Loadmap);
}
CLayer layer = (CLayer)getMap().getMapLayers()[1];
CDoorObject doorObj = new CDoorObject(doorEvent);
int nH = doorObj.getHeight();
int nDiff = nH - 32;
int nY = (doorEvent.getGridLoc().Y * 32) - nDiff;
doorObj.setLocation(new Point(doorEvent.getGridLoc().X * 32, nY));
layer.addObject(doorObj, 2);
}
}
}
public CMap getMap()
{
return this.m_Map;
}
public void addCharacterSet(CCharacterSet charSet)
{
CSpriteObject spriteObj = new CSpriteObject();
spriteObj.loadImage(charSet.CharGraphic);
spriteObj.setAnimations(charSet.CharSize.Y, charSet.CharSize.X);
spriteObj.setCharSet(charSet);
spriteObj.setVisible(true);
//spriteObj.setListener(this);
for (int i=0; i<m_Map.getEvents().Count; ++i)
{
CEvent cevent = (CEvent) m_Map.getEvents()[i];
if (cevent.getType() == (int)CEvent.EventType.PLAYER_START)
{
int nSpaceY = 32; int nDifference = spriteObj.getHeight() - nSpaceY;
spriteObj.setLocation(new Point(cevent.getGridLoc().X * 32,
(cevent.getGridLoc().Y * 32) - nDifference));
}
}
CLayer layer = (CLayer)m_Map.getMapLayers()[1];
layer.addObject(spriteObj, 2);
}
public void addCharacterSet(CCharacterSet charSet, Point ptGrid, int nDir)
{
GameDialog gd = (GameDialog)this.Parent;
MainForm mf = (MainForm)gd.Owner;
CSpriteObject spriteObj = new CSpriteObject();
spriteObj.loadImage(charSet.CharGraphic);
spriteObj.setAnimations(charSet.CharSize.Y, charSet.CharSize.X);
spriteObj.setCharSet(charSet);
spriteObj.setVisible(true);
spriteObj.setLocation(new Point(ptGrid.X * 32, ptGrid.Y * 32));
spriteObj.setDirection(nDir);
spriteObj.setCurrentAnim(nDir);
//spriteObj.setListener(this);
CLayer layer = (CLayer)m_Map.getMapLayers()[1];
layer.addObject(spriteObj, 2);
}
public void Closed()
{
m_SoundPlayer.Stop();
m_SoundPlayer.Close();
}
private void GameMapPanel_Load(object sender, EventArgs e)
{
//this.Height = 0;
//this.Width = 0;
GameDialog holder = (GameDialog)this.Parent;
holder.updateScrollBars();
m_Timer.Start();
}
private void GameMapPanel_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
//create back buffer
Bitmap backBuffer = new Bitmap(Width, Height);
Graphics backG = Graphics.FromImage(backBuffer);
if (m_Map != null)
{
ArrayList mapLayers = m_Map.getMapLayers();
for (int i = 0; i < mapLayers.Count; ++i)
{
CLayer layer = (CLayer)mapLayers[i];
layer.DrawLayer(backG);
}
}
g.DrawImage(backBuffer, new Point(0, 0));
}
private void GameMapPanel_MouseEnter(object sender, EventArgs e)
{
this.Focus();
}
private void GameMapPanel_KeyDown(object sender, KeyEventArgs e)
{
//get CharSet
GameDialog gd = (GameDialog)this.Parent;
MainForm mf = (MainForm)gd.Owner;
CSpriteObject player = new CSpriteObject();
CCharacterSet dbCharSet = (CCharacterSet)mf.m_Database.m_Characters[0];
ArrayList list = m_Map.getMapLayers();
CLayer layer = (CLayer)list[1];
for (int i = 0; i < layer.getObjects().Count; i++)
{
CMapObject mapObj = layer.getObject(i);
if (mapObj.getType() == (int)CMapObject.MapObjectType.SPRITE)
{
CSpriteObject sprite = (CSpriteObject)mapObj;
if (sprite.getCharSet().Name.Equals(dbCharSet.Name))
{
player = sprite;
}
}
}
if (e.KeyCode == Keys.Down)
{
player.setDirection((int)CSpriteObject.Direction.DOWN);
player.startTimer();
}
if (e.KeyCode == Keys.Up)
{
player.setDirection((int)CSpriteObject.Direction.UP);
player.startTimer();
}
if (e.KeyCode == Keys.Left)
{
player.setDirection((int)CSpriteObject.Direction.LEFT);
player.startTimer();
}
if (e.KeyCode == Keys.Right)
{
player.setDirection((int)CSpriteObject.Direction.RIGHT);
player.startTimer();
}
}
private void GameMapPanel_KeyUp(object sender, KeyEventArgs e)
{
//get CharSet
GameDialog gd = (GameDialog)this.Parent;
MainForm mf = (MainForm)gd.Owner;
CSpriteObject player = new CSpriteObject();
CCharacterSet dbCharSet = (CCharacterSet)mf.m_Database.m_Characters[0];
ArrayList list = m_Map.getMapLayers();
CLayer layer = (CLayer)list[1];
for (int i = 0; i < layer.getObjects().Count; i++)
{
CMapObject mapObj = layer.getObject(i);
if (mapObj.getType() == (int)CMapObject.MapObjectType.SPRITE)
{
CSpriteObject sprite = (CSpriteObject)mapObj;
if (sprite.getCharSet().Name.Equals(dbCharSet.Name))
{
player = sprite;
}
}
}
if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up || e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
{
player.stopTimer();
}
}
private void GameMapPanel_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Down:
case Keys.Up:
case Keys.Left:
case Keys.Right:
e.IsInputKey = true;
break;
}
}
private void m_BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
MainForm mf = (MainForm)CUtil.findForm("RPG Inventor");
if (this.getMap().getSoundDir() != null && this.getMap().getSoundDir() != ""
&& this.getMap().getSoundName() != null && this.getMap().getSoundName() != "")
{
String szPath = ".\\Projects\\" + mf.m_Database.m_Name + "\\Audio\\" +
this.getMap().getSoundDir() + "\\" + this.getMap().getSoundName();
string szSoundPlayerPath = m_szLastMedia;
if (!szSoundPlayerPath.Equals(szPath))
{
try
{
m_SoundPlayer.Stop();
m_SoundPlayer.Open(new Uri(szPath, UriKind.Relative));
m_SoundPlayer.Play();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//m_SoundPlayer.Stop();
//m_SoundPlayer.SoundLocation = szPath;
//m_SoundPlayer.PlayLooping();
}
}
}
}
}
In WinForms, controls created in one thread cannot be accessed from any other thread. So you need to run the code on the main thread using Invoke.
Try this:
if (!szSoundPlayerPath.Equals(szPath))
{
try
{
this.Invoke((MethodInvoker)delegate
{
m_SoundPlayer.Stop();
m_SoundPlayer.Open(new Uri(szPath, UriKind.Relative));
m_SoundPlayer.Play();
});
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
I'm not 100% sure if the above three lines are what's causing the exception, but you just need to wrap whatever lines of code are causing the error in the Invoke statement.
When using a WPF element inside a different Thread than the UI thread you need to invoke using the Dispatcher.Invoke if you want a synchronous call, but if you can it is prefered to use Dispatcher.BeginInvoke.
Change your code with:
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
m_SoundPlayer.Stop();
m_SoundPlayer.Open(new Uri(szPath, UriKind.Relative));
m_SoundPlayer.Play();
}));
Thank you so much for your input, this is what I have come up with as a result and it works
if (InvokeRequired)
{
this.BeginInvoke(new Action(() =>
{
m_SoundPlayer.Stop();
m_SoundPlayer.Open(new Uri(szPath, UriKind.Relative));
m_SoundPlayer.Play();
}));
}
else
{
m_SoundPlayer.Stop();
m_SoundPlayer.Open(new Uri(szPath, UriKind.Relative));
m_SoundPlayer.Play();
}
I have this code:
public void globalPbsMouseEnterEvent(object sender, System.EventArgs e)
{
if (e.Button == MouseButtons.Middle)
{
MessageBox.Show("hi");
}
PictureBox p = sender as PictureBox;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
if (file_array != null)
{
if (file_array.Length > 0)
{
for (int i = 0; i < file_array.Length; i++)
{
if (p == pbs[i])
pb.Animate(file_array[i]);
}
}
}
pb.Visible = true;
pb.BringToFront();
leave = true;
}
But e.Button not exist Button not exist as property for e
This is the code in the constructor of form1 where i make the instance for the global enter event. The variable pbs is is array of AnimatedPictureBoxs:
pbs = new AnimatedPictureBox.AnimatedPictureBoxs[8];
progressbars = new ProgressBar[8];
for (int i = 0; i < pbs.Length; i++)
{
progressbars[i] = new ProgressBar();
progressbars[i].Size = new Size(100, 10);
progressbars[i].Margin = new Padding(0, 0, 0, 70);
progressbars[i].Dock = DockStyle.Top;
pbs[i] = new AnimatedPictureBox.AnimatedPictureBoxs();
pbs[i].MouseEnter += globalPbsMouseEnterEvent;
pbs[i].MouseLeave += globalPbsMouseLeaveEvent;
pbs[i].Tag = "PB" + i.ToString();
pbs[i].Size = new Size(100, 100);
pbs[i].Margin = new Padding(0, 0, 0, 60);
pbs[i].Dock = DockStyle.Top;
pbs[i].SizeMode = PictureBoxSizeMode.StretchImage;
Panel p = i < 4 ? panel1 : panel2;
p.Controls.Add(pbs[i]);
p.Controls.Add(progressbars[i]);
pbs[i].BringToFront();
progressbars[i].BringToFront();
}
This is the code in the class AnimatedPictureBox:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DannyGeneral;
namespace WeatherMaps
{
class AnimatedPictureBox
{
//Use this custom PictureBox for convenience
public class AnimatedPictureBoxs : PictureBox
{
public static bool images;
List<string> imageFilenames;
Timer t = new Timer();
public AnimatedPictureBoxs()
{
images = false;
AnimationInterval = 10; //It's up to you, the smaller, the faster.
t.Tick += Tick_Animate;
}
public int AnimationInterval
{
get { return t.Interval; }
set { t.Interval = value; }
}
public void Animate(List<string> imageFilenames)
{
this.imageFilenames = imageFilenames;
t.Start();
}
public void StopAnimate()
{
t.Stop();
i = 0;
}
int i;
private void Tick_Animate(object sender, EventArgs e)
{
if (images == true)
{
imageFilenames = null;
}
if (imageFilenames == null)
{
return;
}
else
{
try
{
if (i >= imageFilenames.Count)
{
i = 0;
}
else
{
Load(imageFilenames[i]);
i = (i + 1) % imageFilenames.Count;
}
}
catch (Exception err)
{
Logger.Write(err.ToString());
}
}
}
}
}
}
What i want to do is when the user click on the middle mouse button it will pause the animation and when he click again on the middle button of the mouse the animation will continue.
But in the globalenter event e dosent have the Button property.
In your code, specifically here
public void globalPbsMouseEnterEvent(object sender, System.EventArgs e)
{
if (e.Button == MouseButtons.Middle)
{
MessageBox.Show("hi");
}
....................
}
You can't do it on MouseEnter actually need to use MouseDown, MouseWheel [for example] to have MouseEventArgs
public void globalPb_MouseDown(object sender, MouseEventArgs e)
{
if (e.MiddleButton = MouseButtonState.Pressed)
{
MessageBox.Show("hi");
}
....................
}
I'm making a little game in C#
When the score is 100, I want two labels to display for one second, then they need to be invisible again.
At the moment I have in Form1:
void startTimer(){
if (snakeScoreLabel.Text == "100"){
timerWIN.Start();
}
}
private void timerWIN_Tick(object sender, EventArgs e)
{
int timerTick = 1;
if (timerTick == 1)
{
lblWin1.Visible=true;
lblWin2.Visible=true;
}
else if (timerTick == 10)
{
lblWin1.Visible = false;
lblWin2.Visible = false;
timerWIN.Stop();
}
timerTick++;
}
The timer's interval is 1000ms.
Problem = labels aren't showing at all
Timers are pretty new to me, so I'm stuck here :/
Try this :
void startTimer()
{
if (snakeScoreLabel.Text == "100")
{
System.Timers.Timer timer = new System.Timers.Timer(1000) { Enabled = true };
timer.Elapsed += (sender, args) =>
{
lblWin1.Visible=true;
timer.Dispose();
};
}
}
Try multithreaded System.Threading.Timer :
public int TimerTick = 0;
private System.Threading.Timer _timer;
public void StartTimer()
{
label1.Visible = true;
label2.Visible = true;
_timer = new System.Threading.Timer(x =>
{
if (TimerTick == 10)
{
Invoke((Action) (() =>
{
label1.Visible = false;
label2.Visible = false;
}));
_timer.Dispose();
TimerTick = 0;
}
else
{
TimerTick++;
}
}, null, 0, 1000);
}
I want to create a timer in a separate thread, but I'm not sure how to do it.
The timer should stop after clicking button a button.
Below I have an example that mostly works but it stops sometimes for 1-2 seconds when the loop is executing. So I guess I have to put it in a separate thread? This is what I've tried:
private void buttonStop_Click(object sender, EventArgs e)
{
timer1.Stop();
}
public void TimeThread()
{
th = new Thread(new ThreadStart(Timer));
th.Start();
}
public void Timer()
{
var delta = DateTime.Now - startTime;
textBoxSeconds.Text = delta.Seconds.ToString("n0");
textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
}
EDIT:
So here is all the code that I have, still not exactly sure how to put the timer in separate thread.
namespace Imgur
{
public partial class Form1 : Form
{
bool flag = true;
int downloadedNumber = 0;
private DateTime startTime;
public Form1()
{
InitializeComponent();
}
public void buttonStart_Click(object sender, EventArgs e)
{
buttonStart.Enabled = false;
buttonStop.Enabled = true;
if (!flag)
{
flag = true;
}
startTime = DateTime.Now;
timer1.Start();
for (int i=0;i<100000 && flag;i++)
{
WebClient webClient = new WebClient();
string pic1 = rnd_str(5);
string pic2 = ".jpg";
string picture = pic1 + pic2;
//********** GETTING SIZE OF IMAGE ***********
Size sz = GetSize("http://i.imgur.com/" + picture);
string imageSize = (sz.Width.ToString() + " " + sz.Height.ToString()); ;
//********************************************
if(imageSize != "161 81")
{
webClient.DownloadFile("http://i.imgur.com/" + picture, #"e:\test\" + picture);
richTextBox1.Text += String.Format("Downloaded picture: {0}\r\n", picture);
downloadedNumber++;
textBoxDownloadedNumber.Text = string.Format("{0}", downloadedNumber);
}
webClient.Dispose();
Application.DoEvents();
if (i == 999995)
{
flag = false;
}
}
richTextBox1.Text += "End Dowloaded Session \n";
buttonStart.Enabled = true;
buttonStop.Enabled = false;
timer1.Stop();
}
public static Size GetSize(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.Accept = "image/gif";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream s = response.GetResponseStream();
Bitmap bmp = new Bitmap(s);
Size sz = new Size(bmp.Width, bmp.Height);
return sz;
}
public static string rnd_str(int liczba_liter)
{
Random r = new Random();
int char_type;
string return_string = "";
int i =0;
for (i = 0; i < liczba_liter; i++)
{
if (r.Next(1, 3) == 1)
{
char_type = r.Next(1, 4);
switch (char_type)
{
case 1:
return_string += (char)r.Next(48, 58); // convertion int -> ASCII character; 48-57 are ASCII digits
break;
case 2:
return_string += (char)r.Next(97, 123); // convertion int -> ASCII character; as above but small letters
break;
case 3:
return_string += (char)r.Next(65, 91); // as above; large letters
break;
default:
i -= 1;
break;//do not add any letter if no type is allowed
}
}
else
{
i -= 1;
return_string += "";
}
}
return return_string;
}
private void buttonStop_Click(object sender, EventArgs e)
{
flag = false;
buttonStart.Enabled = true;
timer1.Stop();
}
public void timer1_Tick(object sender, EventArgs e)
{
var delta = DateTime.Now - startTime;
textBoxSeconds.Text = delta.Seconds.ToString("n0");
textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
}
}
}
In your code it seems there is no connection between the timer and the print of the time passed.
You need to pay attention because it isn't possible to change GUI elements from another thread that isn't the main one.
To do this you need to use Invoke in WinForms
if (control.InvokeRequired)
{
control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
}
else
{
control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
}
or dispatcher in WPF/SL - http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher
In order to use another thread and you have some options:
Threadpool (On .Net 4) - http://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx
Thread class - http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
BackgroundWorker Class - http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
The 3rd option is the easiest if you don't know how to work with theards
There're tree Timers in .Net take a look at the following article and select correct timer looks like you need timer from System.Threading, not from System.Windows.Forms.