MediaElement not always playing video in WPF application - c#

we created a test application were users interact with it using gestures. Each user gets to interact with all gestures in a sequential manner. When the users first is introduced to a new gesture, a small instructional movie is played for the user showing him how to perform that gesture. The movie should first play on the main screen, and then after playing once should loop on the second monitor until the next gesture starts, when it should then close the secondary video screen and start the process over. This is where we are running into problems.
The movies all get loaded up fine, and actually most of the time play correctly. The problem is that sometimes, the movie does not actually start in the secondary monitor. They load up fine but never actually start. This is not something we can reliably reproduce, this happens sometimes at random.
This is the code that we have for the VideoPlayer window at the moment:
public partial class VideoWindow : Window {
static VideoWindow currentVideoWindow;
public VideoWindow(GestureDirection direction, GestureType type, bool reopen = false)
{
if(currentVideoWindow != null) {
currentVideoWindow.CloseWindow();
currentVideoWindow = this;
}
else {
currentVideoWindow = this;
}
GestureParser.Pause(!reopen);
InitializeComponent();
this.Title = type + " " + direction;
this.Show();
videoMediaElement.LoadedBehavior = MediaState.Manual;
videoMediaElement.UnloadedBehavior = MediaState.Manual;
string videoDirectory = #"techniques/";
string video = direction.ToString() + "_" + type.ToString() + ".mp4";
if (Screen.AllScreens.Length > 1) {
int secScreen = Screen.AllScreens.Length == 2 ? 0 : 2;
int mainScreen = Screen.AllScreens.Length == 2 ? 1 : 0;
Screen s = reopen ? Screen.AllScreens[secScreen] : Screen.AllScreens[mainScreen];
System.Drawing.Rectangle r = s.WorkingArea;
this.Top = r.Top;
this.Left = r.Left;
this.Topmost = true;
this.Show();
this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
}
else {
Screen s = Screen.AllScreens[0];
System.Drawing.Rectangle r = s.WorkingArea;
this.Top = r.Top;
this.Left = r.Left;
this.Show();
}
String videoPath = CreateAbsolutePathTo(videoDirectory + video);
if (File.Exists(videoPath)) {
Uri videoUri = new Uri(videoPath, UriKind.Relative);
videoMediaElement.Source = videoUri;
}
if (reopen) {
this.Activate();
canvasWindow.Activate();
videoMediaElement.MediaEnded += (sender, args) => {
videoMediaElement.Stop();
videoMediaElement.Position = TimeSpan.Zero;
};
} else {
videoMediaElement.MediaEnded += (sender, args) => {
this.CloseWindow();
var t = new VideoWindow(direction, type, true);
};
}
videoMediaElement.Play();
Task task = Task.Factory.StartNew(() =>
{
while(GetMediaState(videoMediaElement) != MediaState.Play)
{
videoMediaElement.Play();
}
});
}
private MediaState GetMediaState(MediaElement myMedia)
{
FieldInfo hlp = typeof(MediaElement).GetField("_helper", BindingFlags.NonPublic | BindingFlags.Instance);
object helperObject = hlp.GetValue(myMedia);
FieldInfo stateField = helperObject.GetType().GetField("_currentState", BindingFlags.NonPublic | BindingFlags.Instance);
MediaState state = (MediaState)stateField.GetValue(helperObject);
return state;
}
static CanvasWindow canvasWindow;
public static void SetCanvasWindow(CanvasWindow window) {
canvasWindow = window;
}
private static string CreateAbsolutePathTo(string mediaFile) {
return Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName, mediaFile);
}
private void CloseWindow() {
videoMediaElement.Stop();
videoMediaElement.Close();
this.Close();
}
}
As you can see, we have tried creating a task that constantly checks to see if the video is playing, and if not it should play it. The thing is, the media state is always playing, even if the movie is stopped, and as such it does nothing.
We really don't know what is wrong, and would really appreciate some help.

Related

c# windows forms application Pinning start location when button clicked

I have made a new windows forms application, and I'm trying to use a button to allow the user to save the application startup location when the button is clicked. I have tried to look the problem up, but I can't find anything about using a button to do it.
Here is what I have found so far which saves the location on the screen when the form is closed, I just don't know how to make it only save the location when a button is clicked:
public static void GeometryFromString(string thisWindowGeometry, Form formIn)
{
if (string.IsNullOrEmpty(thisWindowGeometry) == true)
{
return;
}
string[] numbers = thisWindowGeometry.Split('|');
string windowString = numbers[4];
if (windowString == "Normal")
{
Point windowPoint = new Point(int.Parse(numbers[0]),
int.Parse(numbers[1]));
Size windowSize = new Size(int.Parse(numbers[2]),
int.Parse(numbers[3]));
bool locOkay = GeometryIsBizarreLocation(windowPoint, windowSize);
bool sizeOkay = GeometryIsBizarreSize(windowSize);
if (locOkay == true && sizeOkay == true)
{
formIn.Location = windowPoint;
formIn.Size = windowSize;
formIn.StartPosition = FormStartPosition.Manual;
formIn.WindowState = FormWindowState.Normal;
}
else if (sizeOkay == true)
{
formIn.Size = windowSize;
}
}
else if (windowString == "Maximized")
{
formIn.Location = new Point(100, 100);
formIn.StartPosition = FormStartPosition.Manual;
formIn.WindowState = FormWindowState.Maximized;
}
}
private static bool GeometryIsBizarreLocation(Point loc, Size size)
{
bool locOkay;
if (loc.X < 0 || loc.Y < 0)
{
locOkay = false;
}
else if (loc.X + size.Width > Screen.PrimaryScreen.WorkingArea.Width)
{
locOkay = false;
}
else if (loc.Y + size.Height > Screen.PrimaryScreen.WorkingArea.Height)
{
locOkay = false;
}
else
{
locOkay = true;
}
return locOkay;
}
private static bool GeometryIsBizarreSize(Size size)
{
return (size.Height <= Screen.PrimaryScreen.WorkingArea.Height &&
size.Width <= Screen.PrimaryScreen.WorkingArea.Width);
}
public static string GeometryToString(Form mainForm)
{
return mainForm.Location.X.ToString() + "|" +
mainForm.Location.Y.ToString() + "|" +
mainForm.Size.Width.ToString() + "|" +
mainForm.Size.Height.ToString() + "|" +
mainForm.WindowState.ToString();
}
Here's one of many ways to implement a button to save the Location (and optionally Size).
First, Create a Settings resource if one doesn't already exist. Right-click on the Project and select Properties.
Choose the Settings tab and click the link to create the resource.
Make entries for Size and Location:
Add a Click handler for your Save button:
public MainForm()
{
InitializeComponent();
buttonSaveSizeAndPosition.Click += saveSizeAndPosition;
}
private async void saveSizeAndPosition(object sender, EventArgs e)
{
Properties.Settings.Default.Location = Location;
Properties.Settings.Default.Size = Size;
Properties.Settings.Default.Save();
var textB4 = Text;
Text = $"Location = {Location} Size = {Size}";
await Task.Delay(1000);
Text = textB4;
}
Then, when you load the main form check to see whether the Size has moved off of the default value before reloading these properties:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Properties.Settings.Default.Size.Equals(new Size()))
{
Location = Properties.Settings.Default.Location;
Size = Properties.Settings.Default.Size;
}
}

Images slideshow with fade animation

I am writing a theater mode section in music player. The requirements is to loop through a folder containing images of any type(png, jpeg, gif) and show in a picture box with 5 seconds delay for images of type (png,jpeg) and delay time for gif should be the actual gif time duration. Also there should be fade transition between images when switch from one image to another in a single picture box. All need to be done when software is idle lets say for 60 seconds
Problem
Currently the playing song directory has 'img' folder containing 3 png
images and 3 gif. The first attempt to read
Helper.theaterImagesInfo.ToList() works pretty well
foreach (var img in Helper.theaterImagesInfo.ToList())
It starts to display 3 png images with 5 seconds delay and gif images
with the actual gif duration delay. but if i click picturebox to close theaterform as soon as the form is opened again after 60 seconds of idle state of software and loop continue
to iterate again. The default image is shown with
starting 2 png images from 'img' folder the 3rd png is skipped and then 4th gif starts
to play for few seconds not the actual gif duration and continued in wrong order as well as incorrect delay, Seems like while loop is always running in background. therfore it becomes choppy.
Desired Solution
Whenever i play song theaterform should be displayed and start to show images from folder ( in the same sequence and delay) even if the theaterform is opened again after 60 seconds if the song is still playing. Also if there is a way to show fade when changing image in a single picturebox
Code here
Program.cs
internal static class Program
{
public static Timer IdleTimer = new Timer();
readonly static int miliseconds =
Convert.ToInt32(TimeSpan.FromSeconds(60).TotalMilliseconds);
internal static MainForm f = null;
static public TheaterForm tf;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MessageFilter limf = new MessageFilter();
Application.AddMessageFilter(limf);
Application.Idle += new EventHandler(Application_Idle);
IdleTimer.Interval = miliseconds;
IdleTimer.Tick += TimeDone;
IdleTimer.Start();
f = new MainForm();
tf = new TheaterForm();
var app = new MyApplication();
app.Run(Environment.GetCommandLineArgs());
Application.Idle -= new EventHandler(Application_Idle);
}
static private void Application_Idle(Object sender, EventArgs e)
{
if (!IdleTimer.Enabled) // not yet idling?
IdleTimer.Start();
}
static private void TimeDone(object sender, EventArgs e)
{
IdleTimer.Stop();
if (MainForm.waveOut.PlaybackState == PlaybackState.Playing)
{
if (!Helper.IsTheaterOpen)
{
if (Form.ActiveForm == f)
{
Helper.IsTheaterOpen = true;
tf.WindowState = FormWindowState.Maximized;
tf.Bounds = Screen.PrimaryScreen.Bounds;
tf.x = 1;
tf.ShowDialog(f);
}
}
}
else
{
if (!Helper.IsTheaterOpen)
{
if (Form.ActiveForm == f)
{
Helper.IsTheaterOpen = true;
tf.WindowState = FormWindowState.Maximized;
tf.Bounds = Screen.PrimaryScreen.Bounds;
tf.x = 0;
tf.ShowDialog(f);
}
}
}
}
}
public class MyApplication : WindowsFormsApplicationBase
{
protected override void OnCreateMainForm()
{
MainForm = Program.f;
}
protected override void OnCreateSplashScreen()
{
SplashScreen = new SplashForm();
}
}
Helper.cs
internal class Helper
{
public static bool IsTheaterOpen { get; set; }
public struct ImageInfo
{
public bool IsAnimated;
public int durationInMilliseconds;
public Image ImageHere;
}
public static List<ImageInfo> theaterImagesInfo = new List<ImageInfo>(10);
}
MainForm.cs
/*
* Every song directory has one folder named img that contains images and gif relevant
to the song album
*/
private int GetGifDuration(Image img)
{
int delay = 0, this_delay = 0, index = 0;
FrameDimension frameDimension = new FrameDimension(img.FrameDimensionsList[0]);
int frameCount = img.GetFrameCount(frameDimension);
for (int f = 0; f < frameCount; f++)
{
this_delay = BitConverter.ToInt32(img.GetPropertyItem(20736).Value, index) * 10;
delay += (this_delay < 100 ? 100 : this_delay); // Minimum delay is 100 ms
index += 4;
}
return delay;
}
private void PlayAudio()
{
// Getting images from folder and storing in struct on every song play
if (Directory.Exists(Path.GetDirectoryName(CurrentPlayingMusicUrl) + "\\img"))
{
var files =
Directory.EnumerateFiles(Path.GetDirectoryName(CurrentPlayingMusicUrl) +
"\\img", "*", SearchOption.AllDirectories).Where(s => s.EndsWith(".png") ||
s.EndsWith(".jpg") || s.EndsWith(".jpeg") || s.EndsWith(".gif"));
Helper.theaterImagesInfo.Clear();
foreach (var imagePath in files.ToArray())
{
using (System.Drawing.Image image = System.Drawing.Image.FromFile(imagePath))
{
if (image.RawFormat.Equals(ImageFormat.Gif))
{
Helper.theaterImagesInfo.Add(new Helper.ImageInfo { IsAnimated = true, durationInMilliseconds = GetGifDuration(image), ImageHere = Image.FromFile(imagePath) });
}
else
{
Helper.theaterImagesInfo.Add(new Helper.ImageInfo { IsAnimated = false, durationInMilliseconds = 5000, ImageHere = Image.FromFile(imagePath) });
}
}
}
}
else
{
Helper.theaterImagesInfo.Clear();
Program.tf.x = 0;
}
}
TheaterForm.cs
public partial class TheaterForm : Form
{
public TheaterForm()
{
InitializeComponent();
SetDefaultImage();
}
/*
* Getting Default image from top(root) directory ex. AllMusic. If no 'img' folder
found in song album directory ex. AllMusic -> Justin Bieber -> (img folder not
exist)song1, song2, song3 etc.
*/
private async void SetDefaultImage()
{
string path = KJ_Player.Properties.Settings.Default["MusicFolder"] + "\\img";
if (Directory.Exists(path))
{
var files = Directory.EnumerateFiles(path, "*",
SearchOption.AllDirectories).Where(s => s.EndsWith(".png") ||
s.EndsWith(".jpg") || s.EndsWith(".jpeg"));
await Task.Run(() =>
{
if(files != null && files.Count()>0)
{
PictureBox1.Image = Image.FromFile(files.FirstOrDefault());
}
});
}
}
public int x=1;
private async void TheaterForm_Shown(object sender, EventArgs e)
{
if (this.PictureBox1.Image == null) SetDefaultImage();
if (Helper.theaterImagesInfo != null && Helper.theaterImagesInfo.Count > 0)
{
while (x == 1)
{
foreach (var img in Helper.theaterImagesInfo.ToList())
{
if (img.IsAnimated)
{
try
{
this.PictureBox1.Image = img.ImageHere;
await Task.Delay(img.durationInMilliseconds);
}
catch { }
}
else
{
try
{
await Task.Delay(img.durationInMilliseconds);
this.PictureBox1.Image = img.ImageHere;
}
catch { }
}
}
}
SetDefaultImage();
}
}
private void PictureBoxTheater_Click(object sender, EventArgs e)
{
this.x = 0;
if (this.PictureBox1.Image != null) this.PictureBox1.Image=null;
Helper.IsTheaterOpen = false;
this.Close();
}
}
Most likely you just need to break out of that foreach loop:
foreach (var img in Helper.theaterImagesInfo.ToList())
{
if (img.IsAnimated)
{
try
{
this.PictureBox1.Image = img.ImageHere;
await Task.Delay(img.durationInMilliseconds);
}
catch { }
}
else
{
try
{
await Task.Delay(img.durationInMilliseconds);
if (this.x == 1) {
this.PictureBox1.Image = img.ImageHere;
}
}
catch { }
}
if (this.x == 0) {
break; // exit the for loop early
}
}

How can I make my notification windows more toast like?

I am making a notification system for my Package Tracker app... I need to know how can I make this toast style more efficient than what I have now...
Things I'm looking to accomplish:
when multiple notifications are shown have them docked from top to
bottom on right of screen (looking for a better solution) <<< DONE!
when 1 notification closes moves all notifications below it up... <<< DONE!
Sticky Notifications Enabled when computer is idle. <<< DONE!
if a Notification Exists for a particular item it is replaced rather than
creating a new notification. <<< DONE!
To show a notification I use:
#region Check if Notification Exists
foreach (Form f in ActiveNotifications)
{
string[] windowID = f.Text.Split('|');
if (windowID[1] == NotificationTrackingNumber)
{
NotificationFound = true;
f.Text = "Description=" + NotificationDescription;
f.Text = "Status=" + NotificationStatus;
}
}
#endregion Check if Notification Exists
if (NotificationFound)
{
NotificationFound = false;
}
else if (!NotificationFound)
{
notification = new Notification(NotificationDescription, NotificationStatus, NotificationTrackingNumber, min, sec, WindowID);
notification.Closed += new EventHandler(Notification_Closed);
notification.Show();
ActiveNotifications.Add(notification);
WindowID++;
}
To position them up and down the right side of the screen I use:
Rectangle res = Screen.PrimaryScreen.Bounds;
this.Location = new Point(res.Width - 5 - Size.Width, (this.Height + 16) * multiplier + 6);
To re-position any Active Notifications that is below the closed notification
public void Notification_Closed(object sender, EventArgs e)
{
WindowID--;
List<Form> TempNotificationList1 = new List<Form>();
List<Form> TempNotificationList2 = new List<Form>();
Point newFormPoint = NotificationSettings.notificaionLocation;
Point oldFormPoint;
int delIndex = -1;
int newWindowID = 0;
int winHandleIndex = 0;
int ClosedNotificationWindowID = NotificationSettings.WindowMultiplier;
#region Deletes Closed Notification Window from ActivateNotifications
while (winHandleIndex < ActiveNotifications.Count)
{
if (ActiveNotifications[winHandleIndex].Handle == NotificationSettings.notificationClosedID)
{
delIndex = winHandleIndex;
break;
}
winHandleIndex++;
}
if (delIndex > -1)
{
ActiveNotifications.RemoveAt(delIndex);
}
#endregion Deletes Closed Notification Window from ActivateNotifications
#region Changes the Location Active Notifications
while (ClosedNotificationWindowID < ActiveNotifications.Count)
{
string[] windowID = ActiveNotifications[ClosedNotificationWindowID].Text.Split('|');
oldFormPoint = ActiveNotifications[ClosedNotificationWindowID].Location;
ActiveNotifications[ClosedNotificationWindowID].Location = newFormPoint;
newFormPoint = oldFormPoint;
TempNotificationList1.Add(ActiveNotifications[ClosedNotificationWindowID]);
ClosedNotificationWindowID++;
}
#endregion Changes the Location Active Notifications
#region Merges ActiveNotifications & TempNotificationList1
foreach (Form f in ActiveNotifications)
{
if (!TempNotificationList1.Contains(f))
{
TempNotificationList2.Add(f);
}
}
foreach (Form f in TempNotificationList1)
{
if (!TempNotificationList2.Contains(f))
{
TempNotificationList2.Add(f);
}
}
#endregion Merges ActiveNotifications & TempNotificationList1
#region Rebuilds Active Notifications List
ActiveNotifications.Clear();
foreach (Form f in TempNotificationList2)
{
string[] windowID = f.Text.Split('|');
f.Text = newWindowID.ToString() + "|" + windowID[1];
ActiveNotifications.Add(f);
newWindowID++;
}
TempNotificationList1 = null;
#endregion Rebuilds Active Notifications List
}
Well, the code works but is there a more efficient way? Multiplier is really just window count... here is a picture of how it's working as of now...

Communication between objects in C# issue

I'm trying to provide communication between two objects that can be best described as turn - based. What I mean by that is that the first object(a Game class) has multiple goals which are specified in a database, and the second object represents a class that is used to play animations from sprite sheets. My goal currently is to show an introductory animation in the Game class(that I have done), show the player his first goal. Then the class expects user input in the form of animation parameters which are then passed as a list to be animated.
Once the animation is complete, I check if the goal is met. If it is met, and it is not the last one, I need to go back to the Game class, show the next goal, play a sort off explanation, then expect user input and this repeats until all goals are satisfied.
This is Windows Phone 8.1 Silverlight.
Here is the code of the Game class(most relevant snippets):
public Game(GamePage gp, int chapterNum)
{
currentClickedCommand = null;
currentClickedSlot = null;
gamePage = gp;
chapterNumber = chapterNum;
isAnimationComplete = false;
//chosenCommands = new string[5];
gamePage.characterRectangle.Visibility = System.Windows.Visibility.Collapsed;
Thread AnimationThread = new Thread(playIntroAnimation);
AnimationThread.Start();
Thread loadingThread = new Thread(loadControls);
loadingThread.Start();
}
These two threads are used to play the animation(animation thread), and the other one waits for a static variable to be set to true to load user input controls. The code:
private void loadControls()
{
while (!InformationObject.isSequenceComplete) { }
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// loadGoals();
showCurrentGoal();
gamePage.CommandGrid.Visibility = System.Windows.Visibility.Visible;
gamePage.SlotGrid.Visibility = System.Windows.Visibility.Visible;
gamePage.mainCanvas.Background = null;
gamePage.characterRectangle.Visibility = Visibility.Collapsed;
loadCommands();
loadSlots();
});
}
This is the method which plays the animation sequence that the user selected:
public void AnimateCurrentAnimationInSequence(Rectangle container) {
AnimationParams currentParams = sequenceToAnimate[currentAnimationInSequence];
DoubleAnimation fadeInAnimation = new DoubleAnimation();
fadeOutAnimation = new DoubleAnimation();
if (sequencePlayerInteractions.Count != 0 && sequencePlayerInteractions != null)
{
PlayerInteraction currentInteraction = sequencePlayerInteractions[CurrentInteraction];
TalkBubble interactionBubble = new TalkBubble(currentInteraction.Value);
interactionBubble.setWidthHeight((int)container.Width, (int)container.Height);
talkBubble = interactionBubble;
onCanvas.Children.Add(talkBubble);
Canvas.SetLeft(talkBubble, Canvas.GetLeft(container) + 30);
Canvas.SetTop(talkBubble, Canvas.GetTop(container) + 30);
}
// ovdje razdvojiti po tipu
if (!currentParams.IsMoveType)
{
ImageBrush imageBrush = new ImageBrush() { Stretch = Stretch.None, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top };
imageBrush.Transform = new CompositeTransform();
imageBrush.ImageSource = currentParams.Sheet;
container = setRectangleProperties(container, currentParams.Width, currentParams.Height, imageBrush);
// Storyboard za animaciju
Storyboard sb = new Storyboard();
if (currentParams.Loop) sb.RepeatBehavior = RepeatBehavior.Forever; // odredjujem da li je na repeat
// Animacija za talk bubble
if (sequencePlayerInteractions.Count != 0 && sequencePlayerInteractions != null)
{
fadeInAnimation.From = 0.0;
fadeInAnimation.To = 1.0;
fadeInAnimation.Completed += new EventHandler(fadeIn_complete);
fadeInAnimation.FillBehavior = FillBehavior.HoldEnd;
Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath(UIElement.OpacityProperty));
Storyboard.SetTarget(fadeInAnimation, talkBubble);
}
// Animacija sheeta preko frameova
int time = 0; // vrijeme kojim odredjujem trajanja frameova
ObjectAnimationUsingKeyFrames frm = createFrames(currentParams.Repetitions, time, currentParams.Width, currentParams.NumberOfFrames); // inicijaliziram frameove animacije sheeta
frm.BeginTime = new TimeSpan(0, 0, 0);
fadeInAnimation.Duration = TimeSpan.FromMilliseconds(400);
Storyboard.SetTarget(frm, container.Fill);
Storyboard.SetTargetProperty(frm, new PropertyPath("(ImageBrush.Transform).(CompositeTransform.TranslateX)"));
sb.Children.Add(frm);
if (sequencePlayerInteractions.Count != 0 && sequencePlayerInteractions != null) sb.Children.Add(fadeInAnimation);
sb.Completed += new EventHandler(animationInSequence_Complete);
sb.Begin();
}
else {
cameFromSequenceAnimate = true;
AnimateMove(container, currentParams.Direction, currentParams.Steps);
}
}
private void animationInSequence_Complete(object sender, EventArgs e)
{
if (!(currentAnimationInSequence + 1 == animationCount))
{
if (sequencePlayerInteractions.Count != 0 && sequencePlayerInteractions != null) { if (!(CurrentInteraction + 1 == interactionCount)) CurrentInteraction++; }
currentAnimationInSequence++;
AnimateCurrentAnimationInSequence(currentContainer);
}
else
{
// Goal satisfaction
if (CurrentCommandIDs != null && CurrentCommandIDs.Count != 0)
{
bool has = true;
List<string> sequenceID = new List<string>();
foreach (AnimationParams ap in sequenceToAnimate) sequenceID.Add(ap.AnimationID);
for (int i = 0; i < CurrentCommandIDs.Count; i++)
{
if (!sequenceID.Contains(CurrentCommandIDs[i])) has = false;
}
if (has) { InformationObject.isCriteriaMet = true;
InformationObject.setCurrentGoal(InformationObject.currentGoal + 1);
}
else InformationObject.isCriteriaMet = false;
}
KidCode.Game.isSequenceComplete = true;
InformationObject.isSequenceComplete = true;
currentAnimationInSequence = 0;
CurrentInteraction = 0;
}
}
Now, after the animation is done, I need to somehow return back to the game class to basically repeat this. I tried using a static class(InformationObject)
to store information about current goals but I wasn't able to utilize it
Thanks for any help!

Create an instance of app for each screen

I want my WinForms application to create an instance of itself for each screen and display on that screen.
I have the following code:
Main form:
class MainForm
{
public MainForm()
{
string[] args = Environment.GetCommandLineArgs();
foreach (string arg in args)
{
if (arg == "TakeOverAllScreens") { TakeOverAllScreens(); }
if (arg.StartsWith("Screen|"))
{
string[] s;
s = arg.Split('|');
int xPos , yPos, screenNum ;
int.TryParse(s[1], out xPos);
int.TryParse(s[2], out yPos);
int.TryParse(s[3], out screenNum);
Screen[] sc;
sc = Screen.AllScreens;
this.Left = sc[screenNum].Bounds.Width;
this.Top = sc[screenNum].Bounds.Height;
this.StartPosition = FormStartPosition.Manual;
}
}
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
}
}
TakeOverAllScreens form:
private void TakeOverAllScreens()
{
int i = 0;
foreach (Screen s in Screen.AllScreens)
{
if (s != Screen.PrimaryScreen)
{
i++;
Process.Start(Application.ExecutablePath, "Screen|" + s.Bounds.X + "|" + s.Bounds.Y+"|" + i);
}
}
}
My application does create a new instance for every screen, however it only displays on my main screen and does not display on the other screens.
This looks suspect:
int.TryParse(s[1], out xPos);
int.TryParse(s[2], out yPos);
int.TryParse(s[3], out screenNum);
Screen[] sc;
sc = Screen.AllScreens;
this.Left = sc[screenNum].Bounds.Width;
this.Top = sc[screenNum].Bounds.Height;
You pass x and y values across on the command line, and then ignore them and use the width and height of the screen to set your x/y values. If all of the screens are the same resolution, and arranged horizontally or vertically, it's likely that all of these windows are positioned below (or to the right of) any visible portions of the screen.
I also can't find any guarantee that Screen.AllScreens will always return the screens in the same order, so the screenNum value may be referencing a different screen.
I'd also prefer to see this code appearing after the call to InitializeComponents rather than before, so you know that any designer set properties will be overridden by your code, rather than vice versa.
So, my code is:
public MainForm()
{
InitializeComponent();
string[] args = Environment.GetCommandLineArgs();
foreach (string arg in args)
{
if (arg == "TakeOverAllScreens") { TakeOverAllScreens(); }
if (arg.StartsWith("Screen|"))
{
string[] s;
s = arg.Split('|');
int xPos, yPos, screenNum;
int.TryParse(s[1], out xPos);
int.TryParse(s[2], out yPos);
this.Left = xPos;
this.Top = yPos;
this.StartPosition = FormStartPosition.Manual;
}
}
}
And:
private void TakeOverAllScreens()
{
foreach (Screen s in Screen.AllScreens)
{
if (s != Screen.PrimaryScreen)
{
Process.Start(Application.ExecutablePath, "Screen|" + s.Bounds.X + "|" + s.Bounds.Y);
}
}
}
Of course, the TryParse calls are pointless and can be replaced by Parse, if you're just going to ignore the return value.

Categories

Resources