Discussion:
VC6 serial port usage in a tabbed dialog application
(too old to reply)
Me
2012-10-25 01:34:41 UTC
Permalink
VC++ 6.0
I have a main dialog with a tab control with three tab dialogs.
Is it possible for all three tab dialogs to use the same serial com port?
Or is it possible when you click a tab, the tab you leave closes the port
so the next tab can re-open it.
I am using SerialCom for serial communications and please don't flame me
for this.
It has been working for me for several years without issue even under Win7.
TIA.
ScottMcP [MVP]
2012-10-25 14:02:34 UTC
Permalink
VC++ 6.0 I have a main dialog with a tab control with three tab dialogs. Is it possible for all three tab dialogs to use the same serial com port? Or is it possible when you click a tab, the tab you leave closes the port so the next tab can re-open it. I am using SerialCom for serial communications and please don't flame me for this. It has been working for me for several years without issue even under Win7. TIA.
Yes, of course it is possible for all three tab dialogs to use the same serial port. All you have to do is provide all three dialogs with a pointer to the one serial port object.

I showed an example in your previous post about this, but you responded by simply reposting your original question.(?)
Me
2012-10-25 22:45:00 UTC
Permalink
That is not true.
I posted some of my code because when I do as you said i get a message
thats stated the port is already openned. So I asked for insertion details
using my code....
Post by ScottMcP [MVP]
VC++ 6.0 I have a main dialog with a tab control with three tab dialogs. Is it possible for all three tab dialogs to use the same serial com port? Or is it possible when you click a tab, the tab you leave closes the port so the next tab can re-open it. I am using SerialCom for serial communications and please don't flame me for this. It has been working for me for several years without issue even under Win7. TIA.
Yes, of course it is possible for all three tab dialogs to use the same serial port. All you have to do is provide all three dialogs with a pointer to the one serial port object.
I showed an example in your previous post about this, but you responded by simply reposting your original question.(?)
David Lowndes
2012-10-26 00:02:40 UTC
Permalink
Post by Me
I posted some of my code because when I do as you said i get a message
thats stated the port is already openned.
You can't open the port multiple times (without closing it beforehand
of course) - however you can keep using the same handle as many times
as you want in your process.

Dave
Me
2012-10-26 01:24:05 UTC
Permalink
Post by David Lowndes
Post by Me
I posted some of my code because when I do as you said i get a message
thats stated the port is already openned.
You can't open the port multiple times (without closing it beforehand
of course) - however you can keep using the same handle as many times
as you want in your process.
Dave
Thats the part I don't fully understand how to do.
Please help.
Me
2012-10-26 01:48:37 UTC
Permalink
Post by Me
Post by David Lowndes
Post by Me
I posted some of my code because when I do as you said i get a message
thats stated the port is already openned.
You can't open the port multiple times (without closing it beforehand
of course) - however you can keep using the same handle as many times
as you want in your process.
Dave
Thats the part I don't fully understand how to do.
Please help.
How do I share the same handle?
David Lowndes
2012-10-26 07:32:48 UTC
Permalink
Post by Me
How do I share the same handle?
It's just a variable - you access ("share") it the same way you would
any piece of data.

If you're currently storing the handle in one of your tabbed pages
classes, the obvious place to move it to would be the common parent of
each of those page classes (probably your dialog class).

Dave
Me
2012-10-26 11:45:59 UTC
Permalink
Post by David Lowndes
Post by Me
How do I share the same handle?
It's just a variable - you access ("share") it the same way you would
any piece of data.
If you're currently storing the handle in one of your tabbed pages
classes, the obvious place to move it to would be the common parent of
each of those page classes (probably your dialog class).
Dave
Here is what I have recently tried.

//To use SerialCom, in the main Dialog's .h file I add:
#include "SerialCom.h"

//And under public: I add:
class CAdelphiX2Dlg : public CDialog
{
// Construction
public:
CAdelphiX2Dlg(CWnd* pParent = NULL); // standard constructor

Web1a m_dWeb1a;
Web2a m_dWeb2a;
Web3a m_dWeb3a;
CSerialCom port; //for the serial port access

//....
//the rest of the main Dialog .h file
}


//In the main Dialog's .cpp OnInitDialog() I add:
m_cTab.GetWindowRect(tabRect);
m_rSettingsRect.left = 2;
m_rSettingsRect.top = 40;
m_rSettingsRect.right = tabRect.Width() - 4;
m_rSettingsRect.bottom = tabRect.Height() - 40;

m_dWeb1a.Create(IDD_WEBX1, this); // Create the child windows
for the main window class
m_dWeb2a.Create(IDD_WEBX2, this);
m_dWeb3a.Create(IDD_WEBX3, this);

ShowWindowNumber(0);

TCITEM tabItem; // Set the titles for each tab
tabItem.mask = TCIF_TEXT;
tabItem.pszText = _T(" Web-1 ");
m_cTab.InsertItem(0, &tabItem);
tabItem.pszText = _T(" Web-2 ");
m_cTab.InsertItem(1, &tabItem);
tabItem.pszText = _T(" Options ");
m_cTab.InsertItem(2, &tabItem);

CString Comport = "com1"; //setup serial port
if(!(port.OpenPort(Comport))){
MessageBox("Cannot open Communication Port.\nPlease Check Options For
Proper Setting","Error",MB_OK+MB_ICONERROR);
return TRUE;
}
if(!(port.ConfigurePort(9600,8,0,NOPARITY,ONESTOPBIT))){
MessageBox("Cannot Configure Communication
Port","Error",MB_OK+MB_ICONERROR);
port.ClosePort();
}
else{
if(!(port.SetCommunicationTimeouts(0,260,0,0,0))){
MessageBox("Cannot Configure Communication
Timeouts","Error",MB_OK+MB_ICONERROR);
port.ClosePort();
}


//I have tried adding #include "SerialCom.h" and a function in Web1a.h to
//get port.
class Web1a : public CDialog
{
// Construction
public:
Web1a(CWnd* pParent = NULL); // standard constructor
void SetWeb1ComPort(CSerialCom pport);
CSerialCom port

//And I added to Web1a.cpp the following.
void SetWeb1ComPort(CSerialCom pport)
{
port = pport;
}

I get the following build errors
error C2664: 'SetWeb1ComPort' : cannot convert parameter 1 from 'class
CSerialCom' to 'class CSerialCom'
error C2065: 'port' : undeclared identifier
David Lowndes
2012-10-26 13:30:48 UTC
Permalink
I don't know what CSerialCom is, but you appear to be doing it wrong.

You do not want a copy of the CSerialCom object in your tabbed page
classes, all you need is a reference (or a pointer) to the existing
one in your parent dialog class.

Dave
Me
2012-10-26 15:52:47 UTC
Permalink
Post by David Lowndes
I don't know what CSerialCom is, but you appear to be doing it wrong.
You do not want a copy of the CSerialCom object in your tabbed page
classes, all you need is a reference (or a pointer) to the existing
one in your parent dialog class.
Dave
Please show me what I need to put into the Web1a.h and Web1a.cpp to use the
pointer to port from the main Dialog?
ScottMcP [MVP]
2012-10-27 01:12:13 UTC
Permalink
Post by Me
Please show me what I need to put into the Web1a.h and Web1a.cpp to use the
pointer to port from the main Dialog?
My reply of Oct 18 in your other thread did exactly that.
Me
2012-10-29 01:15:44 UTC
Permalink
Post by ScottMcP [MVP]
Post by Me
Please show me what I need to put into the Web1a.h and Web1a.cpp to use the
pointer to port from the main Dialog?
My reply of Oct 18 in your other thread did exactly that.
Here is what Scott sent me on the 18th.
===========================================================================
You can directly call a function in the child dialog. For example, one of
your child dialogs is m_dWeb1a. If you add a function in that dialog called
SetComPort then this will call it:

m_dWeb1a.SetComPort(port);
===========================================================================

Like I said before, I use SerialCom class for serial port usage.
I include SerialCom.cpp and SerialCom.h in my project.
In the main Dialog I do:
CSerialCom port // and use the port functions afterwards.

I tried creating the function in Web1a
In the .h file I tried different things with compiler errors.
class Web1a : public CDialog
{
// Construction
public:
Web1a(CWnd* pParent = NULL); // standard constructor

bool SetWeb1ComPort(HANDLE pport); //don't know what pport should be
// declared as?
//I also tried bool SetWeb1ComPort(CSerialCom port)

And in Web1a.cpp I added:
bool SetWeb1ComPort(HANDLE pport)
{
port = pport; //not sure what to do here either?
return true;
}

In the main dialog I know I have to add:
m_dWeb1a.SetWeb1ComPort(port); //or something like this?

Please help me out here...
David Lowndes
2012-10-27 17:02:58 UTC
Permalink
Post by Me
Please show me what I need to put into the Web1a.h and Web1a.cpp to use the
pointer to port from the main Dialog?
Have you found Scott's original reply?

Dave
Me
2012-10-30 12:12:11 UTC
Permalink
Post by David Lowndes
Post by Me
Please show me what I need to put into the Web1a.h and Web1a.cpp to use the
pointer to port from the main Dialog?
Have you found Scott's original reply?
Dave
I have uploaded my test project to www dot ed711 dot com /AdelphiX2.zip
Please make the required corrections so I can use the same comport setup by
the main dialog in both Web1a and Web2a dialogs.
And yes, I do not understand "pointers" fully.
I know what they are but bot fully how to use.
Please help he.
Thanks.
David Lowndes
2012-10-30 12:31:45 UTC
Permalink
Post by Me
Please make the required corrections so I can use the same comport setup by
the main dialog in both Web1a and Web2a dialogs.
Sure, where do I send my invoice to? :)

Dave
Me
2012-10-30 16:35:20 UTC
Permalink
Post by David Lowndes
Post by Me
Please make the required corrections so I can use the same comport setup by
the main dialog in both Web1a and Web2a dialogs.
Sure, where do I send my invoice to? :)
Dave
If it is going to cost then it must NOT be as easy as suggested!
David Lowndes
2012-10-30 17:11:50 UTC
Permalink
Post by Me
If it is going to cost then it must NOT be as easy as suggested!
If you're not fully comfortable with core C/C++ programming then it's
not going to be easy.

Many people helping here are doing it in their free time, we can point
you in the right direction, but you have to be willing to put in the
time to learn the basics and apply them to your application by
yourself.

Dave
Me
2012-10-30 17:46:27 UTC
Permalink
Post by David Lowndes
Post by Me
If it is going to cost then it must NOT be as easy as suggested!
If you're not fully comfortable with core C/C++ programming then it's
not going to be easy.
Many people helping here are doing it in their free time, we can point
you in the right direction, but you have to be willing to put in the
time to learn the basics and apply them to your application by
yourself.
Dave
I have spent several days doing reaearch regarding pointers or sharing
pointers without much luck. I tried web searches on what you two state I
need to do. I have learned most of my programming with research and help
from the newsgroups. I have written alot of dialog apps and had no need for
this type of sharing until now.
Me
2012-10-30 18:54:14 UTC
Permalink
Post by Me
Post by David Lowndes
Post by Me
If it is going to cost then it must NOT be as easy as suggested!
If you're not fully comfortable with core C/C++ programming then it's
not going to be easy.
Many people helping here are doing it in their free time, we can point
you in the right direction, but you have to be willing to put in the
time to learn the basics and apply them to your application by
yourself.
Dave
I have spent several days doing reaearch regarding pointers or sharing
pointers without much luck. I tried web searches on what you two state I
need to do. I have learned most of my programming with research and help
from the newsgroups. I have written alot of dialog apps and had no need for
this type of sharing until now.
OK
Starting from scratch with my own serial port setup using HANDLE hComm
I have no problems sharing the hComm handle with Web1a and Web2a.
The old problem seems to be the attempt to share the "Class" of port.
Problem solved
bye
Stuart
2012-11-01 23:48:11 UTC
Permalink
Post by Me
OK
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 Me
The 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
Me
2012-11-02 14:02:34 UTC
Permalink
Post by Stuart
Post by Me
OK
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 Me
The 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++).
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
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;
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
Thank you very much for your much needed detailed explanation.
Now I understand the situation much better.
It's nice to get responses like this.
Your help is very much appreciated.
Keep up the great work.

Loading...