您的位置:首页 > 编程语言

VC,Windows编程心得

2011-07-04 13:17 176 查看
结束了一周的工作,好好总结一下! 关于MFC的线程 由于需要做文件上传的工作,起初做的对话框很死板,只是单纯的使用主线程直接执行上传文件的操作,上传过程中界面卡在哪里,虽然是模态窗口,但让人感觉很不友好,并且界面非常不友好,所以就决定另外开一个线程来执行上传的操作,并美化界面。 在做了必要的验证之后,便开始编写线程。主要的思路是,在用户点击上传按钮以后,便开启一个工作线程UplaodTthread(working thread),并做好对话框中对应控件的控制(如隐藏、disable等操作)。然后在UplaodTthread中执行上传的操作。 原本以为这样就可以了,但突然想到用户是可以取消的,于是决定加上取消的操作。于是问题就来了,如果取消,必定是要终止上传的线程UplaodTthread,如何终止线程又成了个问题,这就涉及到线程同步的问题。在这里实在花了一点时间,网上说法一大堆,用MFC类的,用win32函数的,都试了试,也许我还理解的不透彻,所以都失败,最后就直接用了最原始的方法去同步线程——直接使用公共变量来实现线程之间的同步。 在UplaodTthread中使用设置一个标志bool值,用户在主线程发出了终止上传的消息,开启另一个线程UploadAbortedThread线程,在次线程中改变这个值,就可以让UploadThread的上传过程终止,也就是让UploadThread这个working thread直接返回,上传线程终止。而此时,并不能直接关闭对话框,因为UploadThread是需要用到对话框里面的资源的,所以在UploadAbortedThread中还要判断另一个标志bool值,判断UploadThread是否已经返回,UploadThread在return之前改变这个标志bool值(严格的说,这是不严谨的,因为执行这两个指令是可能被打断的,但考虑到return指令不涉及任何其他资源的引用,而且工作线程是全局函数,所以我个人觉得是可以忽略),UploadAbortedThread得知之后,便发送消息,对话框拦截消息,对话框关闭。 这里主要技术点是在创建MFC线程和线程之间的通信,以及工作线程和主线程之间的通信。 工作线程之间的通信:如前所述,我采用的方法是让这两个线程使用同一个对话框里面的同一个变量(比较原始,也许有更好的方法)。 工作线程与主线程之间的通信:AfxBeginThread(FileUploadAbortedThread,this)。由于是主线程(对话框)开启的线程,所以可以把对话框的指针(this)传递给工作线程,工作线程中队指针进行转换,于是就可以获得对话框对象中的所有公有成员函数以及变量。 如何使工作线程的行为影响到主线程:使用cwnd::PostMessage,在本例中,因为工作线程已经获得了对话框的指针,于是就可以使用pCDialog->PostMessage(WM_USER_DEFINE_MSG),对话框自己拦截捕获这个消息,处理消息。在本例中,对话框的关闭,都是使用这种方法,工作线程发送消息,主线程(对话框)截获,做收尾工作,然后关闭对话框。 当然,这里也涉及到自定义消息和在MFC中消息传递路径,把自定义消息放到消息队列中的宏是: ON_MESSAGE(WM_USER_DEFINE_MSG, pFunc) WM_USER_DEFINE_MSG 一般的定义是 #define WM_UPLOA_FILE_OK (WM_USER + 101) 消息函数的声明: afx_msg LRESULT OnUploadAborted(WPARAM wParam, LPARAM lParam); 至于MFC消息的传递路径,这就和MFC框架有关了,由于在本例中是由对话框对象发送的消息,所以,此对话框类只要有对自定义消息的拦截(也就是在此对话框类中插入了消息映射宏),就会首先截获消息,然后处理消息。 关于CFileDialog类 文件上传,必然要支持多选,即一次上传多个文件,除了在构造函数的第四个参数中指定OFN_ALLOWMULTISELECT外,所选文件的名称也是需要特殊的方法保存的,如下代码CString csFileNameBuffer;cf.m_ofn.lpstrFile = csFileNameBuffer.GetBuffer(NMAXFILE) ;cf.m_ofn.nMaxFile = NMAXFILE;其中cf就是CFileDialog的一个对象,它使用CString的一个对象来保存所选文件的所有路径,这里就体现了MFC类提供的功能,下面代码是依次获得所有文件名:POSITION pos = cf.GetStartPosition();for (int i = 0;pos != NULL;++i){ fileName = cf.GetNextPathName(pos);}csFileNameBuffer.ReleaseBuffer();当然,在使用之后需要释放CString 对象所申请的空间,说明,CString对象可以动态申请空间(可是为什么不能自己在析构的时候去释放申请的空间呢?困惑~~~)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: