【MFC】多线程计算圆周率π的值

第一次在csdn发文章哈哈~吐舌头

一个操作系统实验课的作业:多线程计算圆周率的值,要求可以中间通过暂停按钮暂停计算,并且可以继续进行下去。

要求有界面,所以采用mfc编程。

1、新建一个基于对话框的mfc应用程序。

用工具栏拉出一个新的按钮,改变其内容为“欢迎进入π计算程序”,调整到自己喜欢的位置。(图片是自己后期自己p图再加上去的,不用在意,添加方法最后会说的)


2、新建一个对话框。

打开资源视图,对着左边Diglog右键-添加资源,点击“新建”,新建的默认对话框名为IDD_DIALOG1,我没有改哈,好习惯是自己改了。


3、然后就是从右侧工具栏拉进来必要的组件

我拉进来一个静态框,修改默认的id为IDC_STATIC1(这一步必须修改),并且删除了默认的显示文字(把caption选项里的文字清除即可),加了边框。

又拉进来一个“开始计算“”的按钮,响应函数后面会说。

拉进来一个“暂停”的按钮,响应函数后面会说。

删去了原有的无用的“确定按钮”。



4、编码。

在原来的对话框中双击“欢迎进入π计算程序”的按钮,编写响应函数

void CpipipiDlg::OnBnClickedButton1()
{
	testdlg *test = new testdlg;
	test ->Create(IDD_DIALOG1,this);
	test ->ShowWindow(SW_SHOW);
	 
	// TODO: 在此添加控件通知处理程序代码
}

即点击这个按钮会弹出新的ID为IDD_DIALOG1的对话框

回到新的对话框。嗯,接下来就有点复杂了。。。

首先我们定义了全局变量lock,并且在对话框的默认构造函数中添加了lock=0,lock的意义在于控制是否继续往下计算。

双击“开始”按钮,添加响应函数,

void testdlg::OnBnClickedButton2()
{
	//AfxMessageBox(_T("开始了"));
	 
	DWORD   dw1;  
    CreateThread(NULL,0,ThreadB1,NULL,0,&dw1); 

for(;b-c;) f[b++]=a/5;
for(;d=0,g=c*2;c-=14,temp[i++]=e+d/a,e=d%a)
for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);
	SetTimer(1,300,NULL);
	i=0;
	// TODO: 在此添加控件通知处理程序代码
}
CreateThread为创建一个标记为dw1的线程,执行ThreadB函数,ThreadB函数的定义为,即打开锁,可以开始计算。

static DWORD WINAPI ThreadB1(LPVOID lpParam)
{
	lock=1;
	return 1;
}
继续回到button2的响应函数,三句for循环是网上找的计算π的值的神奇代码,原本是可以每4位进行输出,一共输出到800位,我对其进行了些简单的修改,把输出改为存储到temp[]数组中,i/a/b/c/d/e/f/g的默认定义如下:

int i=0;
CString ss,cc;
long a=10000,b,c=2800,d,e,f[2801],g;
int temp[10000];
看不懂呜呜,所以也不会修改来提高上限orz,cc用来保存当前算到的4位,ss用来保存累积到到仙子的四位,使用在更后面的代码中。

继续编写“暂停”按钮的响应函数,与开始同理,创建一个编号dw2为线程,并执行ThreadB2函数。

void testdlg::OnBnClickedButton3()
{
	
	// TODO: 在此添加控件通知处理程序代码
		DWORD   dw2;  
    CreateThread(NULL,0,ThreadB2,NULL,0,&dw2);
	
}

ThreadB2与Thread1的区别是一个是关闭,一个是打开。点击开始的时候会打开,点击暂停的时候会锁上,进而中断后面的Ontimer()函数

static DWORD WINAPI ThreadB2(LPVOID lpParam)
{
	lock=0;
	return 1;
}



最后我们设置了一个id为1,间隔为300ns的定时器,回调函数为空,因此在ontimer()函数中编写,添加对WM_TIME消息的响应函数即可开始编写响应函数Ontimer()。

void testdlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if(n==0)
		ss+="3.141",i++;
	else
		ss+=cc;
	 n++;
	cc.Format("%04d",temp[i++])  ;
	if(n%5==0)
		ss+="\n";
	

	SetDlgItemText(   IDC_STATIC1,   ss);
	
	if(lock==0)
		KillTimer(1);
	CDialogEx::OnTimer(nIDEvent);
}
n初始值为0,第一次进入的时候,我们直接定位3.141,否则原本的计算方法只是3141,没有小数点。除此之外的情况下,每次ss后面补充当前4位cc的字符串,而cc每次从保存结果的temp[]数组中获取4位当前值。
当n为5的倍数时,加入换行符,这些做完后,用SetDlgItemText函数改变静态框的值为ss的内容。
以上都是在每300ns没有打断的情况下触发,若被打断后lock会变为0,会用KillTimer()关掉定时器。即不再继续计算。

5、点缀。
嗯嗯,想想其实也就只有这些而已。
从资源视图添加进你的图片资源Bitmap形式,原图最好放进你的工程文件夹内。下面是我使用的2张图,第一张图小p了一下。



接下来添加些图片,第一个对话框的图片是直接从工具栏拖进来一个静态图片控件,改type为Bitmap,改image为你的图片的id,拉到你需要的位置和大小,注意,很多人在这里由于叠放顺序无法对部分组件进行操作,按ctrl+d就会显示叠放次序,点击数字使得图片的顺序为1就好

第二个对话框我添加图片的方法和上面有所不同,是在对话框的构造函数中添加
SetBackgroundImage(IDB_BITMAP2);设置背景图的,感觉这里拉大小和位置太麻烦了,原图来自千库网

之后就得到了这样的效果orz。

运行程序后,如果哪一步没有出错的话,点击开始计算,就会每四个字符开始显示pi的值,点暂停就会暂停,再点开始计算会继续,点退出会退出。


理论上可以达到800位。



6、最后讲讲更换图 标

图标要求小于255*255的ico文件格式,得到方法为去百度下载个icoformat.8bi,也可以从我网盘下,链接:http://pan.baidu.com/s/1eRLT79K 密码:ponw

下载完成后复制到你的ps文件目录下plug-ins目录下,再打开ps把图片设计好后(必须够小),保存为ico格式。


把得到的ico格式文件拷贝到你的工程文件下res目录下原本默认的ico,把文件名改为和它的一样,把它替换掉。原来的文件名应该为xxx.ico,xxx为你的工程名。做完之后就大功告成啦!运行试试


OK!



猜你喜欢

转载自blog.csdn.net/sickbaimu/article/details/73259701