MFC中如何在一个按钮中循环一个事件,在点击另一按钮时结束这个事件?

通常如果一个按钮中存在死循环时,不能点击另一个按钮的。voidCTestDlg::OnBnClickedButton1(){bInLoop=TRUE;while(bInL... 通常如果一个按钮中存在死循环时,不能点击另一个按钮的。
void CTestDlg::OnBnClickedButton1()
{
bInLoop=TRUE;
while(bInLoop)
{
//一个事件。。。。。。。。。。。。。
};
}
void CTestDlg::OnBnClickedButton2()
{
bInLoop=FALSE;
}
这样是不行的。。我知道可以用线程来解决,也可以用消息处理来解决。在while(bInLoop)时里面传递一个消息来控制循环结束,关键是具体代码怎么写,初学者不知道要用那个函数和语句来写这个。求懂的给改改,能实现按BUTTON2时上面那个BUTTON1 里的WHILE循环结束就行了。写出来再加100分
展开
 我来答
霸王讲故事
推荐于2017-11-26 · 超过39用户采纳过TA的回答
知道小有建树答主
回答量:119
采纳率:0%
帮助的人:106万
展开全部

给你个简单的小例子吧实现你的功能。

1、建立一个MFC工程,上面放2个按钮:第一个按钮是启动循环;第二个按钮是结束循环;

2、步骤:


// CreateThreadexDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "CreateThreadex.h"
#include "CreateThreadexDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

bool bInLoop = true;//------------>定义一个全局变量用于控制循环
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
 CAboutDlg();

...

②在第一个按钮(启动循环)事件里面加入如下代码:

//单击此按钮启动一个线程用于实现循环
void CCreateThreadexDlg::OnBnClickedButton1()
{
 // TODO: 在此添加控件通知处理程序代码
 CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)startlop,NULL,0,0);
}
③在第一个按钮上面定义一个线程函,此函数用于当满足条件实现死循环,不满足条件跳出循环从而关闭线程;

LPTHREAD_START_ROUTINE startlop(void*)
{
 while (bInLoop)//逻辑条件
 {
  MessageBoxW(NULL,L"hello",L"test",MB_OK);
  Sleep(2000);
 }
 return 0;
}

3、关闭循环,点击此按钮将全局变量赋予假,则结束循环

void CCreateThreadexDlg::OnBnClickedButton2()
{
 // TODO: 在此添加控件通知处理程序代码

 bInLoop=false;


}

很简单的一个线程例子,当然方法众多,希望对初学的你有帮助,请采纳,谢谢

任明星Ming
2013-12-16 · TA获得超过798个赞
知道小有建树答主
回答量:1061
采纳率:100%
帮助的人:1149万
展开全部
不要再MFC的窗口及空间里使用线程等待,那样会阻止MFC本身的窗口线程的消息分发,请自行创建个线程或者WM_TIMER来做处理。
这里有个WTL的滚动进度条控件,里面用了WM_TIMER来做线程,持续不断的刷新进度条,当按钮点击停止后,也会停掉滚动条的动画。WTL和MFC是相通的,你可以将里面的关键点,移植到MFC上面。
http://blog.csdn.net/renstarone/article/details/9230763
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
空雪梦见
2013-12-16 · TA获得超过5598个赞
知道大有可为答主
回答量:2522
采纳率:75%
帮助的人:1201万
展开全部
bInLoop=TRUE;
CWinThread* pct = AfxGetThread();
while(bInLoop)
{
MSG m;
while (::PeekMessage(&m, 0, 0, 0, PM_NOREMOVE) != 0)
pct->PumpMessage();
//一个事件。。。。。。。。。。。。。
};

改成这样看看?不过Button2被点击之前,你的程序很可能无法退出(就是点x退不掉)
追问
我的BUTTON2 内容不用改么?
void CTestDlg::OnBnClickedButton2()
{
bInLoop=FALSE;
}
这样的话blnLoop=FALSE的值能传进去么?不用传递消息的函数给他传递值么?blnLoop要定义成全局变量吧。
追答
binLoop可以定义成全局变量也可以定义成CTestDlg类的成员变量。只要Button1和2里binLoop指的是同一个变量,就可以了。

前提是你的 //一个事件 不能运行太长的时间,比如你循环一次要10秒钟,那么你的窗口还是反应非常慢的。

窗口会卡的原因是消息没有得到处理,而这么改代码的原理就是每个循环的时候都把之前积压下来的消息都处理了
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
花花浪客
2013-12-16 · TA获得超过2069个赞
知道小有建树答主
回答量:792
采纳率:100%
帮助的人:713万
展开全部

这里给出两种方法,一种是使用Timer,然后在OnTimer函数里面做自己的事情。

另外一个是定义一个线程函数:

UINT __cdecl MyControllingFunction( LPVOID pParam );

注意这个函数只能是全局函数或者是类的静态函数,不能为类的成员函数,

然后使用AfxBeginThread启动线程。

详细参考附件

 

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
icelbja
2013-12-16 · TA获得超过138个赞
知道小有建树答主
回答量:180
采纳率:100%
帮助的人:152万
展开全部
另开一个线程到时可以,不过这个createthread函数(启动线程函数)应该放在BUTTON1里然后你BUTTON1里的循环放在线程函数里,BUTTON2控制bInLoop真假来结束你的线程里的循环。

如果不开一个线程其实也可以那就是重载run()函数,部分代码
for (;;)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
do //if there is pump all waiting
{
if ( !PumpMessage() )
return ExitInstance();
} while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE));
}
else if (AfxGetMainWnd()->IsIconic())
{
WaitMessage();
}
///你的while循环改成if
if(bInLoop)
{
/////////////////BUTTON1设置bInLoop为真BUTTON2设置bInLoop为假。

}
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(3)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式