c# Double Agent command event handler - c#

here I'm talking about Double Agent (a windows7/8 version of MS Agent, the same as office 2007 I suppose).
I'm sorry I'm talking about a full product but i'm really being mad to catch an event( the bundled sample does not help for this)...
In the sample i have a similar handle:
public MsaWithDa()
{
InitializeComponent();
mDaControl = new DoubleAgent.Control.Control ();
mDaControl.Show += new DoubleAgent.Control.ShowEventHandler (mDaControl_Show);
}
and this:
private void mDaControl_Show(string CharacterID, DoubleAgent.Control.VisibilityCauseType Cause)
{
SetDaControlButtons();
}
Now I need to handle a different event (when the user select a command from the menu of the Agent).. and I have this
private void mainAgent_Command(object sender, AgentObjects.IAgentCtlCommand e)
{
mDaControlChar.Play("Wave");
mDaControlChar.Speak("Hello!");
}
It's based on the user manual of the product:
Double Agent sends this event when your application is input-active
and the user chooses a command from the character's pop-up menu, or by
spoken input.
public event CtlCommandEventHandler CtlCommand
I added this to the main form:
mDaControl.Command += new DoubleAgent.Control.Command(mDaControl_Command);
but something is missing and I have to pass the two values to be able to test.
Sorry, I understand this is a stupid question and sure super-basic but this is the first time I need to use Event Handlers in c#
Hope someone should help, thanks a lot
EDIT:
Based on this article: Understanding events and event handlers in C#
I now coded this:
public delegate void MyEventHandler(object sender, AgentObjects.IAgentCtlCommand e);
public event MyEventHandler AgentObjects;
and this:
private void InitializeAgent()
{
mDaControl.Command += new MyEventHandler(HandleSomethingHappened);
}
private void HandleSomethingHappened(object sender, AgentObjects.IAgentCtlCommand e)
{
mDaControlChar.Play("Wave");
mDaControlChar.Speak("Hello!");
}
BUT i have an error here:
new MyEventHandler(HandleSomethingHappened)
Error 1 Cannot implicitly convert type 'XCopyPro.Main.MyEventHandler'
to
'DoubleAgent.Control.CommandEventHandler' C:\Users\Shawn\Documents\Visual
Studio 2013\Projects\XCopyPro\XCopyPro\FormMain.cs 159 37 XCopyPro

You should be able to do a new DoubleAgent.Control.CommandEventHandler instead of a new MyEventHandler. As long as your method has the same signature as the DoubleAgent event handler it should work.

Sorry, i'm a newbie in C#! You should not help me without docs...
I solved myself following the manual...
The code is pretty simple, somewhere this:
mDaControl.Command += new DoubleAgent.Control.CommandEventHandler(mDaControl_Commands);
And this:
private void mDaControl_Commands(DoubleAgent.Control.UserInput e)
{
mDaControlChar.Play("Wave");
mDaControlChar.Speak("Hello!");
}

Related

c# Event handler no overide

I have started a new job, where the last dev left they want a program he started to be finished .
I have got to this problem and have looked at it for half a day.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
logTimer = new System.Windows.Threading.DispatcherTimer();
logTimer.Tick += new EventHandler(logTimer_Tick);
logTimer.Interval = new TimeSpan(0, 0, 0, 1);
logTimer.Start();
txtLogData.Text = Logger.GetLines();
try
{
DataProcessor gaugeProcessor = new DataProcessor(SQLConnectionString);
gaugeProcessors.Add(gaugeProcessor);
grdProcessor.ItemsSource = gaugeProcessors;
List<GaugePort> ports = SQLClient.GetGaugePorts(SQLConnectionString);
foreach(GaugePort port in ports)
{
GaugePortListener newListener = new GaugePortListener(port);
listeners.Add(newListener);
}
grdPorts.ItemsSource = listeners;
}
catch(Exception ex)
{
}
}
I am getting an error on line 4 "No Overload for ' logTimer_Tick' matches delegates 'Event Handler'"
The Function it calls dose exist and looks like this
private void logTimer_Tick(object sender, EventArgs e)
{
txtLogData.Text = Logger.GetLines();
}
I have had a look at the links below but i have drawn a blank
http://www.yoda.arachsys.com/csharp/threads/parameters.shtml
C# method name expected
Any ideas would be great
Thanks in advance
EDIT
Change the wording for the error message "Typo"
Directly use the method:
logTimer.Tick += logTimer_Tick;
This should help, as the compiler does strange things with your EventHandler.
The weird thing is that your code seems to work on my machine - that means the code you posted isn't equal to the code you tried or it's a bug caused by your compiler. Or, as a third possibility, the logtimer isn't a WinForms timer, then I can't reproduce your problem.
In this third case it may be possible that the second parameter isn't an EventArg (even though it'd be strange that it works if you don't use the EventHandler stuff). Then you could try an object as second parameter:
private void logTimer_Tick (object sender, object e)
It seems to be neccessary for Windows phone 8.1 (No overload for 'method' matches delegate 'System.EventHandler').

C# Events / Block when hit GUI

I'm working on a custom GUI with SharpDX.
I have user Input from a Form Object and assign Action Methods to the specific events. Below my UI I have a "drawing canvas" and I use Tool Objects that also listen to those Form Events.
But I'm a bit stuck on the matter of how to design my program to only pass those events to a second layer (in this case my canvas) when the first layer did not "hit" anything. In short: Only call "Tool.OnMouseDown" when "Button.OnMouseDown" did return false? Would a Chain Of Responsibility be the/a correct or possible approach?
Or shall I make the current Tool check if "Excecute (Vector2)" is above some gui element but I think this would lead to the kind of coupling I want to prevent.
Hope someone is willing to help/hint (sorry for no code examples, if it's to confusingly descriped please tell me ;))
Thanks!
(Disclaimer: I know I don't have to reinvent the wheel, but I use it partly to learn and improve on my design patterns and coding skills)
thanks to sharp-ninja's answer i did the following:
ok working with it like this now :) thanks again Mister Ninja
using System.Windows.Forms;
public class HandleMouseEventArgs : MouseEventArgs
{
public bool handled { get; protected set; }
public HandleMouseEventArgs(MouseEventArgs args) : base(args.Button, args.Clicks, args.X, args.Y, args.Delta)
{
handled = false;
}
public void SetHandled()
{
handled = true;
}
}
Fortunately in .Net events get called in the order in which they are registered. You can use a handlable event arg so that the first handler of the event can tell subsequent event handlers whether the event was handled.
event EventHandler<MyHandlableEventArg> MultiLevelEvent;
Then in your main program:
// First event handler
MultiLevelEvent += (s, e) => { if(x) e.Handled = true; };
// Subsequent event handler
MultiLevelEvent += (s, e) => { if(!e.Handled) { /* Do Work */ } };

Multiple Invokes off of one Delegate

At the moment I am in the process of building a custom button handler (I needed to integrate the kinect into the button system which also used a mouse) then I got to a horrible thing called Event Handling.. at least an hour yelling at my pc :P. I was wondering, before I go and spend a while changing my system to allow for my new want, which is to have multiple events per handler, I was wondering, is the way I'm going to try work (I would just try, but I'm getting off for the night, so my hope is that I can save some time when I boot the computer up tomorrow and not attempt if my system isn't designed for it)
Also, ive seen a getInvoc list or somthing like that before when I was coding.. Would I add multiple delegates onto it then get that list and itterate over it?
On previous examples I had seen where people used:
public event EventHandler myEventHandler;
I had to use:
private Dictionary<BtnEvent, Delegate> m_events;
and then they did the following to add a handler (their way, not mine):
myObj.myEventHandler += delegate(object sender, EventArgs ea)
{
//do stuff on event
};
first.. If they ran this twice, once with funcA and second with funcb would it run both? or just one?
second, if I applied that logic of += to a Delegate would it work? (I had to use Delegate as I was storing the handlers inside of a dictionary, this allowed for logical access to handlers through use of an enum)
(my code)
private Dictionary<BtnEvent, Delegate> m_events;
//....
m_events = new Dictionary<BtnEvent, Delegate>(6);
m_events.Add(BtnEvent.CLICK_ENTER, null);
m_events.Add(BtnEvent.CLICK_LEAVE, null);
m_events.Add(BtnEvent.CLICK_STAY, null);
m_events.Add(BtnEvent.HOVER_ENTER, null);
m_events.Add(BtnEvent.HOVER_LEAVE, null);
m_events.Add(BtnEvent.HOVER_STAY, null);
//....
public bool addHandle(BtnEvent stateToGet, Delegate function)
{
bool success = false;
if(m_events.ContainsKey(stateToGet))
{
m_events[stateToGet] = function;
}
return(success);
}
// CHANGE ABOVE TO:
public bool addHandle(BtnEvent stateToGet, Delegate function)
{
bool success = false;
if(m_events.ContainsKey(stateToGet))
{
m_events[stateToGet] += function;
}
return(success);
}
Will changing m_events[stateToGet] = function; to m_events[stateToGet] += function; allow me to have multiple event handles (functions I passed to addHandle) be called through the following code?
private void ExecuteEvent(BtnEvent currEvent)
{
if(m_events.ContainsKey(currEvent))
{
if(m_events[currEvent] != null)
{
m_events[currEvent].DynamicInvoke(null);
}
}
}
Please see below code which answers your first question:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += new EventHandler(Form1_Load);
}
void Form1_Load(object sender, EventArgs e)
{
funcA();
funcB();
}
private void funcA()
{
button1.Click += new EventHandler(button1_Click);
}
private void funcB()
{
button1.Click += new EventHandler(button1_Click);
}
void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("I am in event handler");
}
}
On clicking the Button, "I am in event handler" message is shown twice which means += operator works in similar way with delegates as it works with integers or strings. It simply adds the function handler to the queue and upon execution of events, calls all the function pointers in queue.
Regarding your second question, I think you wont achieve the expected behavior by changing = to +=. What I understand from your statement is that, you wish to execute multiple events handlers like CLICK_ENTER, CLICK_LEAVE on calling ExecuteEvent() function. However, since you are storing event handlers and their delegates in a Dictionary, changing = to += will only work in the same way as illustrated in above code.

Basic use of user controls, closing a user control and opening another, user control parameters

ladies and gentlemen, once again I unfortunately am going to bother you with newbie stuff. I have searched for this information for hours, so if there’s a thread with what I want on it, it’s buried deeper than I could find.
This was my first question here, and Mark Hall was kind enough to set me straight. Since then, I have created a new project and recreated my first three screens as user controls – a container/login, a choice screen, and a main screen (currently empty). If a user has more than one collection, the choice screen pops up and allows them to choose a collection.
I did run into a snag with parameters, but I’m solving that by overloading the form declaration (solution found here) – yes, I know it’s much better to send parameters through calls, but I’d hate to have to create a call for each parameter (do I?) and… OK, OK, I’m better at this than {get, set}. Man, I hate being a newbie.
Anyways, I’m having trouble with the choice form – I can’t seem to call it, close it, then go to the main form. I have no problem (if there’s only one collection) in going straight to the main form, it’s that darn choice form. Yes, I know I could include a choice datagridview, but a few of our end users aren’t the sharpest bulb in the tool shed, and need hand-holding. Anyways, here’s the code.
CONTAINER/LOGIN SCREEN
namespace DeleteThis
{
public partial class ContainerForm : Form
{
Main Main = new Main();
LoginCollectionChoice LoginChoice = new LoginCollectionChoice();
DataTable dtPermissions = new DataTable();
public ContainerForm()
{
InitializeComponent();
Main.ExitEvent += new Main.ExitEventHandler(Main_ExitEvent);
LoginChoice.ExitEvent += new
LoginCollectionChoice.ExitEventHandler(LoginChoice_ExitEvent);
}
void LoginChoice_ExitEvent(object sender, EventArgs e)
{
pnlcontainer.Controls.Remove(LoginChoice);
}
void Main_ExitEvent(object sender, EventArgs e)
{
pnlcontainer.Controls.Remove(Main);
}
private void btnLogin_Click(object sender, EventArgs e)
{
LoginProcedure();
}
private void LoginProcedure()
{
DataTable dtPermissions = AdminClass.GetCollectionsForUser(int.Parse(txtbxUserName.Text));
if (dtPermissions.Rows.Count == 1)
{
//Valid user, one collection. Head right in.
pnlcontainer.Controls.Add(Main);
Main.BringToFront();
}
else
{
//More than one collection found. Giving user choice
LoginCollectionChoice LoginChoice = new LoginCollectionChoice(dtPermissions);
pnlcontainer.Controls.Add(LoginChoice);
LoginChoice.BringToFront();
}
}
private void btnExitProgram_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
I hope I didn't kill anything in the snipping. And now the choice screen…
public partial class LoginCollectionChoice : UserControl
{
public delegate void ExitEventHandler(object sender, EventArgs e);
public event ExitEventHandler ExitEvent;
private static DataTable dtPermit;
DataTable dtPermissions = new DataTable();
public LoginCollectionChoice()
{
}
public LoginCollectionChoice(DataTable dtPermissions)
{
InitializeComponent();
GrdCollection.DataSource = dtPermissions;
dtPermit = dtPermissions;
}
private void btnChoose_Click(object sender, EventArgs e)
{
//Code for the user to choose a collection
ExitEvent(this, new EventArgs());
}
}
I’ve snipped all non-relevent code, I hope you gentlemen and ladies can help this newbie get on the right path. Please, be gentle, you wouldn’t want to see me cry, would you? :) Oh! And if you know of any great tutorial sites, please email them to me. I'd prefer to spend a week on tutorials than a week on stumbling and asking here. Thank you all very much.
Are you calling logonForm.Show()?
It seems like you'd need to show it that way.
You use BringToFront(), but I think it needs to be shown first.
The first thing that jumps out to me is that you are calling
LoginCollectionChoice LoginChoice = new LoginCollectionChoice(dtPermissions);
which is creating a local variable called LoginChoice, which is not the same as your class variable even though they share the same name.
What you want to do is to not declare a local variable in that method. Change that line to
LoginChoice = new LoginCollectionChoice(dtPermissions);
Having said that, I believe tylerjgarland in that you need to call .Show() first. And the way you are closing the form is certainly odd. I would create a form, showDialog, get the result and then close the form that way.

Is there a way to tell which EventLog caused the EntryWritten event in C#?

I'm working on a web application that shows event logs data, similar to Event Viewer. The application also has to provide a way for users to subscribe to event logs and receive notifications when an entry is written to subscribed logs, using a web service.
I'm using this code to subscribe to an event log in the web service:
EventLog eventLog = new EventLog(observer.logName, observer.machineName);
eventLog.EnableRaisingEvents = true;
eventLog.EntryWritten += new EntryWrittenEventHandler(eventLog_EntryWritten);
eventList.Add(eventLog);
I'm trying to use observers as subscribers to event logs, and when an EventWritten event is handled, call the Update method of one observer. The problem is, I don't know how to differentiate event logs, since they all use the same event handler. I'm doing this because the number of event logs differs from one machine to another. Also, I want observers to handle only one type of EventLog, ie. one observer would send an e-mail when an event is written to the Application log.
I use this line of code to get all logs on the current computer:
remoteEventLogs = EventLog.GetEventLogs(machineName);
EventWritten event handler has this object sender parameter, but Visual Studio shows its type as EventLogInternal, which I can't use, and I can't cast the sender to EventLog to get EventLog.Log property. If I try to cast it, like this:
void eventLog_EntryWritten(object sender, EntryWrittenEventArgs e)
{
var log = (EventLog)sender;
}
I get an exception saying I can't cast an EventLogInternal to EventLog.
Is there a way to know which EventLog fires the event?
Thanks
I think the problem is, that the whole concept of the EventLog class is that it assumes it works upon a single Log - which it does. So neither the EventWrittenEventArgs nor the EventEntry class sport a member that contains the Log-name, as it is implicitly given by the associated EventLog-instance. Bad is of course, that you cannot get to it inside the EventWritten-handler.
You could create a wrapper around System.Diagnostics.EventLog, like so:
class MyEventLog : EventLog
{
public MyEventLog(string logName, string machineName)
: base(logName, machineName)
{
base.EnableRaisingEvents = true;
base.EntryWritten += MyEventLog_EntryWritten;
}
void MyEventLog_EntryWritten(object sender, EntryWrittenEventArgs e)
{
Console.WriteLine("Entry in {0} log.", base.Log);
// Your code
}
}
Then use MyEventLogin places where you normally would use EventLog. Probably give it a better name though.
You could also factor out the "Your Code" part by providing an Action<string, EntryWrittenEventArgs> property that is being called from inside MyEventLog_EntryWritten and can be set to your "external" handler function.
Another option would be to use reflection along these lines:
string log = (string)sender.GetType().GetProperty("Log").GetValue(sender, null);
since sender in this case actually has the Log property.
I think that what you are looking for can be found in the EntryWrittenEventArgs.
The MSDN shows there is a property called Entry that shows you all kinds of information about what just got logged. There are some properties that might help you in the EventLogEntry class, such as MachineName or UserName.
Here is a link to the Args class
http://msdn.microsoft.com/en-us/library/system.diagnostics.entrywritteneventargs.aspx
Here is a link to the Entry class
http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogentry.aspx
I don't see a direct link to the specific event log, but if you poke around in that class with the debugger the Entry object might give you enough information to look it up.
I hope this helps some.
I agree with the idea of wrapping the EventLog class within another class as suggested by Christian. I recently worked on such a requirement.
This is the class that I created
public class EventLogWatcher : EventLog
{
Action<string, EntryWrittenEventArgs> _changeHandler;
public EventLogWatcher(string logName, Action<string, EntryWrittenEventArgs> changeHandler)
: base(logName)
{
_changeHandler = changeHandler;
}
public void EnableCapture()
{
base.EnableRaisingEvents = true;
base.EntryWritten += EventLogChangeHandler;
}
public void DisableCapture()
{
base.EnableRaisingEvents = false;
base.EntryWritten -= EventLogChangeHandler;
}
private void EventLogChangeHandler(object sender, EntryWrittenEventArgs e)
{
_changeHandler(base.Log, e);
}
}
Here is a usage
foreach (string eventlogType in LogTypes)
logWatchers.Add(new EventLogWatcher(eventlogType, EventLogChangeHandler));
foreach (EventLogWatcher localLog in logWatchers)
{
try
{
localLog.EnableCapture();
}
catch(Exception ex)
{
EventManager.PublishExceptionLogMessage(ex);
}
}
EventManager.PublishInfoLogMessage($"Started EventLog listeners for {string.Join(",", LogTypes)} logs");
private void EventLogChangeHandler(string eventLogType, EntryWrittenEventArgs e)
{
try
{
if (UploadAllowed(eventLogType, e))
{
Dm.EventLog model = _eventLogEntryMapper.MapEntryToModel(e);
Task.Factory.StartNew(
() => _eventLogUploadService.UploadEventLog(model),
_cancellationTokenProvider.Token,
TaskCreationOptions.None,
TaskScheduler.Default);
}
}
catch(Exception ex)
{
EventManager.PublishExceptionLogMessage(ex);
}
}
Another option would be to change the event-registration like this:
eventLog.EntryWritten += (sender, e) => eventLog_EntryWritten(eventLog, e);

Categories