如何在MFC对话框中按按钮停止循环 我在C++中使用Visual Studio 2017上的对话框为基础的MFC应用程序。

如何在MFC对话框中按按钮停止循环 我在C++中使用Visual Studio 2017上的对话框为基础的MFC应用程序。,c++,visual-studio,user-interface,mfc,dialog,C++,Visual Studio,User Interface,Mfc,Dialog,在我的应用程序中,我有一个显示文本的窗口。当我按下“开始”按钮时,我使用一个无限while循环向它写入数字,当我按下“停止”按钮时,我想停止这个过程。窗口如下所示: void CEditableListControlDlg::OnBnClickedButton1() { int counter = 0; while ((WM_COMMAND != IDC_BUTTON2)) { counter++; m_editCtrl.Set

在我的应用程序中,我有一个显示文本的窗口。当我按下“开始”按钮时,我使用一个无限while循环向它写入数字,当我按下“停止”按钮时,我想停止这个过程。窗口如下所示:

void CEditableListControlDlg::OnBnClickedButton1()
{
     int counter = 0;
     while ((WM_COMMAND != IDC_BUTTON2)) {
            counter++;
            m_editCtrl.SetWindowTextA(std::to_string(counter).c_str());
     }
}

为此,在
Start
按钮处理程序中,我使用while循环在应用程序窗口中计数和打印计数器。每次进入while循环时,我都会检查是否按下了ICD_按钮2(即停止按钮ID):

void CEditableListControlDlg::OnBnClickedButton1()
{
     int counter = 0;
     while ((WM_COMMAND != IDC_BUTTON2)) {
            counter++;
            m_editCtrl.SetWindowTextA(std::to_string(counter).c_str());
     }
}
我没有在
Stop
按钮处理程序中输入任何代码

但是我的应用程序停止响应,我需要使用任务管理器关闭它。有什么问题吗?也许这不是检查是否收到点击按钮的消息的正确方法


谢谢。

这里最基本的是您正在阻塞主线程。即使您更正了“停止”按钮上的错误检查,也不会得到预期结果。原因是当触发事件时,按下按钮,主线程需要处理该事件。你的循环是在路上和。这就是为什么你必须终止这个过程来结束它

如果你真的需要做一些非常激烈的事情,那么可能需要一条线索,但我不认为这是你的目标

//in.h

UINT_PTR timer;
//in.cpp

//initialize timer to null in constructor or CEditableListControlDlg::Create

//you may want to disable the this button while the timer is active
//but don't start another timer if active!
void CEditableListControlDlg::OnBnClickedButton1()
{
    if(timer)
        return;
    //200 millisecond events.
    timer= SetTimer( ID_TIMER, 200, NULL );
}

void CEditableListControlDlg::OnTimer( UINT nIDEvent ) 
{
    //if you have more than one timer, if(nIDEvent == ID_TIMER)...;
    counter++;
    m_editCtrl.SetWindowTextA(std::to_string(counter).c_str());
    CWnd::OnTimer( nIDEvent );
}

//you may want to disable the this button while the timer is inactive
void CEditableListControlDlg::OnBnClickedButton2()
{
    if(timer)
        KillTimer(timer);
    timer= nullptr;
}

我不知道计时器如何解决在后台处理某些内容时允许UI操作的问题。计时器方式最多只能处理一个hat计时器事件的工作单元

一个单独的线程是一个合适的解决方案,但是对于这个场景来说可能太多了

中间方法是在繁忙的
循环中“泵送”消息,有关详细信息,请参见此:

每个GUI程序都有一个消息循环,用于检查来自操作系统的传入消息并对其作出反应。通过自己创建一个无止境的循环,您可以阻止这种情况的发生——这就是为什么您需要Task Manager来关闭程序。它还阻止了诸如重新粉刷窗户之类的事情


MFC提供了一个
OnIdle
函数,在消息循环无事可做时调用该函数。您可以使用此函数进行后台工作,例如增加计数器。有关详细信息,请参阅Microsoft的文档。

要允许主消息循环处理GUI事件,如停止按钮,请单击,添加并在
while
循环中调用此函数
PumpMessages()

void CEditableListControlDlg::PumpMessages()
{
    // Must call Create() before using the dialog
    ASSERT(m_hWnd!=NULL);

    MSG msg;
    // Handle dialog messages
    while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
      if(!IsDialogMessage(&msg))
      {
        TranslateMessage(&msg);
        DispatchMessage(&msg);  
      }
    }
}

我的橡皮鸭想知道
WM_COMMAND
IDC_BUTTON2
如何在循环
WM_COMMAND
IDC_BUTTON2
中更改它们的值。您基本上是在(12!=34).
时编写
。也许这有帮助:我想这需要在工作线程中完成吗?因此,在“开始”按钮中,您启动工作线程,将句柄传递给窗口,以便它可以发布消息以使用数字进行更新。然后,当你按下停止按钮,你杀死工作线程。。。否则,在按钮处理程序中使用
只会阻塞系统。或者使用评论中建议的计时器方法。@andretruckle一个工作线程对我来说听起来太过分了。在这里,计时器更合适。但毕竟我们不知道OP到底想要实现什么。因为对我来说,仅仅增加一个数字听起来毫无意义。