【发布时间】:2021-01-13 05:13:50
【问题描述】:
我正在用 C++ 在 Visual Studio 2017 上编写 MFC 应用程序。该应用程序是用于与 USB 设备通信的用户界面。在我的应用程序中有Start 按钮。当用户按下Start 按钮时,USB 设备开始流式传输数据,即它开始发送数据包,直到我告诉它停止(我知道每个数据包的最大大小,但我不知道我有多少数据包会得到)。我正在将流数据写入 .CSV 文件。
为此,我使用了循环板(我仍然没有原始板)。 我正在尝试模拟一个真实的场景,所以我编写了一个发送和读取数据的 while 循环。
在我的应用程序中,我还添加了一个Stop 按钮,它应该通过退出这个while循环来停止数据传输。
由于我无法从主对话框中执行此操作,因此我想创建一个子对话框来执行通信(它将执行从循环板发送和接收包的 while 循环)并且我将控制它我的主对话框中的子窗口。
为此,我根据 Barrnet Chou 的建议创建了另一个类,如下所示:
header 文件:
#pragma once
#include <string>
#include "libusb.h"
class ChildDlg : public CDialog
{
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnButton1Clicked();
afx_msg void OnButton2Clicked();
};
cpp 文件:
#pragma once
#include "stdafx.h"
#include "ChildDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// constants definition for packet transfers
constexpr auto VID = 0x04B4;
constexpr auto PID = 0x00F0;
constexpr auto OUT_ENDPOINT_ID = 1;
constexpr auto IN_ENDPOINT_ID = 1;
constexpr auto MAX_PACKET_SIZE = 512;
constexpr int INIT_PACKET_SIZE = 4;
bool flag;
struct libusb_device_descriptor DeviceDescriptor;
libusb_context* context = NULL; //a libusb session
libusb_device_handle* DeviceHandle = NULL; //a device handle
BEGIN_MESSAGE_MAP(ChildDlg, CDialog)
ON_BN_CLICKED(IDC_BUTTON1, &ChildDlg::OnButton1Clicked)
ON_BN_CLICKED(IDC_BUTTON2, &ChildDlg::OnButton2Clicked)
END_MESSAGE_MAP()
void startCommunication() {
/* Prepare device for communication */
int RetVal = libusb_init(&context); //initialize a library session
if (RetVal < 0) {
// MessageBox(hwnd, "Error in libusb_init", "Error:", MB_OK);
return;
}
else {
libusb_set_debug(context, 3); //set verbosity level to 3, as suggested in the documentation
DeviceHandle = libusb_open_device_with_vid_pid(context, VID, PID); //these are vendorID and productID for Cypress FX3 specific device
}
if (DeviceHandle == NULL) {
// MessageBox(hwnd, "Cannot open device", "Notice:", MB_OK);
return;
}
if (libusb_kernel_driver_active(DeviceHandle, 0) == 1) { //find out if kernel driver is attached
//detach it
if (libusb_detach_kernel_driver(DeviceHandle, 0) != 0) {
// MessageBox(hwnd, "Failed To Detach Kernel Driver!", "Error:", MB_OK);
return;
}
}
RetVal = libusb_claim_interface(DeviceHandle, 0); //claim interface 0 (the first) of device (desired device FX3 has only 1)
if (RetVal < 0) {
// MessageBox(hwnd, "Cannot Claim Interface", "Error:", MB_OK);
return;
}
}
void endCommunication() {
libusb_close(DeviceHandle); //close the device we opened
libusb_exit(context); //needs to be called at the end
}
void ChildDlg::OnButton1Clicked() {
// Insert Start button handler here
flag = true;
startCommunication();
unsigned char* DataOut = new unsigned char[INIT_PACKET_SIZE]; //data to write
unsigned char* DataIn = new unsigned char[MAX_PACKET_SIZE]; //data to read
int BytesWritten; //used to find out how many bytes were written
int BytesRead; //used to find out how many bytes were read
DataOut[0] = 'a'; DataOut[1] = 'b'; DataOut[2] = 'c'; DataOut[3] = 'd'; //some dummy values
int RetVal = libusb_bulk_transfer(DeviceHandle, (OUT_ENDPOINT_ID | LIBUSB_ENDPOINT_OUT), DataOut, sizeof(DataOut), &BytesWritten, 0);
if (RetVal == 0 && BytesWritten == sizeof(DataOut)) //we wrote the 4 bytes successfully
MessageBox("Writing Successful!", "Notice:");
else
MessageBox("Write Error", "Notice:");
int counter = 0;
while ((libusb_bulk_transfer(DeviceHandle, (IN_ENDPOINT_ID | LIBUSB_ENDPOINT_IN), DataIn, sizeof(DataIn), &BytesRead, 200) == 0) && flag == true) {
std::string cleanData = std::to_string(DataIn[0]) + std::to_string(DataIn[1]) + std::to_string(DataIn[2]) + std::to_string(DataIn[3]);
MessageBox(cleanData.c_str(), "DATA IN ");
int RetVal = libusb_bulk_transfer(DeviceHandle, (OUT_ENDPOINT_ID | LIBUSB_ENDPOINT_OUT), DataOut, sizeof(DataOut), &BytesWritten, 0); //the out endpoint of current device is 1
if (RetVal != 0 || BytesWritten != sizeof(DataOut)) MessageBox("Write Error", "Error:");
}
while (libusb_bulk_transfer(DeviceHandle, (IN_ENDPOINT_ID | LIBUSB_ENDPOINT_IN), DataIn, sizeof(DataIn), &BytesRead, 200)) {
MessageBox("Garbage", "Notice:");
}
delete[] DataOut; //delete the allocated memory for data
delete[] DataIn; //delete the allocated memory for data
endCommunication();
}
void ChildDlg::OnButton2Clicked() {
flag == false;
}
当在主对话框中按下Start 按钮时,我向子对话框发送消息如下:
/* Start Handler */
void CEditableListControlDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
dlg->SendDlgItemMessageA(IDC_BUTTON1, BM_CLICK);
return;
}
当在主对话框中按下Stop 按钮时,我会向子对话框发送一条消息,如下所示:
/* Stop Handler */
void CEditableListControlDlg::OnBnClickedButton2()
{
// TODO: Add your control notification handler code here
dlg->SendDlgItemMessageA(IDC_BUTTON2, BM_CLICK);
}
我有两个问题,第一个是我不知道如何将消息从子对话框发送回主对话框。
第二个问题是我得到如下编译错误:
Severity Code Description Project File Line Suppression State
Error C2065 'IDC_BUTTON1': undeclared identifier
Severity Code Description Project File Line Suppression State
Error C2065 'IDC_BUTTON2': undeclared identifier
但我不知道如何声明这些按钮?在我的主对话框中,我通过将它们添加到 Resource view 并单击它们两次来创建这些按钮(这会自动创建足够的处理程序)
有没有办法将Resource view 添加到子对话框中?如果没有我想如何创建这些标识符IDC_BUTTON1 和ICD_BUTTON2?
谢谢。
【问题讨论】:
-
“没有弹出窗口” - 子窗口和弹出窗口实际上是互斥的。如果您希望您的子窗口“弹出”,您可能需要阅读window features。
-
1.我不确定您是否在父窗口中添加了消息映射。如果没有,您可以添加它,例如 ON_MESSGAE。 2.可以查看
Button1 and Button2的ID是否被修改,或者是否添加了相应的头文件。 -
@BARRENTCHOU 感谢您的评论。我检查了,不幸的是我仍然找不到问题,消息映射在标题中声明并在
cpp文件中实现,我确实在主对话框中包含ChildDlg.h -
我认为您可以在需要发送消息的地方使用GetParent。
标签: c++ visual-studio mfc libusb