Serial IO in VisualStudio 2011 / C++

I needed to hack together a quick windows application to read data over a serial port and write it to a file. Unfortunately I think VisualStudio is probably still the best way of writing Win32 GUI apps. However I’ve not really used VisualStudio since the VisualStudio.net beta, and most of the stuff I did before that was on VisualStudio 6.

Man Microsoft have really murdered C++… are these proprietary garbage collection extensions all over the place? I couldn’t see a way of writing a pure C++, unmanaged GUI app in VS 2011…

Anyway, to get Serial IO working in a GUI application I needed to add the following methods, these were all added to the Form itself, like I say this was a quick hack:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public:
  // members
  String^ comport;
  String^ dump_filepath;
  String^ current_filename;
  SerialPort^ serialn;
 
  // initalise serial port
  void init_acquire() {
    int baudRate=9600;
 
    serialn = gcnew SerialPort(comport, baudRate);
 
    serialn->ReadTimeout = 50;
 
    serialn->Open();
  }
 
  // Read from serial port
  String^ acquire() {;
    String^ s;
    try {
      s = serialn->ReadLine();
    }
    catch (TimeoutException ^) { }
     
    return s;
  }
 
  // Button handler, starts thread
  private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
 
    dumped_lines      = 0;
    dumped_file_count = 0;
    dump_filepath = this->drop_location_textbox->Text;
    current_filename = dump_filepath + dumped_file_count + ".txt";
 
    comport = comport_textbox->Text;
 
      ThreadStart ^myThreadDelegate = gcnew ThreadStart(this, &Form1::repeat);
    trd = gcnew Thread(myThreadDelegate);
    trd->IsBackground = true;
    trd->Start();
    dumped_lines = 0;
  }
 
  // Thread code
  delegate void DelegateThreadTask();
  private: void ThreadTask() {
 
    // This weirdness is required because setting the TextBox text is not thread safe.
    if (data_textbox->InvokeRequired == false) {
      String ^data = acquire();
      this->data_textbox->Text = this->data_textbox->Text + data;
      //current_filename
 
      StreamWriter^ sw = gcnew StreamWriter(current_filename,true);
 
      sw->WriteLine(data);
 
      sw->Close();
 
    } else {
      DelegateThreadTask ^myThreadDelegate = gcnew DelegateThreadTask(this,&Form1::ThreadTask);
      this->Invoke(myThreadDelegate);     
    }
  }
 
  // Thread loop (reads from serial, dumps to file/textbox.
  private: void repeat() {
    init_acquire();
    while(true) {
      ThreadTask();
      Thread::Sleep(100);
    }
  }

You’ll also need to add the following headers:

1
2
3
using namespace System::IO::Ports;
using namespace System::Threading;
using namespace System::IO;

Leave a Reply