注意:这个程序是在上章采用查询法的基础上进行修改的,需要用到上一章的程序,没有的话请看上一张
一、删除采用查询法的一些程序
删除ShangWeiJiDlg.h里面的
void AddCom(void);
void EnumerateSerialPorts(CUIntArray& ports, CUIntArray& portse, CUIntArray& portsu);//获取可用串口函数
afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);
void RefreshCom(void);
删除ShangWeiJiDlg.cpp里面的函数
void CShangWeiJiDlg::AddCom(void)
{
EnumerateSerialPorts(ports, portse, portsu);
unsigned short uicounter;
unsigned short uisetcom;
CString str;
//获取可用串口个数
uicounter = portse.GetSize();
//如果个数大于0
if (uicounter > 0)
{
//初始化串口列表框
for (int i = 0; i < uicounter; i++)
{
uisetcom = portse.ElementAt(i);
str.Format(_T("COM%d "), uisetcom);
m_COM.AddString(str);
}
}
}
void CShangWeiJiDlg::EnumerateSerialPorts(CUIntArray& ports, CUIntArray& portse, CUIntArray& portsu)
{
//清除串口数组内容
ports.RemoveAll();//所有存在串口
portse.RemoveAll();//可用串口
portsu.RemoveAll();//已占用串口
//因为至多有255个串口,所以依次检查各串口是否存在
//如果能打开某一串口,或打开串口不成功,但返回的是 ERROR_ACCESS_DENIED错误信息,
//都认为串口存在,只不过后者表明串口已经被占用
//否则串口不存在
for (int i = 1; i < 256; i++)
{
//Form the Raw device name
CString sPort;
sPort.Format(_T("\\\\.\\COM%d"), i);
//Try to open the port
BOOL bSuccess = FALSE;
HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (hPort == INVALID_HANDLE_VALUE)
{
DWORD dwError = GetLastError();
if (dwError == ERROR_ACCESS_DENIED)
{
bSuccess = TRUE;
portsu.Add(i); //已占用的串口
}
}
else
{
//The port was opened successfully
bSuccess = TRUE;
portse.Add(i); 可用的串口
//Don't forget to close the port, since we are going to do nothing with it anyway
CloseHandle(hPort);
}
//Add the port number to the array which will be returned
if (bSuccess)
ports.Add(i); //所有存在的串口
}
}
BOOL CShangWeiJiDlg::OnDeviceChange(UINT nEventType, DWORD dwData)
{
//DEV_BROADCAST_DEVICEINTERFACE* dbd = (DEV_BROADCAST_DEVICEINTERFACE*) dwData;
switch (nEventType)
{
case DBT_DEVICEREMOVECOMPLETE://移除设备
case DBT_DEVICEARRIVAL://添加设备
RefreshCom();//刷新组合框的内容
break;
default:
break;
}
return TRUE;
}
void CShangWeiJiDlg::RefreshCom(void)
{
int count = m_COM.GetCount();
for (int i = 0; i < count; i++)
{
m_COM.DeleteString(count - 1 - i);
}
AddCom();
m_COM.SetCurSel(0);
}
删除引用的头文件,不删除也不影响,但是为了后期的方便,最好删除
#include <Dbt.h>
二、加入注册表获取函数
将BOOL CShangWeiJiDlg::OnInitDialog()函数里面的
AddCom();//向组合框中添加串口设备
换成
FindCommPort(&m_COM);
将void CShangWeiJiDlg::OnBnClickedBtnopen()函数里面的
//当前端口号
int curPort = portse.ElementAt(m_COM.GetCurSel());//根据索引找到对应的com口编号
m_Comm1.put_CommPort(curPort);//端口号
换成
//拿到COM口索引
int COM=0;
int index = m_COM.GetCurSel();
CString str;
m_COM.GetLBText(index, str);//根据索引获取内容,得到对应的com口名称
/*转换COM口名称为数值*/
char a;
for (int i = 0; i <str.GetLength(); i++)//GetLength()是获取str里面字符的数量
{
a = str.GetAt(i);//GetAt()是读取具体某一位的字符
if (a < 0x3a && a>0x2f)//判断是否为数字,是的话就进去,不是的话就跳过
{
a -= 0x30;//-0x30就可使ASCii数字转换成数值
COM += a;//将值传递给COM
COM = COM * 10;//COM左移一位,当最后一位的时候也乘了10,所以最后需要除掉
}
}
COM /= 10;//因为个位的时候也乘了10,所以这里除去10
m_Comm1.put_CommPort(COM); //选择com,可根据具体情况更改
将ShangWeiJiDlg.h里面函数声明
void FindCommPort(CComboBox *pComboBox);
将ShangWeiJiDlg.cpp里面加入
/* -------- 从注册表里搜寻安装的串口 -----------------------
Win2k/XP和Win98/Me的注册表值不同,所以用枚举
把串口名字写入一个ComboBox控件里
*/
void CShangWeiJiDlg::FindCommPort(CComboBox *pComboBox)
{
HKEY hKey;
#ifdef _DEBUG
ASSERT(pComboBox != NULL);
pComboBox->AssertValid();
#endif
if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Hardware\\DeviceMap\\SerialComm"),
NULL,
KEY_READ,
&hKey) == ERROR_SUCCESS) // 打开串口注册表
{
int i = 0;
TCHAR portName[256], commName[256];
DWORD dwLong, dwSize;
while (1)
{
dwLong = dwSize = sizeof(portName);
if (::RegEnumValue(hKey,
i,
portName,
&dwLong,
NULL,
NULL,
(PUCHAR)commName,
&dwSize) == ERROR_NO_MORE_ITEMS) // 枚举串口
break;
pComboBox->AddString(commName); // commName就是串口名字
i++;
}
if (pComboBox->GetCount() == 0)
{
::AfxMessageBox(_T("在HKEY_LOCAL_MACHINE:Hardware\\DeviceMap\\SerialComm里找不到串口!!!"));
}
RegCloseKey(hKey);
}
}
然后就可以运行啦,这里最主要的就是void CShangWeiJiDlg::FindCommPort(CComboBox *pComboBox)这个里面的处理函数,它就是在注册表查找的函数。