一、MFC概念和作用
MFC:微软基础类库 (Microsoft Foundation Class Library),封装了windows应用程序的各种API和相关机制的C++类库
总结:
- MFC是一个大的类库
- MFC是一个应用程序框架
为什么使用MFC?
- 应用提供的框架,可以快速开发
MFC常用的头文件
- afx.h-将各种MFC头文件包含在内
- afxwin.h-包含了各种MFC窗口类。包含afx.h和windows.h
- afxext.h-提供了扩展窗口类的支持,例如工具栏
二、空win32程序模板
1 |
|
三、加载bmp文件
bmp文件是MFC中使用的位图,用来显示图片
1 | // 函数:LoadBitmapFromFile |
四、更改文本框数据
这是一个按钮控件,通过点击按钮,更改文本数据
- 使用CString定义一个字符串
- 使用Format 设置格式和内容
- 使用SetDlgItemText将字符串和控件练习起来
1 | void CInterfaceDlg::OnBnClickedBtnTractionMax() |
五、读取文件
1 | // 读取司控器信息配置文件函数 |
六、写入文件
1 | void CInterfaceDlg::OnBnClickedBtnWrite() |
这是为空情况下自动创建的
1 | [Controller] |
这是节点之后,更新的
其中的 # 和 ;是注释,自动跳过,没有影响
1 | #司控器设置 |
七、创建子窗口
1 | void CInterfaceDlg::OnBnClickedBtnViewSend() |
创建主窗口类
1
2
3
4
5
6// CMainDlg.h
class CMainDlg : public CDialogEx
{
private:
CChildDialog* m_pChildDlg; // 指向子窗口的指针
};1
2
3
4
5
6
7
8
9
10// CMainDlg.cpp
void CMainDlg::OnBnClickedBtnCreateChild()
{
if (m_pChildDlg == nullptr)
{
m_pChildDlg = new CChildDialog(this); // 创建子对话框对象
m_pChildDlg->Create(IDD_CHILD_DIALOG, this); // 创建子对话框
m_pChildDlg->ShowWindow(SW_SHOW); // 显示子对话框
}
}创建子窗口类
添加对话框资源
确保在资源文件中添加了IDD_MAIN_DIALOG
(主对话框)和IDD_CHILD_DIALOG
(子对话框)的对话框资源,并在主对话框中添加一个按钮,其 ID 设置为IDC_BTN_CREATE_CHILD
,用来创建和显示子对话框。
八、添加列表控件
设置列表控件样式和列头
1 | BOOL CDlgSend::OnInitDialog() |
详细解释
**设置列表控件样式 (
LVS_EX_
开头的扩展样式)**:LVS_EX_FULLROWSELECT
:允许整行选择。LVS_EX_GRIDLINES
:显示网格线。LVS_EX_HEADERDRAGDROP
:允许头部拖放。LVS_EX_SINGLEROW
:只允许选择单行。- 这些样式通过按位或运算符
|
结合到dwExListStyle
中,然后通过m_listSend.SetExtendedStyle(dwExListStyle);
应用到列表控件。
定义和添加列头:
CString strListHead[]
定义了列头的标题。int nListWidth[]
定义了每列的宽度。- 通过
m_listSend.InsertColumn(i, strListHead[i], LVCFMT_LEFT, nListWidth[i], -1);
将每个标题和对应的宽度添加到列表控件中。
填充列表控件数据:
FillListSend();
函数用于填充列表控件的数据。这个函数可能会从数据源获取数据,并将数据插入到列表控件的行中。
设置定时器:
SetTimer(IDT_TIMER_SEND, 100, NULL);
设置了一个定时器,每隔100毫秒触发一次定时器消息。这通常用于执行定时任务,如周期性地更新列表数据或其他界面操作。
返回值:
- 函数最后返回
TRUE
,除非将焦点设置到某个控件,否则应该返回TRUE
。在 MFC 对话框中,通常是TRUE
,除非你有特定的需求返回FALSE
。
- 函数最后返回
总结
在 CDlgSend::OnInitDialog()
函数中,你初始化了 m_listSend
列表控件的样式、列头和数据。这些操作确保了列表控件的外观和行为符合预期,并且设置了定时器以便于定时执行任务。如果需要进一步的解释或有其他问题,请随时告诉我!
九、套接字
这个套接字通讯是在你的程序,与电路板之间进行服务的,发送给电路板使用的是sendto()函数,需要注意,发送信息的DO数据,需要nMsg和nID都定义好,才可以发送给对方
你的代码展示了一个在 MFC 应用程序中初始化和关闭服务器端套接字的过程。以下是对这段代码的详细解释:
1 | void CInterfaceDlg::InitSocket() |
为了更清晰地理解这个过程,我们可以看看UDP套接字通信的基本步骤:
创建套接字:
1
m_sockSrv[0] = socket(AF_INET, SOCK_DGRAM, 0);
设置客户端地址:
1
2
3m_addrClient[0].sin_family = AF_INET;
m_addrClient[0].sin_port = htons(port);
m_addrClient[0].sin_addr.s_addr = inet_addr("client_ip_address");发送数据:
1
sendto(m_sockSrv[0], (char*)&data, sizeof(data), 0, (SOCKADDR*)&m_addrClient[0], sizeof(SOCK
在这个套接字消息响应函数中,处理了来自套接字的不同消息类型。让我们逐步分析这个函数的具体作用和逻辑:
套接字接收代码详细解释:
1 | LRESULT CInterfaceDlg::OnSocket(WPARAM wParam, LPARAM lParam) // 套接字响应,获取DI信息 |
代码逻辑:
FD_READ: 当接收到FD_READ事件时,表示有数据可以读取。
- 使用
recvfrom
从套接字读取数据到chRecv
数组中。 - 检查数据前缀是否为
0x88
,如果是则解析ID,并根据ID检查是否为0x00000060
。 - 如果ID匹配,从数据中提取按钮状态到
nBtn
数组中。 - 再次检查数据中的另一段(从索引13开始),重复上述步骤。
- 使用
数据处理:
- 遍历所有模块的套接字,找到与当前套接字匹配的模块。
- 对接收到的两段数据(
mdRecv
数组中的数据)进行处理:- 提取消息和ID。
- 根据消息和ID,决定将数据复制到
m_mdModuleDI
或m_mdModuleAI
中,或处理其他类型的数据。
FD_WRITE: 当接收到FD_WRITE事件时,表示套接字可以写入数据。此处未进行任何操作。
默认处理: 对于其他未处理的事件类型,未进行任何操作。
注意事项:
ID的计算:
1
int nID = (chRecv[1] << 24) + (chRecv[2] << 16) + (chRecv[3] << 8) + chRecv[4];
ID的计算方式需要使用括号确保操作顺序正确,否则可能导致计算结果不正确。
消息类型的处理:
- 确保对每种消息类型和ID的处理逻辑正确。
- 对于未知消息类型或ID,可以考虑增加日志记录或错误处理。
内存操作:
- 使用
memcpy
时,确保源和目标内存区域大小匹配,防止缓冲区溢出或内存损坏。
- 使用
这个函数主要用于处理从套接字接收到的数据,并将解析后的数据存储到相应的模块结构中。
程序发送数据到电路板
1 | void CInterfaceDlg::UpdateDataRecv() |
注意,DO数据需要设置标志字段,直接发送是没办法收到的
十、编辑框和按钮
1、添加编辑框控件和按钮,然后更改ID和Caption
2、编辑框添加成员变量,用来保存输入的编辑框信息
添加之后,Dlg.h会多出变量定义,Dlg.cpp会将变量和控件绑定
1 | // Dlg.h |
3、设置编辑框默认文本,在OnInitDialog()中设置初始文本或水印文字
1 | BOOL CTextToSpeechDlg::OnInitDialog() |
4、双击按钮,系统会自动初始化按钮触发的函数
1 | void CTextToSpeechDlg::OnBnClickedTranfer() |