MFC中如何在一个按钮中循环一个事件,在点击另一按钮时结束这个事件?
void CTestDlg::OnBnClickedButton1()
{
bInLoop=TRUE;
while(bInLoop)
{
//一个事件。。。。。。。。。。。。。
};
}
void CTestDlg::OnBnClickedButton2()
{
bInLoop=FALSE;
}
这样是不行的。。我知道可以用线程来解决,也可以用消息处理来解决。在while(bInLoop)时里面传递一个消息来控制循环结束,关键是具体代码怎么写,初学者不知道要用那个函数和语句来写这个。求懂的给改改,能实现按BUTTON2时上面那个BUTTON1 里的WHILE循环结束就行了。写出来再加100分 展开
给你个简单的小例子吧实现你的功能。
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;
}
很简单的一个线程例子,当然方法众多,希望对初学的你有帮助,请采纳,谢谢
这里有个WTL的滚动进度条控件,里面用了WM_TIMER来做线程,持续不断的刷新进度条,当按钮点击停止后,也会停掉滚动条的动画。WTL和MFC是相通的,你可以将里面的关键点,移植到MFC上面。
http://blog.csdn.net/renstarone/article/details/9230763
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秒钟,那么你的窗口还是反应非常慢的。
窗口会卡的原因是消息没有得到处理,而这么改代码的原理就是每个循环的时候都把之前积压下来的消息都处理了
这里给出两种方法,一种是使用Timer,然后在OnTimer函数里面做自己的事情。
另外一个是定义一个线程函数:
UINT __cdecl MyControllingFunction( LPVOID pParam );
注意这个函数只能是全局函数或者是类的静态函数,不能为类的成员函数,
然后使用AfxBeginThread启动线程。
详细参考附件
如果不开一个线程其实也可以那就是重载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为假。
}
}