Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have C# application for a Food Truck. I have some music playing when customers view the menu. On the menu form I have four tabs. I have the WMPLib code in form load. When the form loads the music begins playing however when I switch to a different tab the music stops. I have debugged but there is nothing there to really see since it runs the lines but just stops when you switch tabs. Any ideas on how to keep the music playing when switching tabs on the main form. I would like it to play continuous not just start again on each tab. Thanks. Here is an image of the form with the tabs.
Here is the form load code:
try
{
WMPLib.WindowsMediaPlayer wplayer = new WMPLib.WindowsMediaPlayer();
wplayer.URL = "runningdownadream.mp3";
wplayer.settings.setMode("loop", true);
wplayer.controls.play();
}
catch (Exception ex)
{
MessageBox.Show("No music. Windows Media Player not installed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
In order to play an MP3 in the background using WMPLib, try the following:
Create a class (name: HelperMp3.cs)
HelperMp3.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AxWMPLib;
using System.Diagnostics;
namespace WmpLibTest
{
public class HelperMp3 : IDisposable
{
public delegate void EventHandlerMediaError(object sender, object pMediaObject);
public delegate void EventHandlerPlayStateChanged(object sender, int newValue);
//events
public event EventHandlerMediaError Mp3MediaError;
public event EventHandlerPlayStateChanged Mp3PlayStateChanged;
public string MP3Filename { get; set; } //fully-qualified MP3 filename
private WMPLib.WindowsMediaPlayer _wplayer = new WMPLib.WindowsMediaPlayer();
public HelperMp3()
{
//subscribe to events (add event handlers)
_wplayer.PlayStateChange += _wplayer_PlayStateChange;
_wplayer.MediaError += _wplayer_MediaError;
}
private void _wplayer_MediaError(object pMediaObject)
{
System.Diagnostics.Debug.WriteLine("Error (MediaError): " + pMediaObject.ToString());
//if subscribed to event, raise event, otherwise throw exception
if (Mp3MediaError != null)
{
//raise event
Mp3MediaError(this, pMediaObject);
}
else
{
throw new Exception("Error (MediaError): " + pMediaObject.ToString());
}
}
private void _wplayer_PlayStateChange(int NewState)
{
//Undefined = 0,
//Stopped = 1,
//Paused = 2,
//Playing = 3,
//ScanForward = 4,
//ScanReverse = 5,
//Buffering = 6,
//Waiting = 7,
//MediaEnded = 8,
//Transitioning = 9,
//Ready = 10,
//Reconnecting = 11,
//Last = 12
if (Mp3PlayStateChanged != null)
{
//raise event
Mp3PlayStateChanged(this, NewState);
}
System.Diagnostics.Debug.WriteLine("_wplayer_PlayStateChange: " + NewState.ToString());
}
public void Dispose()
{
if (_wplayer != null)
{
_wplayer.controls.stop();
//unsubscribe from events (add event handlers)
_wplayer.PlayStateChange -= _wplayer_PlayStateChange;
_wplayer.MediaError -= _wplayer_MediaError;
//release all resources
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(_wplayer);
_wplayer = null;
}
}
public void Start()
{
if (_wplayer != null)
{
_wplayer.controls.play();
}
}
public void Stop()
{
if (_wplayer != null)
{
_wplayer.controls.stop();
}
}
public void PlayMp3()
{
Debug.WriteLine("MP3Filename: " + MP3Filename);
if (String.IsNullOrEmpty(MP3Filename) || !System.IO.File.Exists(MP3Filename))
{
throw new Exception("MP3Filename not specified.");
}
Debug.WriteLine("Playing mp3...");
//set value
_wplayer.URL = MP3Filename;
_wplayer.settings.setMode("loop", true);
_wplayer.controls.play();
}
}
}
In the form (ex: Form1) code, create an instance of the class above:
private HelperMp3 _helperMp3 = new HelperMp3();
Then create a method that starts the music:
private void StartMusic(string mp3Filename)
{
//set property
helperMp3.MP3Filename = mp3Filename;
Task t1 = Task.Run(_helperMp3.PlayMp3);
}
Subscribe to the Load event for the form (ex: Form1_Load) and add the following code:
private void Form1_Load(object sender, EventArgs e)
{
//ToDo: replace with your MP3 filename
StartMusic(#"C:\Temp\Test.mp3");
}
Subscribe to the FormClosed event for the form (ex: Form1_FormClosed) and add the following code:
Form1_FormClosed
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (_helperMp3 != null)
{
_helperMp3.Dispose();
_helperMp3 = null;
}
}
Alternatively, one can use BackgroundWorker. If using BackgroundWorker, in HelperMp3.cs change method PlayMp3 to the following:
public void PlayMp3(System.ComponentModel.BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e)
{
Debug.WriteLine("MP3Filename: " + MP3Filename);
if (String.IsNullOrEmpty(MP3Filename) || !System.IO.File.Exists(MP3Filename))
{
throw new Exception("MP3Filename not specified.");
}
if (worker.CancellationPending || e.Cancel)
{
e.Cancel = true;
}
Debug.WriteLine("Playing mp3...");
//set value
_wplayer.URL = MP3Filename;
_wplayer.settings.setMode("loop", true);
_wplayer.controls.play();
}
Note: If using BackgroundWorker, the BackgroundWorker will complete, but the WMPLib control will still be running.
Related
As the title says I need help writing a program that will connect to PVI and another program(I am not sure if it is possible to establish communication with a program like this that was written by the original machine manufacturer I will provide as much detail as i can if needed on this.) this will then exchange information from the PLC to the program running and allow freezing the frame of this program and taking screenshots of it as well as unfreezing it after.
I will include the code that i have so far which I wrote using a training manual provided from B&R this is just to establish connection to PVI and the automation studio program running on a PLC.
This is an outdated training manual but is the only source of information I have available for this problem. The program i wrote does compile and run it does seem to make something of a connection to a PLC that I have connected to my laptop as well as when running the simulation program without a PLC. However it does not read data from the program as the training manual explains it would read the values of some variables i have made in automation studio.
Also when attempting to click on any of the buttons i made and i will be honest i am not 100% sure what they are even supposed to do it will give me an error (System.NullReferenceException: 'Object reference not set to an instance of an object.' myStructPV was null.).
Which i assume is trying to tell me that the variable that is being used when the button is pushed is null however these variables are part of the PVI services namespace and i am not sure what value you would give them in initialization.
I do apologize if this does not make much sense as i mentioned i am quite new at developing and have not used Visual studio or C# since college way back.
Any advice or help will be appreciated very much thank you.
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 BR.AN.PviServices;
namespace PVITestApp
{
public partial class Form1 : Form
{
public Service myService;
public Cpu myCpu;
public BR.AN.PviServices.Task myTask;
public Variable myVariable;
public Module myModule;
public Variable myVariablePV1;
public Variable myStructPV;
public Form1()
{
InitializeComponent();
// txtStatus.Text = "text box is functioning!";
}
private void MyStructPV_Error(object sender, PviEventArgs e)
{
throw new NotImplementedException();
}
private void MyStructPV_ValueChanged(object sender, VariableEventArgs e)
{
throw new NotImplementedException();
}
private void Form1_Load(object sender, EventArgs e)
{
myService = new Service("service");
myService.Connected += MyService_Connected;
myService.IsStatic = true;
myService.Connect();
}
private void MyService_Connected(object sender, PviEventArgs e)
{
this.txtStatus.Text += "Service Connected\r\n";
if (myCpu == null)
{
myCpu = new Cpu(myService, "cpu");
//myCpu.Connection.DeviceType = BR.AN.PviServices.DeviceType.TcpIp;
myCpu.Connection.DeviceType = DeviceType.TcpIp;
myCpu.Connection.TcpIp.DestinationStation = 2;
myCpu.Connection.TcpIp.DestinationPort = 11160;
myCpu.Connection.TcpIp.DestinationIpAddress = "192.168.0.1";
//myCpu.Connection.TcpIp.DestinationIpAddress = "127.0.0.1";
myCpu.Connected += MyCpu_Connected;
myCpu.Error += MyCpu_Error;
myCpu.Connect(ConnectionType.CreateAndLink);
// maybe need to use this one - myCpu.Connect(ConnectionType.Create);
}
// throw new NotImplementedException();
}
private void MyCpu_Error(object sender, PviEventArgs e)
{
this.txtStatus.Text += e.Name + " Error:" + e.ErrorCode + "\r\n";
// throw new NotImplementedException(txtStatus.Text = "Error connecting.");
}
private void MyCpu_Connected(object sender, PviEventArgs e)
{
this.txtStatus.Text += "CPU Connected\r\n";
myTask = new BR.AN.PviServices.Task(myCpu, "pvitest");
myTask.Connected += MyTask_Connected;
myTask.Error += MyTask_Error;
myTask.Connect();
//throw new NotImplementedException();
}
private void MyTask_Error(object sender, PviEventArgs e)
{
this.txtStatus.Text += e.Name + " Error:" + e.ErrorCode + "\r\n";
//throw new NotImplementedException();
}
private void MyTask_Connected(object sender, PviEventArgs e)
{
this.txtStatus.Text += "Task " + e.Name + " Connected\r\n";
if (myVariable == null)
{
myVariable = new Variable(myTask, "Lifesign");
myVariable.Active = true;
myVariable.RefreshTime = 200;
myVariable.ValueChanged += MyVariable_ValueChanged;
myVariable.Error += MyVariable_Error;
myVariable.Connect();
}
if (myVariablePV1 == null)
{
myVariablePV1 = new Variable(myTask, "VarCreateOnly");
myVariablePV1.Address = "PV1";
myVariablePV1.Connect(ConnectionType.Create);
}
// throw new NotImplementedException();
}
private void MyVariable_Error(object sender, PviEventArgs e)
{
txtStatus.Text += e.Name + " E#" + e.ErrorCode.ToString();
//throw new NotImplementedException();
}
private void MyVariable_ValueChanged(object sender, VariableEventArgs e)
{
if (myStructPV == null) //PG35 stuff may need to move
{
myStructPV = new Variable(myTask, "Pv_Struct");
myStructPV.Active = true;
myStructPV.RefreshTime = 1000;
myStructPV.ValueChanged += MyStructPV_ValueChanged;
myStructPV.Error += MyStructPV_Error;
myStructPV.Connect();
}
// /\ above may need to be moved back.
if (e.Name == "Lifesign")
{
lblValLifesign.Text = ((Variable)sender).Value.ToString();
}
if (e.Name == "linkVarPV1")
{
lblPV1.Text = ((Variable)sender).Value.ToString();
}
Variable tmpVar = (Variable)sender; //PG 36 - 37
if(e.Name == "Pv_Struct")
{
if (tmpVar.Value.DataType == DataType.Structure)
{
foreach (Variable member in tmpVar.Members.Values)
{
txtStatus.Text += member.Value.ToString() + "\r\n";
}
}
}
foreach (String membername in e.ChangedMembers)
{
if (membername != null)
{
txtStatus.Text += tmpVar.Value[membername].ToString() + "\r\n";
}
}
//throw new NotImplementedException();
}
private void CmdConnectPV1_Click(object sender, EventArgs e)
{
Variable myLinkPV1 = new Variable(myVariable, "linkVarPV1");
myLinkPV1.LinkName = myVariablePV1.FullName;
myLinkPV1.Active = true;
myLinkPV1.ValueChanged += MyLinkPV1_ValueChanged;
myLinkPV1.Error += MyLinkPV1_Error;
myLinkPV1.Connect(ConnectionType.Link);
}
private void MyLinkPV1_Error(object sender, PviEventArgs e)
{
//throw new NotImplementedException();
}
private void MyLinkPV1_ValueChanged(object sender, VariableEventArgs e)
{
// throw new NotImplementedException();
}
private void CmdReadVar_Click(object sender, EventArgs e)
{
myVariable.ValueRead += MyVariable_ValueRead;
myVariable.ReadValue();
}
private void MyVariable_ValueRead(object sender, PviEventArgs e)
{
this.lblReadVar.Text = ((Variable)sender).Value.ToString();
//throw new NotImplementedException();
}
private void CmdReadTime_Click(object sender, EventArgs e)
{
myCpu.DateTimeRead += MyCpu_DateTimeRead;
myCpu.ReadDateTime();
}
private void MyCpu_DateTimeRead(object sender, CpuEventArgs e)
{
DateTime dt;
dt = e.DateTime;
this.Text = dt.ToString();
//throw new NotImplementedException();
}
private void CmdWriteVal_Click(object sender, EventArgs e)
{
myVariable.Value = 0;
myVariable.ValueWritten += MyVariable_ValueWritten;
}
private void MyVariable_ValueWritten(object sender, PviEventArgs e)
{
//throw new NotImplementedException();
}
private void CmdSetStruct_Click(object sender, EventArgs e)
{
myStructPV.WriteValueAutomatic = false;
myStructPV.Value["Member1"] = 10;
myStructPV.Value["Member2"] = 20;
myStructPV.Value["Member3"] = myVariable.Value;
myStructPV.WriteValue();
}
}
}
myStructPV is null because you're calling CmdSetStruct_Click() without having created myStructPV. You'd need MyVariable_ValueChanged() to run first or to at least put the code from it that creates myStructPV into CmdSetStruct_Click().
As long as you are getting to status "Task pvitest Connected" when running the init stuff, then all the PVI connection is working (if you don't have a task on you PLC named pvitest but still make it to CPU Connected then you're doing okay still). You just have to debug your connecting to actual tags.
As far as communicating with an existing Windows program written by the OEM, that's unlikely. You'd have to use some kind of debugger to get at its memory or hope they made some kind of API which is very unlikely.
I think Isaac is right to assume that you click on the button that executesCmdSetStruct_Click() before you actually initialize the myStruct Pv.
This could be because your connection to the PLC doesn't work up until to the point where you are able to get the valueChanged event from the Lifebit variable.
Could your Lifebit variable on the PLC be global? Would be nice to see the console output of the VS to be able to pinpoint the issue until it crashes.
Regarding running in the PVI trial mode you are right, it can create some problems for the initial connection but in that case, if you just stop the PVI manager and start it again, it should all be fine.
I'd anyway recommend you to have just one struct for handling the communication in an out of the PLC. For example:
gComm.ToPlc.Status.someVariable
gComm.FromPlc.Cmd.startDoingSth
With that, you would have to go through the PVI variable connection process twice only. Once to connect to the ToPlc struct and once to connect to the FromPlc struct. Your code will be a lot easier to manage that way.
And finally, you can use the onConnected events of the variables rather than the valueChanged. That way before you allow your app to move on, you can wait until you get a valid connection on the variables & catch the errors thrown from the variable connection and handle them gracefully. This would make it possible to prevent your app from crashing.
I have been following the guidance here FileSystemWatcher Changed event is raised twice.
However I have a list of files that I'm watching so if I delete 20 files together the event is called 20 times. This is expected and works fine.
How can I only have an event fired once for 20 "simultaneous" file changes (i.e How can I ignore all other file changes until the code in the first instance of Onchanged below has completed. Right now Onchanged is called 20 times.) ?
private void Main_Load(object sender, EventArgs e)
{
public static List<FileSystemWatcher> watchers = new List<FileSystemWatcher>();
UpdateWatcher();
}
public void OnChanged(object sender, FileSystemEventArgs e)
{
try
{
Logging.Write_To_Log_File("Item change detected " + e.ChangeType + " " + e.FullPath + " " + e.Name, MethodBase.GetCurrentMethod().Name, "", "", "", "", "", "", 2);
watchers.Clear();
foreach (FileSystemWatcher element in MyGlobals.watchers)
{
element.EnableRaisingEvents = false;
}
//Do some processing on my list of files here....
return;
}
catch (Exception ex)
{
// If exception happens, it will be returned here
}
finally
{
foreach (FileSystemWatcher element in MyGlobals.watchers)
{
element.EnableRaisingEvents = true;
}
}
}
public void UpdateWatcher() // Check Items
{
try
{
watchers.Clear();
for (int i = 0; i < MyGlobals.ListOfItemsToControl.Count; i++) // Loop through List with for
{
FileSystemWatcher w = new FileSystemWatcher();
w.Path = Path.GetDirectoryName(MyGlobals.ListOfItemsToControl[i].sItemName); // File path
w.Filter = Path.GetFileName(MyGlobals.ListOfItemsToControl[i].sItemName); // File name
w.Changed += new FileSystemEventHandler(OnChanged);
w.Deleted += new FileSystemEventHandler(OnChanged);
w.Created += new FileSystemEventHandler(OnChanged);
w.EnableRaisingEvents = true;
watchers.Add(w);
}
}
catch (Exception ex)
{
// If exception happens, it will be returned here
}
}
The key point here is what does "together" mean to you. after all the system does an independent delete operation for each, which would technically mean they are not all deleted at the exact same time, but if you just wanna be close, let's say if they are all deleted within 5 seconds of each other then we only want OnChange to fire once, you can do the following. Note that this doesn't handle the rename change notification. You weren't listening for it, so I assumed you don't need to.
you may wanna change the 5 seconds window to a small window depending on your use.
class SlowFileSystemWatcher : FileSystemWatcher
{
public delegate void SlowFileSystemWatcherEventHandler(object sender, FileSystemEventArgs args);
public event SlowFileSystemWatcherEventHandler SlowChanged;
public DateTime LastFired { get; private set; }
public SlowFileSystemWatcher(string path)
: base(path)
{
Changed += HandleChange;
Created += HandleChange;
Deleted += HandleChange;
LastFired = DateTime.MinValue;
}
private void SlowGeneralChange(object sender, FileSystemEventArgs args)
{
if (LastFired.Add(TimeSpan.FromSeconds(5)) < DateTime.UtcNow)
{
SlowChanged.Invoke(sender, args);
LastFired = DateTime.UtcNow;
}
}
private void HandleChange(object sender, FileSystemEventArgs args)
{
SlowGeneralChange(sender, args);
}
protected override void Dispose(bool disposing)
{
SlowChanged = null;
base.Dispose(disposing);
}
}
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;
namespace Cameron_PickerillTrinitapoli_Assn1
{
public partial class seasonalBttnChanger : Form
{
public seasonalBttnChanger()
{
InitializeComponent();
}
//Triggers when program first loads
//Sets up
private void bttnChanger_Load(object sender, EventArgs e)
{
List<Button> lstTxt = new List<Button>
{
bttnSpring, bttnSummer, bttnAutumn, bttnWinter
};
//Wiring up event handlers in run time
foreach (Button txt in lstTxt)
{
txt.MouseEnter += button_MouseEnter;
txt.MouseLeave += button_MouseLeave;
}
}
// Sets up different background colors for TextBoxes
//* Static values for the color of each button need
//to be added.
//**Not what I was trying to accomplish
//**This needs to go somewhere else
void button_MouseEnter(object sender, EventArgs e)
{
try
{
// Event handlers always pass the parameter "sender" in as an object.
// You have to downcast it back to the actual type.
String bttnName = null;
String bttnNameSpring = "Spring";
String bttnNameSummer = "Summer";
String bttnNameAutumn = "Autumn";
String bttnNameWinter = "Winter";
Button txt = (Button)sender;
// stkColor.Push(txt.BackColor);
//txt.BackColor = Color.Red;
bttnName = txt.Name;
if (bttnName == bttnNameSpring)
{
txt.BackColor = Color.LightGreen;
}
else if (bttnName == bttnNameSummer)
{
//txt.BackColor = Color.Red;
txt.BackColor = Color.Red;
}
else if (bttnName == bttnNameAutumn)
{
txt.BackColor = Color.Yellow;
}
else if (bttnName == bttnNameWinter)
{
txt.BackColor = Color.Cyan;
}
}
catch (Exception ex)
{
MessageBox.Show("Error:\n " + ex.Message);
}
}
//Handler for mouse leaving the button
void button_MouseLeave(object sender, EventArgs e)
{
try
{
Button txt = (Button)sender;
//txt.BackColor = stkColor.Pop();
}
catch (Exception ex)
{
MessageBox.Show("Error:\n " + ex.Message);
}
}
}
}
}
Alright, so I'm just trying to create a simple program that changes the background colors of these buttons to some plain colors when you mouse over them. I had the same thing working using TextBox, but I need to get it working with button. I changed everything over to use the Button class, and it seems to have all the same functionality, but now the program runs, but nothing happens when you mouse over the buttons.
I'm pretty new to c#, stack exchange, and only slightly less so to programming in general, so sorry if I'm dinking up on etiquette/formatting my questions, etc.
I think you are trying to reference your buttons title when you are actually calling the button name
Changing:
String bttnName = null;
String bttnNameSpring = "Spring";
String bttnNameSummer = "Summer";
String bttnNameAutumn = "Autumn";
String bttnNameWinter = "Winter";
Button txt = (Button)sender;
To:
String bttnName = null;
String bttnNameSpring = "bttnSpring";
String bttnNameSummer = "bttnSummer";
String bttnNameAutumn = "bttnAutumn";
String bttnNameWinter = "bttnWinter";
Causes the code to work.
If you do infact want to use the "Spring", "Summer" etc reference than i would suggest changing
bttnName = txt.Name;
to
bttnName = txt.Text;
And ensure that the Text of the labels is set correctly
Please in my code i try to catch win32.systemevents.sessionended event to procede with saving of my app data by the end of session in case the app is not closed manually .. some time ago this has been workin and now that i had my project grown a lil it is not any more..? i have tried to find something meaningfull for few days but found nothing really.. when i try to catch another systemevent like MonitorResolutionChanged it works well but this one not. I have also tried to register within the mainWindow (app form ..), nothing :-( Please any idea?
I think all the relevant information should be in the beginning till void Main but i put it all in case you would need or want to see more .. Thanx a lot Tomas
My code:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using MovablePython; // my own class within this project
using Avn; //my own referenced assembly
namespace DirDist
{
class Program
{
private static string appGuid = "Cddbserviceman";
private static System.Windows.Forms.ContextMenu nIMenu;
internal static System.Windows.Forms.NotifyIcon notifyIcon1;
private static MenuItem showItem;
public static MenuItem justCDsItem;
private static MenuItem searchItem;
private static MenuItem settingsItem;
private static MenuItem quitItem;
internal static Form1 mainWindow;
private static Hotkey hk;
internal static Registration.LicenceState mode; // app mode - registered/trial/blocked/demaged ..
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (Mutex mutex = new Mutex(false, appGuid))
{
if (!mutex.WaitOne(0, false))
{
MessageBox.Show("CDDB is already running on your machine \n (Check status bar for access ..)");
return;
}
GC.Collect();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
mode = Registration.Startup();
Program.mainWindow = new Form1();
mainWindow.Activate();
//mainWindow.Validate();
//mainWindow.Update();
mainWindow.Visible = false;
PutIcon();
//Microsoft.Win32.SystemEvents.SessionEnded += SystemEvents_SessionEnded;
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);//**zkousime zda funguje pro hibernaci ..
RegisterHotKey(true);
Application.Run();
}
}
static void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
//MessageBox.Show("SessionEnded fired");
RegisterHotKey(false);
notifyIcon1.Visible = false;
notifyIcon1.Dispose();
notifyIcon1 = null;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
Microsoft.Win32.SystemEvents.SessionEnded -= new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
mainWindow.Close();
}
// zaregistruje globalni hotkey ctrl+shift+F Pro hledani
private static void RegisterHotKey(bool active)
{
if (!active)
{
if (hk != null) hk.Unregister();
}
else
{
if(hk ==null) hk = new Hotkey();
hk.KeyCode = Keys.F;
//hk.Windows = true;
hk.Shift = true;
hk.Control = true;
//hk.Pressed += delegate { Console.WriteLine("Windows+1 pressed!"); };
hk.Pressed += delegate { searchItemClick(new object(), new EventArgs()); };
if (hk.GetCanRegister(mainWindow)) hk.Register(mainWindow);
else ; // just do nothing
}
}
private static void PutIcon()
{
if (notifyIcon1 == null)
{
showItem = new MenuItem ("&Show interface", new System.EventHandler (showInfaceClick));
justCDsItem = new MenuItem ("&Jus'CDs",new System.EventHandler ( justCDsClick));
justCDsItem.Checked = Form1.settings.justCDs;
searchItem = new MenuItem("Search CDDB",new System.EventHandler (searchItemClick));
searchItem.Shortcut = Shortcut.CtrlShiftF;
searchItem.ShowShortcut = true;
settingsItem = new MenuItem("Settings", new System.EventHandler(settingsItemClick));
quitItem = new MenuItem("&Quit", new System.EventHandler(quitItemClick));
nIMenu = new System.Windows.Forms.ContextMenu(new MenuItem[5] { showItem, justCDsItem, searchItem,settingsItem, quitItem });
notifyIcon1 = new System.Windows.Forms.NotifyIcon();
notifyIcon1.ContextMenu = nIMenu;
notifyIcon1.Icon = new System.Drawing.Icon(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Icon1.ico");
//notifyIcon1.Icon = new System.Drawing.Icon(System.IO.Path.GetDirectoryName(
//System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase ) + "Icon1.ico");
//notifyIcon1.Icon = new System.Drawing.Icon("Icon1.ico");
notifyIcon1.DoubleClick += new EventHandler(notifyIcon1_DoubleClick);
notifyIcon1.Visible = true;
}
}
/* private static void notifyIcon1_MouseMove(object sender, MouseEventArgs mea)
* aby to fungovalo je treba upravit contextmenu na contextmenustrip a taky ty items .. az nakonec
* je tu kolem uz rozdelana priprava ..
{
notifyIcon1.ShowBalloonTip(2000,AppName,"Active",ToolTipIcon.None);
} */
// clicks on NotificationIcon context menu ..
private static void showInfaceClick(object sender, EventArgs e)
{
mainWindow.tabControl1.SelectedIndex = 0;
mainWindow.Show();
}
private static void justCDsClick(object sender, EventArgs e)
{
Form1.settings.justCDs = mainWindow.checkBox1.Checked = justCDsItem.Checked = !Form1.settings.justCDs;
if (mainWindow.Visible) mainWindow.Update();
}
private static void searchItemClick(object sender, EventArgs e)
{
mainWindow.tabControl1.SelectedIndex = 1 ;
//this.Size = new Size(this.Width, SystemInformation.PrimaryMonitorSize.Height);
mainWindow.Location = new System.Drawing.Point(SystemInformation.PrimaryMonitorSize.Width - mainWindow.Width, SystemInformation.PrimaryMonitorSize.Height - mainWindow.Height);
//mainWindow.Location = new System.Drawing.Point(880, 500);
mainWindow.Show();
}
private static void settingsItemClick(object sender, EventArgs e)
{
mainWindow.tabPage3_GotFocus(new Object(), new EventArgs());
mainWindow.tabControl1.SelectedIndex = 2;
mainWindow.Show();
}
public static void quitItemClick(object sender, EventArgs e)
{
if (DialogResult.Cancel == MessageBox.Show("Really exit application and stop scanning?",Form1.AppName,MessageBoxButtons.OKCancel,MessageBoxIcon.Question)) return;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
//if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
if (Form1.settings.fileIndex) mainWindow.SaveIndex(Form1.settings.indexPath);
mainWindow.Close();
mainWindow = null;
notifyIcon1.Visible = false;
Application.Exit();
}
static void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
//throw new NotImplementedException();
//if (!mainWindow.Visible) mainWindow.WindowState = FormWindowState.Normal; else mainWindow.WindowState = FormWindowState.Minimized;
//if (!mainWindow.Visible) mainWindow.Show(); else mainWindow.Hide();
if (!mainWindow.Visible) mainWindow.Visible = true; else mainWindow.Visible = false;
}
}
}
OK. So here is the catch and solution . In Windows it is not determined whether win32.systemevents.sessionended shall be risen or form.close() will be called first by operating system. moreover it seems that if form.close() is called first then sessionended is omited even though form is not closed and disposed due to canceling closing process. in my system this behaviour changed after i ran some registry cleaning software. anyway understanding this we have to take care of both possible scenarios.
1. catch win32.systemevents.sessionended (or sessionending) event whatever suits our needs better and be
.
.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
Program.mainWindow = new Form1();
mainWindow.Activate();
mainWindow.Visible = false;
PutIcon();
RegisterHotKey(true);
Application.Run();
}
}
public static void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
// do whatever needed and exit application ..
RegisterHotKey(false);
notifyIcon1.Visible = false;
notifyIcon1.Dispose();
notifyIcon1 = null;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
Microsoft.Win32.SystemEvents.SessionEnded -= new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
if (mainWindow != null)
{
mainWindow.Dispose();
mainWindow = null;
}
Application.Exit();
}
2. properly override form.OnClosing() because this is being called when form is closing either manually by user or by system when shuting down, loging off etc. or create hanler for main form.Closing:
public Form1()
{
this.Closing += new CancelEventHandler(this.Form1_Closing);
InitializeComponent();
}
private void Form1_Closing(Object sender, CancelEventArgs e)
{
if (systemShutdown) Program.SystemEvents_SessionEnded(this, new Microsoft.Win32.SessionEndedEventArgs(Microsoft.Win32.SessionEndReasons.SystemShutdown));
else
{
e.Cancel = true;
this.Hide();
}
}
just want to mention that message pump must be runnig in order to sessionended be risen. Application.run() accomplishes that.
in my case as you can see i had to dig even deeper as i had closing redirected just to hide the app not to close it ( i just hide the app to notification irea icon and close it manually when i need .. ) and so i had to use some kind of way to specify the situation when this is called because sender is unfortunatelly and unexpectedly always this ..?
this is done by overring WndProc and catching propper message .here you can listen pretty much to everything inside windows ( like disc inserted / removed )but it is hooked only to a form and implementation gets often not so simple as you have to manully define various values and structs and compare against those values .. other then that its pretty simple:
private static int WM_QUERYENDSESSION = 0x11;
private static bool systemShutdown = false;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg==WM_QUERYENDSESSION)
{
systemShutdown = true;
}
base.WndProc(ref m);
}
this was found here:
http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.sessionending.aspx
Thinking a bit further we can possibly omit point 1 as system shall probably always try to call mainForm.close() but i keep it as i can not be certain about windows behaviour once it runs those things in different order again .. and also it is the mainly suggested solution for reacting to system shut down ..
hope this is helpfull for someone. greets from prague tomas
Here is something that you could try
For a shutdown, override the OnShutdown method:
protected override void OnShutdown()
{
//your code here
base.OnShutdown();
}
For a logoff:
First, add an event handler to Microsoft.Win32.SystemEvents.SessionEnded in the Service Constructor:
public MyService()
{
InitializeComponent;
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
}
Then add the handler:
void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
//your code here
}
This should catch any ended session, including the console itself (the one running the services).
My question comes from a problem which I have right now. I have MainWindow, AuthenticateWindow, and AddEntryWindow which all are WinForms. In main window I have possibility to Authenticate and Add Entry into my main windows textbox. They can not add an entry until they authenticate (no problem with this). I need to add an entry to the text box which will update my main windows textbox. The problem if, how can I check if entry was added to my textbox?
I am trying to have a Save option from menu strip. I am getting an error whenever I am trying to save an empty file. How could I authenticate the saving process by Save button by having it first disabled, and enabled after entry was added?
I could always verify if if textbox had an entry but I want to have button disabled first, and enabled after entry was added. I do not have a privilege to do so as of right now.
Please ask questions if I am not clear enough.
private void tsmiSave_Click(object sender, EventArgs e)
{
// Open sfdSaveToLocation which let us choose the
// location where we want to save the file.
if (txtDisplay.Text != string.Empty)
{
sfdSaveToLocation.ShowDialog();
}
}
MainWindow.cs
using System;
using System.IO;
using System.Windows.Forms;
namespace Store_Passwords_and_Serial_Codes
{
public partial class MainWindow : Form
{
private AuthenticateUser storedAuth;
public MainWindow()
{
InitializeComponent();
}
private void MainWindow_Load(object sender, EventArgs e)
{
// Prohibit editing.
txtDisplay.Enabled = false;
}
public string ChangeTextBox
{
get
{
return this.txtDisplay.Text;
}
set
{
this.txtDisplay.Text = value;
}
}
private void tsmiAuthenticate_Click(object sender, EventArgs e)
{
AuthenticationWindow authWindow = new AuthenticationWindow();
authWindow.ShowDialog();
storedAuth = authWindow.Result;
}
private void tsmiAddEntry_Click(object sender, EventArgs e)
{
if (storedAuth == null)
{
DialogResult result = MessageBox.Show
("You must log in before you add an entry."
+ Environment.NewLine + "You want to authenticate?",
"Information", MessageBoxButtons.YesNo,
MessageBoxIcon.Information);
if (result == DialogResult.Yes)
{
AuthenticationWindow authWindow =
new AuthenticationWindow();
authWindow.ShowDialog();
storedAuth = authWindow.Result;
AddEntryWindow addWindow = new AddEntryWindow
(this, storedAuth.UserName, storedAuth.Password);
addWindow.ShowDialog();
}
}
else
{
AddEntryWindow addWindow = new AddEntryWindow
(this, storedAuth.UserName, storedAuth.Password);
addWindow.ShowDialog();
}
}
private void tsmiClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void tsmiSave_Click(object sender, EventArgs e)
{
// Open sfdSaveToLocation which let us choose the
// location where we want to save the file.
sfdSaveToLocation.ShowDialog();
}
private void sfdSaveToLocation_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
{
string theFileName = sfdSaveToLocation.FileName;
EncryptDecrypt en = new EncryptDecrypt();
string encrypted = en.Encrypt(txtDisplay.Text,
storedAuth.UserName, storedAuth.Password);
MessageBox.Show(encrypted);
File.WriteAllText(theFileName, encrypted);
}
}
}
AddEntryWindow.cs
using System;
using System.Windows.Forms;
// Needed to be used with StringBuilder
using System.Text;
// Needed to be used with ArrayList.
using System.Collections;
namespace Store_Passwords_and_Serial_Codes
{
public partial class AddEntryWindow : Form
{
string user, pass;
// Initializind ArrayList to store all data needed to be added or retrived.
private ArrayList addedEntry = new ArrayList();
// Initializing MainWindow form.
MainWindow mainWindow;
// Default constructor to initialize the form.
public AddEntryWindow()
{
InitializeComponent();
}
public AddEntryWindow(MainWindow viaParameter, string user, string pass)
: this()
{
mainWindow = viaParameter;
this.user = user;
this.pass = pass;
}
private void AddEntryWindow_Load(object sender, EventArgs e)
{ }
private void btnAddEntry_Click(object sender, EventArgs e)
{
// Making sure that type is selected.
if (cmbType.SelectedIndex == -1)
{
MessageBox.Show("Please select entry type!", "Error!",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// Each field must be filled for specified type.
// Here we are checking if all fields were filled.
else if ((cmbType.SelectedIndex == 0 && (txtUserName.Text == string.Empty || txtPassword.Text == string.Empty)) ||
(cmbType.SelectedIndex == 1 && (txtURL.Text == string.Empty || txtPassword.Text == string.Empty)) ||
(cmbType.SelectedIndex == 2 && (txtSoftwareName.Text == string.Empty || txtSerialCode.Text == string.Empty)))
{
MessageBox.Show("Please fill all the fields!", "Error!",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
int totalEntries = 0;
if(cmbType.SelectedIndex == 0)
addedEntry.Add(new AddPC(cmbType.Text,
txtUserName.Text, txtPassword.Text));
else if(cmbType.SelectedIndex == 1)
addedEntry.Add(new AddWebSite(cmbType.Text,
txtUserName.Text, txtPassword.Text, txtURL.Text));
else if(cmbType.SelectedIndex == 2)
addedEntry.Add(new AddSerialCode(cmbType.Text,
txtSoftwareName.Text, txtSerialCode.Text));
StringBuilder stringBuilder = new StringBuilder();
foreach (var list in addedEntry)
{
if (list is AddPC)
{
totalEntries++;
AddPC tmp = (AddPC)list;
stringBuilder.Append(tmp.ToString());
}
else if (list is AddWebSite)
{
totalEntries++;
AddWebSite tmp = (AddWebSite)list;
stringBuilder.Append(tmp.ToString());
}
else if (list is AddSerialCode)
{
totalEntries++;
AddSerialCode tmp = (AddSerialCode)list;
stringBuilder.Append(tmp.ToString());
}
}
mainWindow.ChangeTextBox = stringBuilder.ToString();
mainWindow.tsslStatus.Text = "A total of " + totalEntries + " entries added.";
// Clearing all fields.
ClearFields();
}
}
private void btnClear_Click(object sender, EventArgs e)
{
ClearFields();
}
private void btnClose_Click(object sender, EventArgs e)
{
// Closing the Add Entry Window form.
this.Close();
}
private void cmbType_SelectedIndexChanged(object sender, EventArgs e)
{
// Deciding which data must be entered depending on
// what type is selected from combo box.
// PC
if (cmbType.SelectedIndex == 0)
{}
// Web Site
else if (cmbType.SelectedIndex == 1)
{}
// Serial Code
else if (cmbType.SelectedIndex == 2)
{}
}
private void ClearFields()
{
// Clearing all fields to the default state.
}
}
}
Regards.
It sounds like you probably just want to subscribe to the TextChanged event, which will be fired whenever the text in the textbox changes.
I can't say I really followed everything that you're doing, but I think you should be fine to just enable or disable your Save button within that event handler.
EDIT: It's not really clear where all your different components live, but you want something like:
// Put this after the InitializeComponent() call in the constructor.
txtDisplay.TextChanged += HandleTextBoxTextChanged;
...
private void HandleTextBoxTextChanged(object sender, EventArgs e)
{
bool gotText = txtDisplay.Text.Length > 0;
menuSaveButton.Enabled = gotText;
}
I'd also strongly advise you not to use ArrayList but to use the generic List<T> type. The non-generic collections should almost never be used in new code.