Hi,
When I create an object from the dll, I pass the function pointer (delegate)
to it. When an event happens on the serial port, this delegate is called and
I can update the UI.
Can you show how I can implement something like this please??
Thanks in advance!
well it's you lucky day, (I hope thats what you ment).
I already wrapped unmanaged code to interact with the serial port:
[Flags]
public enum CommEvents
{
/// <summary>
/// No events
/// </summary>
EV_NONE = 0x0000,
/// <summary>
/// Any Character received
/// </summary>
EV_RXCHAR = 0x0001,
/// <summary>
/// Received certain character
/// </summary>
EV_RXFLAG = 0x0002,
/// <summary>
/// Transmit Queue Empty
/// </summary>
EV_TXEMPTY = 0x0004,
/// <summary>
/// CTS changed state
/// </summary>
EV_CTS = 0x0008,
/// <summary>
/// DSR changed state
/// </summary>
EV_DSR = 0x0010,
/// <summary>
/// RLSD changed state
/// </summary>
EV_RLSD = 0x0020,
/// <summary>
/// BREAK received
/// </summary>
EV_BREAK = 0x0040,
/// <summary>
/// Line status error occurred
/// </summary>
EV_ERR = 0x0080,
/// <summary>
/// Ring signal detected
/// </summary>
EV_RING = 0x0100,
/// <summary>
/// Printer error occurred
/// </summary>
EV_PERR = 0x0200,
/// <summary>
/// Receive buffer is 80 percent full
/// </summary>
EV_RX80FULL = 0x0400,
/// <summary>
/// Provider specific event 1
/// </summary>
EV_EVENT1 = 0x0800,
/// <summary>
/// Provider specific event 2
/// </summary>
EV_EVENT2 = 0x1000
}
protected CommEvents commEvents = CommEvents.EV_N ONE;
private EventHandlerLis t events;
protected EventHandlerLis t Events
{
get
{
if (events == null)
{
lock(this)
{
if (events == null)
{
events = new EventHandlerLis t();
}
}
}
return events;
}
}
// Event objects
private static readonly object EventCharacterR eceived;
private static readonly object EventCertainCha racterReceived;
private static readonly object EventTransmitQu eueEmpty;
private static readonly object EventCTSStateCh anged;
private static readonly object EventDSRStateCh anged;
private static readonly object EventRLSDStateC hanged;
private static readonly object EventBreakRecei ved;
private static readonly object EventLineStatus ErrorOccurred;
private static readonly object EventRingSignal Detected;
private static readonly object EventPrintError Occurred;
private static readonly object EventReceiveBuf ferIs80PercentF ull;
private static readonly object EventProviderSp ecificEvent1;
private static readonly object EventProviderSp ecificEvent2;
static Port() // static constructor
{
EventCharacterR eceived = new object();
EventCertainCha racterReceived = new object();
EventTransmitQu eueEmpty = new object();
EventCTSStateCh anged = new object();
EventDSRStateCh anged = new object();
EventRLSDStateC hanged = new object();
EventBreakRecei ved = new object();
EventLineStatus ErrorOccurred = new object();
EventRingSignal Detected = new object();
EventPrintError Occurred = new object();
EventReceiveBuf ferIs80PercentF ull = new object();
EventProviderSp ecificEvent1 = new object();
EventProviderSp ecificEvent2 = new object();
}
// example to an event "Character Received" you register on:
public event EventHandler CharacterReceiv ed // Any Character received
{
add
{
if (Events[EventCharacterR eceived] == null)
{
commEvents |= CommEvents.EV_R XCHAR;
SetEvents();
}
Events.AddHandl er(EventCharact erReceived, value);
}
remove
{
Events.RemoveHa ndler(EventChar acterReceived, value);
if (Events[EventCharacterR eceived] == null)
{
commEvents &= ~CommEvents.EV_ RXCHAR;
SetEvents();
}
}
}
protected void SetEvents()
{
if (commEvents == CommEvents.EV_N ONE)
{
return;
}
if (Trace.debug())
{
Trace.debug("Se tting {0} communication port events:\n{1}", PortName,
commEvents);
}
bool result = _SetCommMask(hP ort, (int)commEvents );
if (result == false)
{
throw new CommunicationEx ception("Failed to SetCommMask (set the
events)");
}
}
[DllImport("kern el32.dll", EntryPoint="Set CommMask",
SetLastError=tr ue,
CharSet=CharSet .Unicode, ExactSpelling=t rue,
CallingConventi on=CallingConve ntion.StdCall)]
protected static extern bool _SetCommMask(
Int32 hFile,
int lpEvtMask);
[DllImport("kern el32.dll", EntryPoint="Wai tCommEvent",
SetLastError=tr ue,
CharSet=CharSet .Unicode, ExactSpelling=t rue,
CallingConventi on=CallingConve ntion.StdCall)]
protected static extern bool _WaitCommEvent(
Int32 hFile,
ref CommEvents Mask,
IntPtr lpOverlap);
public void WaitForEvents()
{
if (commEvents == CommEvents.EV_N ONE)
{
throw new CommunicationEx ception("No events have been registered.");
}
CommEvents eventsReceived = CommEvents.EV_N ONE;
bool result = _WaitCommEvent( hPort, ref eventsReceived, IntPtr.Zero);
if (result == false)
{
throw new CommunicationEx ception("Failed Waiting for comm events.");
}
// CharacterReceiv ed
object[] args = new object[]{this, EventArgs.Empty };
EventHandler invoker = null;
if ((eventsReceive d & CommEvents.EV_R XCHAR) == CommEvents.EV_R XCHAR)
{
invoker = (EventHandler)E vents[Port.EventChara cterReceived];
if ( invoker != null)
{
invoker.Dynamic Invoke(args);
}
}
}
Remark:
In this code, the user registers on the events, the first registration
on each event adds a flag to the member: "commEvents ".
After all the clients unregistered from an the event, the flag is
removed from: "commEvents ".
The collection of events is sent to the RS-232 port.
when the WaitForEvents is called, the thread is waiting for any of the
registered events to occur.
When they do, the C# event of the corresponding RS-232 event is
triggered.
Eyal.