BEtter solution to retrieve serial COM ports and fill a ComboBox (with MFC)

SG 35 Reputation points
2023-10-20T15:47:42.3266667+00:00

Hi,
Despite the lack of any function to retrieve a list of serial COM ports in MFC, I wrote my own. It's working but I'm a bit confuse with all those Windows data types and I had to do some tricks to convert strings.
I use CreatefileW() to iterate over COM ports and I store the file name in a ComboBox if the port's handle is valid.

Both elements use a LPCTSTR , but I did not find any way to concatenate this data type.

To stay in adequation with MFC, I tried to use CFile instead of CreateFileW but it's more "file" oriented.

I found GetCommPorts(), a Win32 function (winbase.h) but I haven't found any sample code.

Is my code on the right way or I need to take another approach ?

int CMFCArduinoDlg::ListComPorts() 
{ 	
	HANDLE hComm;	// Handle for COM port 	
	CString tempFileName;	// Temporary filename	  	

	// Iterate 20 times to find any existing COM port 	
	for (int i = 1; i < 20; i++) 	
		{		 		
			std::string commonBaseName = "\\\\.\\COM";	// Common base for the filename
			commonBaseName += std::to_string(i); // Add port number at the end
			// Store the full filename into a CString
			tempFileName = commonBaseName.c_str();	
			// Cstring to LPCTSTR conversion	 		
			LPCTSTR lpFileName = tempFileName;			  		

			// Scan current port (COM+i) 		
			hComm = CreateFileW(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 		
			if (hComm != INVALID_HANDLE_VALUE) 		
				{
					// If hComm exists, add the COM port to ComboBox 
					comboBoxControl.AddString(lpFileName); 	
					CloseHandle(hComm);		 			
				} 	
		} 	
		return 0; 
}

Thanks and sorry for the headache.

Windows development | Windows API - Win32
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. David Lowndes 2,640 Reputation points MVP
    2023-10-20T15:59:35.8966667+00:00

    Using GetCommPorts should mean you don't have to try each one - it should give you the available port numbers.
    Other than that, since you're using MFC, your code could be a little simpler if you just stick to using CString. Use its Format method to create the port number string, and there's no need to have lpFileName - it already has a cast method, so your code looks cleaner.

    Example of GetCommPorts.

    2 people found this answer helpful.
    0 comments No comments

  2. SG 35 Reputation points
    2023-10-21T13:37:01.11+00:00

    OK found it in Naughter's code:
    I replaced

    CString portList[20];
    
    
    

    by

    	std::vector<CString> portList{ puPortNumbersFound, std::allocator<CString>{} };
    
    

    Now the function returns a std::vector<CString>

    I never used this before, it makes the code cleaner and can save lot of memory.

    Thanks very much for your help

    1 person found this answer helpful.
    0 comments No comments

  3. SG 35 Reputation points
    2023-10-21T09:04:51.41+00:00

    OK, this GetCommPort function is a bit hard to tame.
    I found a piece of code I re-adapted:

    CString* CMFCArduinoDlg::ListCommPorts() 
    {	 	
    	std::vector<ULONG> lpPortNumbers;	// Array to store port numbers 	
    	lpPortNumbers.resize(255);
    	ULONG puPortNumbersFound = 0; 	
    	ULONG nReturn = GetCommPorts(&(lpPortNumbers[0]), static_cast<ULONG>(lpPortNumbers.size()), &puPortNumbersFound); 	
    	if (nReturn != ERROR_SUCCESS) 	
    	{ 		
    		SetLastError(nReturn); 		
    		return false; 	
    	}  	
    	CString portList[20];	// Pre-allocated CString array 	 	
    	for (int i = 0; i < puPortNumbersFound; i++) 	
    	{ 		
    		portList[i].Format(L"\\\\.\\COM%d", lpPortNumbers[i]);	// Port number full string (COMx) 	
    	} 	
    	return portList; 
    }
    
    
    

    This code is working but my problem is I don't know (anymore) how to pre-allocate the CString array to store the formatted strings.

    I left C++ for almost 25 years, things come back little by little. (With my old book: Ivor Horton Visual C++ 6.0 of 1999).


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.