如何使用控制台应用程序获取输出并将其显示到 MFC Dialog StaticText

Posted

技术标签:

【中文标题】如何使用控制台应用程序获取输出并将其显示到 MFC Dialog StaticText【英文标题】:How to get the output with console app and display it to MFC Dialog StaticText 【发布时间】:2016-09-20 06:22:39 【问题描述】:

我正在开发一个需要与控制台应用程序获得相同输出的 MFC 应用程序。控制台应用程序可以显示来自串行端口的输入数据。我想使用 MFC 对话框应用程序获取输入并将其显示到编辑控件框中。由于我还是 C++ 的新手,这对我来说似乎很有挑战性。对解决方法有什么建议吗?提前致谢!

控制台应用代码:

enum  EOF_Char = 27 ;

int ShowError (LONG lError, LPCTSTR lptszMessage)

    // Generate a message text
    TCHAR tszMessage[256];
    wsprintf(tszMessage,_T("%s\n(error code %d)"), lptszMessage, lError);
    return 1;


int __cdecl _tmain (int /*argc*/, char** /*argv*/)

    CSerial serial;
    LONG    lLastError = ERROR_SUCCESS;
    lLastError = serial.Open(_T("COM1"), 0, 0, false);
    lLastError = serial.Setup(CSerial::EBaud9600, CSerial::EData8,CSerial::EParNone, CSerial::EStop1);
    lLastError = serial.SetupHandshaking(CSerial::EHandshakeHardware);

    // ** The query command to get input data **
    lLastError = serial.Write(":MEAS:FREQuency?\n");

    // Register only for the receive event
    lLastError = serial.SetMask(CSerial::EEventBreak |
                                CSerial::EEventCTS   |
                                CSerial::EEventDSR   |
                                CSerial::EEventError |
                                CSerial::EEventRLSD  |
                                CSerial::EEventRecv);
    if (lLastError != ERROR_SUCCESS)
         return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port event mask"));

    // Use 'non-blocking' reads,cuz we don't know how many bytes will be received. 
    lLastError = serial.SetupReadTimeouts(CSerial::EReadTimeoutNonblocking);

    if (lLastError != ERROR_SUCCESS)
        return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port read timeout."));

    // Keep reading data, until an EOF (CTRL-Z) has been received
    bool fContinue = true;

    do
    
        // Wait for an event
        lLastError = serial.WaitEvent();

        if (lLastError != ERROR_SUCCESS)
            return ::ShowError(serial.GetLastError(), _T("Unable to wait for a COM-port event."));

        // Save event
        const CSerial::EEvent eEvent = serial.GetEventType();

    // Handle break event
    if (eEvent & CSerial::EEventBreak)
       printf("\n### BREAK received ###\n");  
    // Handle CTS event
    if (eEvent & CSerial::EEventCTS)
       printf("\n### Clear to send %s ###\n", serial.GetCTS()?"on":"off");           
    // Handle error event
    if (eEvent & CSerial::EEventError)
    
        printf("\n### ERROR: ");
        switch (serial.GetError())
        
        case CSerial::EErrorBreak:      printf("Break condition");          break;
        case CSerial::EErrorMode:       printf("Unsupported mode");         break;
        case CSerial::EErrorOverrun:    printf("Buffer overrun");           break;
        case CSerial::EErrorTxFull:     printf("Output buffer full");       break;
        default:                        printf("Unknown");                  break;
        
        printf(" ###\n");
    
    // Handle RLSD/CD event
    if (eEvent & CSerial::EEventRLSD)
       printf("\n### RLSD/CD %s ###\n", serial.GetRLSD()?"on":"off"); 

    // Handle data receive event
    if (eEvent & CSerial::EEventRecv)
    
        // Read data, until there is nothing left
        DWORD dwBytesRead = 0;
        char szBuffer[101];
        do
        
            // Read data from the COM-port
            lLastError = serial.Read(szBuffer,sizeof(szBuffer)-1,&dwBytesRead);
            if (lLastError != ERROR_SUCCESS)
                return ::ShowError(serial.GetLastError(), _T("Unable to read from COM-port."));

            if (dwBytesRead > 0)
            
                // Finalize the data, so it is a valid string
                szBuffer[dwBytesRead] = '\0';

                // **Display the data/Need the same output for EditBox**
                printf("%s", szBuffer);
                // Check if EOF (CTRL+'[') has been specified
                if (strchr(szBuffer,EOF_Char))
                    fContinue = false;
            
        
        while (dwBytesRead == sizeof(szBuffer)-1);
    

while (fContinue);

// Close the port again
serial.Close();
return 0;

【问题讨论】:

你走在了前面。如果您想使用 MFC,您必须首先学习 C++ Windows API(请参阅Prerequisites for learning MFC programming 了解基本原理)。 @IInspectable 感谢您的建议,我正在审查 winAPI,但这需要一段时间。你能帮我一些建议,关于我应该更关注学习 MFC 编程的哪些部分来解决我的问题吗?谢谢! 此时您在 MFC 上的任何投资都将浪费时间。没有什么是有意义的,您将继续根据仪式化的观察编写代码。在某些时候,您将不得不再次忘记您在cargo cult programming 日子里的所有这些坏习惯,从而浪费更多时间。建议您先Learn to Program for Windows in C++(不带MFC)。 @IInspectable !再次感谢您的建议!我会跟着它改掉我在编程中的所有坏习惯。 【参考方案1】:

由于我的 C++ 知识不够好,所以我没有意识到我的问题是如何打破上述代码中的循环以及 char 数组和 CString 之间的转换。这是我的答案:

 void Singlemode::OnBnClickedButton3()
 
     CString str3;
    // TODO: Add your control notification handler code here
    CSerial serial;
    LONG    lLastError = ERROR_SUCCESS;
    lLastError = serial.Open(_T("COM1"), 0, 0, false);
    lLastError = serial.Setup(CSerial::EBaud9600, CSerial::EData8, CSerial::EParNone, CSerial::EStop1);
    lLastError = serial.SetupHandshaking(CSerial::EHandshakeHardware);
    lLastError = serial.Write(":MEAS:FREQuency?\n");

    // Register only for the receive event

    // Use 'non-blocking' reads, because we don't know how many bytes
    // will be received. This is normally the most convenient mode
    // (and also the default mode for reading data).
  bool fContinue = true;
   do
    
        // Wait for an event
       lLastError = serial.WaitEvent();
       // Save event
      const CSerial::EEvent eEvent = serial.GetEventType();
      // Handle data receive event
      if (eEvent & CSerial::EEventRecv)
        
        // Read data, until there is nothing left
        DWORD dwBytesRead = 0;
        char szBuffer[101];
        do
        
            // Read data from the COM-port
            lLastError = serial.Read(szBuffer, sizeof(szBuffer) - 1, &dwBytesRead);

            if (dwBytesRead > 0)
              
                // Finalize the data, so it is a valid string
                szBuffer[dwBytesRead] = '\0';

                // Display the data
                str3 = CString(szBuffer); // conversion to display
                show_result.SetWindowText(str3);
                fContinue = false;   // break the loop
                
             while (dwBytesRead == sizeof(szBuffer) - 1);
         
     while (fContinue);
  

【讨论】:

以上是关于如何使用控制台应用程序获取输出并将其显示到 MFC Dialog StaticText的主要内容,如果未能解决你的问题,请参考以下文章

从 Apache Beam 管道收集输出并将其显示到控制台

如何创建自定义组件并将其添加到基于对话框的应用程序 (MFC)?

从返回类型 DataSet 获取输出并将其显示在 Gridview 中

vc6.0里MFC进度条如何使用

如何从 C++/MFC 程序中获取控制台窗口? [复制]

如何从 Express API 获取数据并将其显示到 React 应用程序?