Here's some code from a simple win32 serial-port monitor I hacked-together for use with the Atmel family of micro-controllers, specifically, for use with Arduinos.
I'll leave it to you to extract the parts you want for your own console app. As you can see, I never bothered to implement the Stop button - I just kill then restart the program. (I did say it was hacked-together, remember! :) )
The code was also built using Code::Blocks
EDIT: pay attention to the onStartButton code - just realized I don't actually use the values for speed, stop bits etc - I should be setting these to the DCB.
1.
main.cpp
#include <ctype.h>
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"
HINSTANCE hInst;
int availRates[] = {300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600};
int numBits[] = {7,8};
int stopBits[] = {1,2};
const char *parity[] = {"Even", "Odd", "None", "Mark", "Space"};
HWND dlgHwnd;
typedef struct threadData_t
{
HWND callbackWnd;
};
void initIntCombo(HWND combo, int *dataArray, int numElements)
{
int i;
char tmpStr[16];
for (i=0; i<numElements; i++)
{
sprintf(tmpStr, "%d", dataArray[i]);
SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)tmpStr);
}
}
void initStrCombo(HWND combo, const char *dataArray[], int numElements)
{
for (int i=0; i<numElements; i++)
SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)dataArray[i]);}
void initPortCombo(HWND combo)
{
int curPort;
char mPortName[16];
HANDLE hCom;
for (curPort=1; curPort<=20; curPort++)
{
sprintf(mPortName, "\\\\.\\COM%d", curPort);
hCom = CreateFile(mPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (hCom != INVALID_HANDLE_VALUE)
{
sprintf(mPortName, "COM%d", curPort);
CloseHandle(hCom);
SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)mPortName);
}
}
}
void onStartButton()
{
HWND baudCombo, dataBitsCombo, parityCombo, stopBitsCombo;
int baud, nBits, stopBits;
char parityLetter;
char dcbString[32], dcbStrUsed[32];
int selectedParityOption;
baud = GetDlgItemInt(dlgHwnd, IDC_BAUDRATE_COMBO, NULL, true);
nBits = GetDlgItemInt(dlgHwnd, IDC_DATABITS_COMBO, NULL, true);
stopBits = GetDlgItemInt(dlgHwnd, IDC_STOPBITS_COMBO, NULL, true);
selectedParityOption = SendDlgItemMessage(dlgHwnd, IDC_PARITY_COMBO, CB_GETCURSEL, 0, 0);
parityLetter = tolower(parity[selectedParityOption][0]);
sprintf(dcbString, "Success\r\n- %d,%c,%d,%d\r\n", baud, parityLetter, nBits, stopBits);
sprintf(dcbStrUsed, "%d,%c,%d,%d", baud, parityLetter, nBits, stopBits);
DCB dcb;
FillMemory(&dcb, sizeof(dcb), 0);
dcb.DCBlength = sizeof(dcb);
if (!BuildCommDCB(dcbStrUsed, &dcb))
SetWindowText(GetDlgItem(dlgHwnd, IDC_EDIT1) , "Failed");
else
SendDlgItemMessage(dlgHwnd, IDC_EDIT1, EM_REPLACESEL, true, (LPARAM)dcbString);
}
BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
dlgHwnd = hwndDlg;
initPortCombo(GetDlgItem(hwndDlg, IDC_PORTNAME_COMBO));
initIntCombo(GetDlgItem(hwndDlg, IDC_BAUDRATE_COMBO), availRates, sizeof(availRates) / sizeof(availRates[0]));
SendMessage(GetDlgItem(hwndDlg, IDC_BAUDRATE_COMBO), CB_SETCURSEL, 7, 0);
initIntCombo(GetDlgItem(hwndDlg, IDC_DATABITS_COMBO), numBits, sizeof(numBits) / sizeof(numBits[0]));
SendMessage(GetDlgItem(hwndDlg, IDC_DATABITS_COMBO), CB_SETCURSEL, 1, 0);
initIntCombo(GetDlgItem(hwndDlg, IDC_STOPBITS_COMBO), stopBits, sizeof(stopBits) / sizeof(stopBits[0]));
SendMessage(GetDlgItem(hwndDlg, IDC_STOPBITS_COMBO), CB_SETCURSEL, 0, 0);
initStrCombo(GetDlgItem(hwndDlg, IDC_PARITY_COMBO), parity, sizeof(parity) / sizeof(parity[0]));
SendMessage(GetDlgItem(hwndDlg, IDC_PARITY_COMBO), CB_SETCURSEL, 2, 0); }
return TRUE;
case WM_CLOSE:
{
EndDialog(hwndDlg, 0);
}
return TRUE;
case WM_DEVICECHANGE:
SendDlgItemMessage(hwndDlg, IDC_PORTNAME_COMBO, CB_RESETCONTENT, 0, 0);
initPortCombo(GetDlgItem(hwndDlg, IDC_PORTNAME_COMBO));
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
onStartButton();
break;
case IDC_BUTTON3:
SetDlgItemText(hwndDlg, IDC_EDIT1, "");
break;
}
}
return TRUE;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hInst=hInstance;
InitCommonControls();
return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
}
2.
resource.h
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define DLG_MAIN 100
#define IDC_BUTTON3 1000
#define IDC_DATABITS_COMBO 1007
#define IDC_PORTNAME_COMBO 1008
#define IDC_BAUDRATE_COMBO 1009
#define IDC_PARITY_COMBO 1010
#define IDC_STOPBITS_COMBO 1011
#define IDC_BUTTON1 1012
#define IDC_BUTTON2 1013
#define IDC_EDIT1 1014
3. resource.rc
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
DLG_MAIN DIALOG 0, 0, 369, 303
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Serial Monitor v0.01"
FONT 8, "Ms Shell Dlg"
{
GROUPBOX "Serial Port settings", IDC_STATIC, 15, 14, 166, 116
LTEXT "Port Name", IDC_STATIC, 36, 29, 34, 8, SS_LEFT
LTEXT "Baud Rate", IDC_STATIC, 35, 48, 35, 8, SS_LEFT
LTEXT "Data Bits", IDC_STATIC, 40, 67, 30, 8, SS_LEFT
LTEXT "Parity", IDC_STATIC, 52, 88, 18, 8, SS_LEFT
LTEXT "Stop Bits", IDC_STATIC, 41, 107, 29, 8, SS_LEFT
COMBOBOX IDC_PORTNAME_COMBO, 93, 27, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
COMBOBOX IDC_BAUDRATE_COMBO, 93, 46, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
COMBOBOX IDC_DATABITS_COMBO, 93, 65, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
COMBOBOX IDC_PARITY_COMBO, 93, 86, 75, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
COMBOBOX IDC_STOPBITS_COMBO, 93, 105, 75, 31, CBS_DROPDOWNLIST | CBS_HASSTRINGS
PUSHBUTTON "Start Listening", IDC_BUTTON1, 213, 30, 57, 14
PUSHBUTTON "Stop Listening", IDC_BUTTON2, 213, 48, 57, 14
GROUPBOX "Actions", IDC_STATIC, 196, 14, 158, 116
EDITTEXT IDC_EDIT1, 15, 143, 340, 147, ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN
PUSHBUTTON "Clear", IDC_BUTTON3, 214, 66, 57, 14
}