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_NONE;
private EventHandlerList events;
protected EventHandlerList Events
{
get
{
if (events == null)
{
lock(this)
{
if (events == null)
{
events = new EventHandlerList();
}
}
}
return events;
}
}
// Event objects
private static readonly object EventCharacterReceived;
private static readonly object EventCertainCharacterReceived;
private static readonly object EventTransmitQueueEmpty;
private static readonly object EventCTSStateChanged;
private static readonly object EventDSRStateChanged;
private static readonly object EventRLSDStateChanged;
private static readonly object EventBreakReceived;
private static readonly object EventLineStatusErrorOccurred;
private static readonly object EventRingSignalDetected;
private static readonly object EventPrintErrorOccurred;
private static readonly object EventReceiveBufferIs80PercentFull;
private static readonly object EventProviderSpecificEvent1;
private static readonly object EventProviderSpecificEvent2;
static Port() // static constructor
{
EventCharacterReceived = new object();
EventCertainCharacterReceived = new object();
EventTransmitQueueEmpty = new object();
EventCTSStateChanged = new object();
EventDSRStateChanged = new object();
EventRLSDStateChanged = new object();
EventBreakReceived = new object();
EventLineStatusErrorOccurred = new object();
EventRingSignalDetected = new object();
EventPrintErrorOccurred = new object();
EventReceiveBufferIs80PercentFull = new object();
EventProviderSpecificEvent1 = new object();
EventProviderSpecificEvent2 = new object();
}
// example to an event "Character Received" you register on:
public event EventHandler CharacterReceived // Any Character received
{
add
{
if (Events[EventCharacterReceived] == null)
{
commEvents |= CommEvents.EV_RXCHAR;
SetEvents();
}
Events.AddHandler(EventCharacterReceived, value);
}
remove
{
Events.RemoveHandler(EventCharacterReceived, value);
if (Events[EventCharacterReceived] == null)
{
commEvents &= ~CommEvents.EV_RXCHAR;
SetEvents();
}
}
}
protected void SetEvents()
{
if (commEvents == CommEvents.EV_NONE)
{
return;
}
if (Trace.debug())
{
Trace.debug("Setting {0} communication port events:\n{1}", PortName,
commEvents);
}
bool result = _SetCommMask(hPort, (int)commEvents);
if (result == false)
{
throw new CommunicationException("Failed to SetCommMask (set the
events)");
}
}
[DllImport("kernel32.dll", EntryPoint="SetCommMask",
SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
protected static extern bool _SetCommMask(
Int32 hFile,
int lpEvtMask);
[DllImport("kernel32.dll", EntryPoint="WaitCommEvent",
SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
protected static extern bool _WaitCommEvent(
Int32 hFile,
ref CommEvents Mask,
IntPtr lpOverlap);
public void WaitForEvents()
{
if (commEvents == CommEvents.EV_NONE)
{
throw new CommunicationException("No events have been registered.");
}
CommEvents eventsReceived = CommEvents.EV_NONE;
bool result = _WaitCommEvent(hPort, ref eventsReceived, IntPtr.Zero);
if (result == false)
{
throw new CommunicationException("Failed Waiting for comm events.");
}
// CharacterReceived
object[] args = new object[]{this, EventArgs.Empty};
EventHandler invoker = null;
if ((eventsReceived & CommEvents.EV_RXCHAR) == CommEvents.EV_RXCHAR)
{
invoker = (EventHandler)Events[Port.EventCharacterReceived];
if ( invoker != null)
{
invoker.DynamicInvoke(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.