Post by MeOK
Starting from scratch with my own serial port setup using HANDLE hComm
I have no problems sharing the hComm handle with Web1a and Web2a.
A handle is something that works quite similar to a pointer (in many
OSes, a handle _is_ just an opaque pointer). However, you should make
yourself comfortable with C++'s terms (or any terms for object orientation).
Post by MeThe old problem seems to be the attempt to share the "Class" of port.
That statement is almost incomprehensible. I assume that you mean that
working with the HANDLE hComm did the trick, whereas using the "class"
version for working with COM ports lead to various errors. Note that
HANDLE and CSerialCom are two completely different things.
A HANDLE is a kind of ID that is given to you by the OS when you open a
COM port. This ID must then be used in all sub-sequent attempts to read
or write the COM port. Working directly with the HANDLE can be a bit
cumbersome, especially when you forget to close the COM port using the
"close" function (the COM port will be blocked for all other
applications until your application terminates).
To avoid a blocked COM port due to programming errors, CSerialCom was
invented. CSerialCom acts as a Resource Guard (google for RAII) for a
COM port (also some convenience methods that makes the configuration of
a COM port a bit easier). CSerialCom uses a COM port HANDLE internally
(the HANDLE is the only way how the COM port can be used, everything
that provides communication with the COM port must use a HANDLE). The
purpose of CSerialCom is to ensure that the COM port is properly closed
when an object of CSerialCom goes out of scope (google for scope, a
concept that is of great importance for C++).
So if you want to read from a COM port, you can either write:
void readFromCOM2usingHANDLE () {
char Buffer[100];
HANDLE com = ::open("COM2");
if (com) {
::read(com, Buffer, sizeof(Buffer));
::close(com);
}
}
or using CSerialCom
void readFromCOM2usingCSerialCom () {
char Buffer[100];
CSerialCom com;
if (com.OpenPort ("COM2")) {
int ByesRead;
com.ReadString(Buffer, sizeof(Buffer), &BytesRead);
}
}
Notice that the example using CSerialCom is almost identical to the code
that uses the HANDLE directly. However, there is a slight difference:
When the program flow leaves the scope of readFromCOM2usingCSerialCom,
the COM port will be closed automatically.
For your application, the benefit from using CSerialCom is not so
obvious since the COM port should be closed when the window that
contains the three tabs is closed. As I understand you have managed to
solve the problem by passing the HANDLE to the COM port to your tab
views. To achieve the same thing with a CSerialCom object, you would
have to pass a CSerialCom* pointer to the tab views. Then the CSerialCom
object would be a member of the window that contains the tab views, and
the tab views would access this member through pointers.
So instead of
void SetWeb1ComPort(HANDLE port);
HANDLE pport;
in your tab view Web1a, you should write
void SetWeb1ComPort(CSerialCom* port);
CSerialCom* pport;
and pass not the CSerialCom object to Web1a but only a pointer:
m_dWeb1a.SetWeb1ComPort(&port);
instead of
m_dWeb1a.SetWeb1ComPort(port);
Note that the class CSerialCom is not very good. One of the greatest
shortcomings is that the author forgot to close the underlying COM port
in CSerialCom's destructor. Due to this error, the whole purpose of
CSerialCom is not served (CSerialCom only eases the opening of a COM
port). Furthermore, CSerialCom should not be copy-constructable. The
worst thing about CSerialCom is that it is publicly derived from CWnd.
Please do yourself a favour and look for a better class.
Regards,
Stuart