MFC个人心得

2024-06-09

MFC个人心得(精选11篇)

MFC个人心得 篇1

MFC个人心得

在四周时间里完成一个MFC的一个项目,个人觉得还是比较宽裕的,我们在第一周确立了项目的软件功能和名称,我们借鉴手机上RSS软件的广泛应用,想要通过MFC编写一个PC端的RSS应用,用户可以通过我们的软件获取到各大网站的新闻,科技精选,人文精选等等,总之,就是可以通过我们的软件得到每天想要获得资讯消息。

之后我们确定了各小组成员在整个团队中的分工。想要完成这样一个RSS软件的开发,思路还是比较明确的,首先要通过后台获取到各大资讯网站的网页源代码,再从这些源代码中间解析出有用的信息,之后将这些信息传递给前台,前台通过一个友好的界面将信息有条有序的展现给用户。我的主要工作就是开发后台,通过解析HTML代码获取各类资讯。由于先前我在Java平台下对于HTML解析的开发有一定的经验,所以我着手开始编写程序是的第一件事就是搜索看是否有已经写好的解析HTML的C++类库,经过我两天的搜索,我发现在C++环境下并没有比较完好的HTML解析类库,于是我暂时放弃了寻找现成的HTML解析类库,通过MFC中的CSting类中的函数操作来自己编写HTML解析类库。我采用DOM型的方式解析HTML,通过两天时间的编写基本实现了HTML的解析功能并且获取了大量网站的有用信息。由

于要求写在参与MFC项目的心得体会,我就贴上具体的C++代码了。在编写程序的过程中,我还是觉得一个优秀的程序员在于提升代码的重用性与可维护性,在理解别人代码的基础上使用网上现有代码是一个比较好的习惯,这样既能够了解其他人在编写程序时的思路理解,开拓自己的编程理念,同时也大量节省了时间,时间的优秀使用在编写程序的过程中是极其重要的。

另外,在编写MFC程序的过程中我也着实体验到了MFC编写程序的局限性。MFC虽然给开发者提供了一个现成的框架,着实便利的开发者的开发。但同样也造成了一个巨大的问题,开发者很难开发出具有个人特色的软件,想要重新改写程序整体的外观就比较困难,并且C++在编写程序时需要开发者自己定义变量的空间开辟和回收,这点上没有JAVA开发时来的方便,尤其是C++当中的指针机制,一不注意还是很容易造成程序错误的。

最后一点就是一个团队在一个项目中的重要意义。如果这样一个软件完全由我一个人进行开发,可能需要耗费大量时间,但是如果合理地分配给各个组员进行完成,便能取得事半功倍的效果,亦能听取各方面的意见,是的程序更加的完善。

MFC个人心得 篇2

随着计算机用户的不断增加,人们对网络安全的需求也在不断的增加。因此,本课题旨在开发一款个人防火墙,为用户计算机提供一个功能较全面、较实用的网络安全防护。

1 项目需求分析

1.1 个人防火墙环境需求

关于选择何种防火墙取决于几个因素,包括网络规模大小、网络流量大小、系统和数据的敏感程度和应用类型等。在实际安全系统规划和建设中,要根据用户的安全需求和防火墙的功能特点来选择防火墙,而不能仅仅根据防火墙的类型。

防火墙并不能解决全部的安全问题。深层防御战略安全体系和思想认为信息安全保障的概念基础是反应(React) 、检测(Detection) 、恢复(Recovery)和保护(Protection)四个相互作用和反馈的安全环节。防火墙只是一种安全保护措施,必须要和其它安全措施,比如漏洞扫描、主机防护、入侵检测等等有融合起来才能发挥更加强大的安全效果。同时,不同的用户应用类型和不同的用户网络环境也可能影响到防火墙的选择和配置。因此,在计划使用防火墙来保护用户网络时,对防火墙的配置和使用环境进行认真规划十分重要。

1.2 个人防火墙功能需求

个人防火墙主要是对本地计算机与其他计算机的通信进行记录和分析,一旦发现可疑的通信,立即报警,并阻止未经授权的访问。下面将从个人防火墙各个模块具体阐述其功能需求。

1)主程序

一款优秀的防火墙至少需要一个合适、友好的交互界面。在用户交互界面中,有各个过滤模块的开关。这样用户可以自由选择打开或者需要关闭的过滤模块。并且,还可以灵活的添加和删除规则。而且,一款友好的UI界面能增强用户的体验,能深受更加的用户青睐。

2)应用程序进程管理

计算机系统中往往运行众多的进程,用户可以通过应用程序进程来管理那些在后台运行的进程,以便将其关闭并节省内存资源。对于不确定的进程,可以通过打开当前进程所在目录来查看和判别当前进程的合法性。3 )联网应用程序进程管理在应用程序运行的过程中,有些应用程序可能会在后台连接网络,如木马程序,当肉鸡与远控建立连接后,由于黑客的非法入侵和窃取用户数据,会导致用户访问网络时很卡。用户可以通过联网的管理模块来判断对哪些联网的应用进程进行关闭,已阻断非法的网络连接。

4)规则设置

规则设置是个人防火墙的核心功能之一,通过规则设置可以管理应用联网进程的黑白名单、端口过滤、域名过滤、IP过滤、异常端口连接等。用户可以通过设置规则来自由的对数据进行过滤。降低计算机被入侵的风险。

5)日志记录

日志记录也是个人防火墙的核心功能之一。用户可以通过查看日志记录了解哪些应用程序发起了联网,以及联网的时间、联网程序所在的文件夹路径等。方便用户分析和了解应用程序的联网行为和动机。

2 个人防火墙的设计

在个人防火墙的设计中使用了NDIS中间层驱动过滤技术和winsock2 SPI应用层拦截技术。

2.1 个人防火墙模块划分

个人防火墙整体上由五个模块组成,分别为:主程序模块、进程管理模块、联网程序管理模块、规则设置模块、日志记录模块。在每个模块之间都定义了接口,可以实现模块之间相互通信。各个模块间关系如图1所示。

2.2 个人防火墙功能设计

防火墙的主界面设计采用VC++的MFC框架开发,NDIS则采用WDK来开发。通过利用SPI技术以及NDIS驱动拦截技术来作为整个防火墙的核心功能。

1)主程序(UI界面):该模块在整个系统中起着核心作用,负责与各个模块间通信,同时也用来管理和设置规则。用户可以通过主程序来打开和关闭过滤开关,可以将不需要的过滤关闭掉。也可以管理当前的系统进程以及联网应用进程。

2)进程管理模块:进程管理模块主要是列举的了当前系统中所有运行程序的进程和系统进程。进程管理模块包含了结束进程功能和根据进程定位到程序所在的文件夹位置。类似于系统自带的任务管理器,方便用户管理系统中的进程。

3)联网程序管理模块:联网应用进程管理模块的功能是列举出当前系统中所有正在联网的应用程序。其中包含了协议类型、本地IP、远程IP、本地端口、远程端口、当前的连接状态、应用程序的进程ID以及应用程序所在的文件夹位置等详细信息。可以方便用户查看当前的联网程序,也可以只查看TCP连接、UDP连接、以及异常连接等功能,提供结束应用程序的功能,防止一些恶意程序偷偷连接网络。

4)规则设置模块:规则设置模块是整个防火墙的核心模块,防火墙的过滤规则都是根据用户所设置的规则来实现过滤和拦截工作。这些规则都保存在系统的注册表中。规则设置模块中有黑名单设置、白名单设置、IP过滤规则设置、端口过滤规则设置、域名过滤规则设置、包过滤规则设置、异常连接管理设置、其他规则设置等,如表1所示。

其他设置规则中有程序锁功能、进程自我保护功能、注册表保护功能、开机自启功能。

程序锁的功能是保护非本计算机用户运行应用程序。进程自我保护功能是防止一些恶意软件结束本进程。注册表保护是防止恶意程序破坏用户设置的规则,篡改数据。自我启动则是实现开机随着系统保护,实现实时保护功能。

5)日志记录模块:日志记录模块将程序的联网记录都记录下来,存储方式是采用数据库存储,数据库用My SQL数据库。数据库中的表命名为:log,在表中有3个字段,分别为DATE、EVENT、RESULTS,其中DATE用来保存发起联网操作的时间,EVENT是用来记录操作事件,RESULTS则是用来记录防火墙的操作结果。同时也提供日志清除功能,删除历史日志,防止日志数据过多。

3 个人防火墙的实现

个人防火墙的设计仅应用于windows操作系统,采用My SQL数据库,通过使用VC++6.0、WDK等开发工具,在WIN7系统上完成了系统的开发。

3.1 主程序设计

主程序在整个系统中起着核心作用,负责与各个模块间通信,以及与用户进行交互。用户可以通过主程序界面来配置和管理规则。以及各个过滤开关的控制。主程序设计界面如图2所示。

主程序运行时,先加载GProtect.sys驱动保护自身进程,然后通知NDIS驱动更新所有的规则设置。主要调用Load Driver来加载驱动,利用Set Driver()来启动驱动。

加载驱动的关键代码如下:

3.2 黑白名单模块的实现

黑白名单模块管理记录各个程序的联网权限。用户可以自由添加和删除黑白名单中的程序。程序在白名单中,联网时则默认放行;在黑名单中,则默认不允许其连接网络。黑白名单管理模块如图3所示。

校验值采用入口点和镜像大小来做标识,然后调用写入注册表API来写入到 注册表中 ,其中用到 的API为Reg Cre-ate Key Ex、Reg Set Value Ex。

若联网的程序不在黑名单或者白名单中,这提示用户来判断是否放行,提示界面如图4所示:

3.3 IP过滤模块的实现

在模块中可以对本机不允许访问的IP段进行过滤。对于被添加在IP规则中的IP段,本机发起连接访问时都将会被拦截。可以自由添加IP段和删除,IP过滤模块如图5所示:

添加是将起始IP和结束IP添加到列表中,移除可以将选中的IP段移除掉。保存是将列表中的IP段保存至注册表中,并通知NDIS过滤驱动对IP规则进行刷新。“保存”按钮的功能也是将IP段规则写入到注册表中,用到Reg Create Key Ex、Reg-Set Value Ex函数。

3.4 端口过滤模块的实现

在众多的黑客入侵中,有相当一部分是通过一些端口所存在的BUG来入侵计算机的,实现控制电脑主机的目的。一旦一些不安全的端口开放着,并且被黑客攻击,那我们的计算机就很有可能被黑客攻陷并成为“肉鸡”。因此实现端口过滤能够有效的阻止黑客的攻击,保护计算机系统安全。端口过滤模块如图6所示。

“添加”按钮将输入的端口号添加到端口列表中,“保存”按钮将远程端口号和本地端口号保存到注册表中并通知内核层刷新端口规则。

3.5 包过滤模块的实现

包过滤可以通过数据包的类型进行拦截,在该模块中可以拦截TCP包、UDP包、ARP包及ICMP包的发送和接收。禁ping可以拦截icmp消息,防止一些黑客通过ping来判断主机的存活。包过滤的界面设计如图7所示。

“保存”按钮的功能是将每个选项的结果保存到注册表中,并通知内核层来刷新规则,通知内核层主要调用Io Device Con-trol函数来实现通信。与内核通信的代码如下:

3.6 其他设置功能模块的实现

其他功能设置模块中可以设置系统的一些选项,具体如图8所示:

程序锁:保护系统程序的运行。开启程序锁后,运行所有的程序时必须输入预先设置的密码后才能解除锁定。该功能的实现方式是HOOK SSDT表中的Nt Create Section这个函数,运行的程序时候,先跳转到我们自己的函数中,提示用户输入密码,若密码输入正确则解除锁定,并恢复Nt Create Section这个函数的真实地址,否则就返回错误,阻止程序的运行。

进程自我保护:保护系统本身的进程,防止被而已程序结束。保护进程的方法是HOOK SSDT表中的Nt Open Process函数,结束进程时候都会先调用Nt Open Process来获取进程的句柄,然后再调用Nt Terimate Process函数来杀掉进程,因此我们HOOK Nt Open Process这个函数,判断调用这个函数传进来的进程ID,如是当前进程的ID则返回错误,有效防止被结束。

注册表保护:防止规则被破坏,禁止关键位置的写入或者删除操作。防火墙的规则都存放在注册表中,保护规则所在的注册表位置是非常有必要的。实现注册表保护的方式是HOOK SSDT表中的Zw Delete Value Key、Zw Delete Key、Zw Set Val-ue Key这三个函数。

开机自启:使防火墙随系统启动而自动启动。通过写入注册表中的HKEY_LOCAL_MACHINESOFTWAREMicro-softWindowsCurrent VersionRun项中,实现能够实时保护计算机系统。

4 结束语

本文建立在TCP/IP模型的基础上,展开了对windows平台下主机通信的深入研究,通过个人防火墙的数据包拦截和过滤技术,保证了用户计算机的安全。个人防火墙在应用层采用winsock2 SPI技术对应用联网拦截,在内核层则采用NDIS中间层驱动技术进行底层的数据包拦截。个人防火墙的UI界面采用VC++ 6.0的MFC框架进行开发,日志记录采用My SQL数据库,完成了防火墙应有的安全功能。此外,在个人防火墙中设计了设计了多种过滤功能和程序锁,使其更实用,增强了用户体验。

参考文献

[1]宫鼎.基于权重与匹配效率的防火墙规则集优化算法[J].现代计算机:专业版,2014,10(14):45-48.

[2]GONG Ding.Rule Set Optimization Algorithm of the FirewallBased on Weight and Matching Efficiency[J].Modern Comput-er,2014,10(14):45-48.

[3]余静.基于NDIS中间层的协议转换[J].通信技术,2013,46(1):73-75.

[4]YU Jing.Frame Format Conversion based on NDIS[J].Commu-nications Technology,2013,46(1):73-75.

[5]杨永杰.一种基于NDIS网络数据包过滤器的设计[J].计算机应用与软件,2010,27(7):100-101.

MFC处理绘图 篇3

pDC->LineTo(100,100)// 从起点(0,0)到终点(100,100)画一条直线、矩形: Crect rect(0,0,100,100);

pDC->Rectangle(&rect);// 画一个长 100,宽 100 的矩形、圆和椭圆:

Crect rect(0,0,100,100);

pDC->Ellipse(&rect);

Crect rect(0,0,50,100);

pDC->Ellipse(&rect);、多边形:

CPoint poly[4];

poly[0]=CPoint(0,0);

poly[1]=CPoint(50,50);

poly[2]=Cpoint(50,100);

poly[3]=Cpoint(0,50);

pDC->Polygon(poly,4);

(二)库存对象

库存对象是由操作系统维护的用于绘制屏幕的常用对象,包括库存画笔、画刷、字体等。使用 SelectStockObject()函数可以直接选择库存对象,修改系统默认值。

例如,在视图中选用画笔和画刷库存对象来画图。

Void Cexam3_3View::OnDraw(CDC*pDC)

{

Cexam3_2Doc*pDoc=GetDocument();

CRect rect;

Rect.SetRect(Cpoint(0,0),Cpoint(200,200));

pDC->SelectStockObject(WHITE_PEN);// 选用白色画笔

pDC->SelectStockObject(GRAY_BRUSH);// 选用灰色画刷

pDC->Rectangle(rect);

pDC->MoveTo(0,0);

pDC->LineTo(200,200);

pDC->MoveTo(0,200);

pDC->LineTo(200,0);

}

(三)创建和使用自定义画刷和画笔、创建 CPen 的的方法:

•定义时直接创建

Cpen MyPen(PS_SOLID,2,RGB(255,0,0));

(2)定义 Cpen 对象,再调用 CreatePen()函数

Cpen pen;

Pen.CreatePen(PS_SOLID,2,RGB(255,0,0));、创建画刷的方法:

(1)创建实心画刷的 CreateSolidBrush()函数

Cbrush bs;

Bs.CreateSolidBrush(RGB(255,0,0));

(2)创建带阴影的画刷的 CreateHatchBrush()函数

Bs.CreateHatchBrush(HS_CROSS,RGB(255,0,0));// 创建一个带十字阴影的红色画刷

(3)创建位图画刷的 CreatePatternBrush()函数

本函数的应用如下:

CbitMap bmp;

Bmp.LoadBitMap(IDB_MYBITMAP);

Cbrush bs;

Bs.CreatePatternBrush(&bmp);

例4_

3、在视图中绘制三个图形,一个用阴影风格的画刷画的椭圆形,一个用深兰色实心画刷画的圆角矩形,一个用浅灰色画刷画的饼形。

void CExam4_3View::OnDraw(CDC* pDC)

{

CExam4_3Doc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

//设置影象模式

pDC->SetMapMode(MM_ANISOTROPIC);

CPen NewPen,OldPen;

//将画笔选入设备上下文

NewPen.CreatePen(PS_SOLID,5,RGB(0,0,255));

//创建深蓝色实心画刷

pDC->SelectObject(&NewPen);

CBrush NewBrush1,NewBrush2;

//将画刷选入设备上下文

NewBrush1.CreateSolidBrush(RGB(0,0,128));

//绘制圆角矩形

pDC->RoundRect(200,100,330,200,15,15);

//将库存对象浅灰画刷选入设备上下文

pDC->SelectStockObject(LTGRAY_BRUSH);

//绘制饼图

pDC->Pie(350,50,420,150,360,50,400,50);

//创建阴影画刷

NewBrush2.CreateHatchBrush(HS_DIAGCROSS,RGB(125,125,125));

pDC->SelectObject(NewBrush2);

//绘制椭圆

pDC->Ellipse(50,50,150,150);

总结MFC窗口销毁过程 篇4

考虑单窗口情况:

假设自己通过new创建了一个窗口对象pWnd,然后pWnd->Create。则销毁窗口的调用次序:

1. 手工调用pWnd->DestroyWindow;

2. DestroyWindow会发送WM_DESTROY;

3. WM_DESTROY对应的消息处理函数是OnDestroy();

4. DestroyWindow会发送WM_NCDESTROY;

5. WM_NCDESTROY对应的消息处理函数是OnNcDestroy;

6. OnNcDestroy最后会调用PostNcDestroy;

7. PostNcDestroy经常被用户重载以提供释放内存操作。例如可以使用delete this;

通过这种方式,窗口对象对应的窗口和窗口对象本身都被释放了。

如果含有子窗口:

如果含有子窗口,则调用父窗口的DestroyWindow时,它会向子窗口发送WM_DESTROY和WM_NCDESTROY消息。

具体调用顺序参考下文的例子。

DestroyWindow对delete的影响:

应该说前者对后者并没有什么影响。但经常在DestroyWindow间接导致执行的PostNcDestroy中delete窗口对象指针,即delete this。

CView::PostNcDestroy中唯一的操作就是delete this;CframeWnd::PostNcDestory也是如此。而默认的CWnd::PostNcDestroy是空操作,CDialog中也没有对其进行重载,即也是空。

delete对Destroy的影响:

delete会导致析构函数。CWnd的析构函数中有对DestroyWindow的调用,但必须保证:

m_hWnd != NULL &&

this != (CWnd*) & wndTop && this != (CWnd*)&wndBottom &&

this != (CWnd*)&wndTopMost && this != (CWnd*)&wndNoTopMost。

Cdialog的析构函数中也有对DestroyWindow的调用,但条件比较松,只需要m_hWnd != NULL。另外Cdialog::DoModal也会调用DestroyWindow。

CFrameWnd的OnClose中会调用DestroyWindow,但其析构中不会调用DestroyWindow。

CView的析构也不会调用DestroyWindow。

一个SDI程序的销毁过程

有CMainFrame类、CMyView类。并且CMyView有两个子窗口CMyDlg和CmyWnd的实例。

点击退出按钮,CMainFrame会收到WM_CLOSE消息。CframeWnd(CMainFrame的父类)间接会调用CWnd::DestroyWindow;它首先向CMyView发送WM_DESTORY和WM_NCDESTROY消息,并引发相应的处理函数;然后向CMyDlg发送WM_DESTORY和WM_NCDESTROY消息,并引发相应的处理函数;然后向CMyWnd发送WM_DESTORY和WM_NCDESTROY消息,并引发相应的.处理函数。

具体的执行顺序是:

1. 调用CMainFrame::DestroyWindow

2. CFrameWnd::OnDestroy

3. CMyView::OnDestroy

4. CmyWnd::OnDestroy

5. CmyDlg::OnDestroy

6. CmyWnd::PostNcDestroy

7. CmyWnd的析构

8. CmyDlg::OnDestroy

9. CmyDlg的析构

10. CMyView::PostNcDestroy

11. CmyView的析构

12. CMainFrame的析构

13. CMainFrame::DestroyWindow退出

上面情况是假设我们在CmyWnd和CmyDlg的PostNcDestroy中添加了delete this。如果没有添加,则7,10不会执行。

因为CView::PostNcDestroy中调用了delete this,所以然后会执行CMyView的析构操作。因为CframeWnd::PostNcDestroy中调用了delete this,所以最后执行CMainFrame的析构操作。

如果自己的CmyDlg和CmyWnd在PostNcDestroy中有delete this;则二者会被析构。否则内存泄漏。当然delete也可以放在CMyView的析构中做,只是不够OO。

总结

可以有两种方法销毁窗口对象对应的窗口和释放窗口对象指针。一种是通过DestroyWindow。这是比较好的方法,因为最后MFC会自动相应WM_CLOSE导致CframWnd::DestroyWindow被调用,然后会一次释放所有子窗口的句柄。用户需要做的是在PostNcDestroy中释放堆窗口对象指针。但因为某些对象是在栈中申请的,所以delete this可能出错。这就要保证写程序时自己创建的窗口尽量使用堆申请。

另一种是delete。Delete一个窗口对象指针有的窗口类(如CWnd,Cdialog)会间接调用DestroyWindow,有的窗口类(如CView,CframeWn)不会调用DestroyWindow。所以要小心应对。

二者是相互调用的,很繁琐。

一段很好的文章:(作者:闻怡洋)

一个MFC窗口对象包括两方面的内容:一是窗口对象封装的窗口,即存放在m_hWnd成员中的HWND(窗口句柄),二是窗口对象本身是一个C++对象。要删除一个MFC窗口对象,应该先删除窗口对象封装的窗口,然后删除窗口对象本身。

删除窗口最直接方法是调用CWnd::DestroyWindow或::DestroyWindow,前者封装了后者的功能。前者不仅会调用后者,而且会使成员m_hWnd保存的HWND无效(NULL)。如果DestroyWindow删除的是一个父窗口或拥有者窗口,则该函数会先自动删除所有的子窗口或被拥有者,然后再删除父窗口或拥有者。在一般情况下,在程序中不必直接调用DestroyWindow来删除窗口,因为MFC会自动调用DestroyWindow来删除窗口。例如,当用户退出应用程序时,会产生WM_CLOSE消息,该消息会导致MFC自动调用CWnd::DestroyWindow来删除主框架窗口,当用户在对话框内按了OK或Cancel按钮时,MFC会自动调用CWnd::DestroyWindow来删除对话框及其控件。

窗口对象本身的删除则根据对象创建方式的不同,分为两种情况。在MFC编程中,会使用大量的窗口对象,有些窗口对象以变量的形式嵌入在别的对象内或以局部变量的形式创建在堆栈上,有些则用new操作符创建在堆中。对于一个以变量形式创建的窗口对象,程序员不必关心它的删除问题,因为该对象的生命期总是有限的,若该对象是某个对象的成员变量,它会随着父对象的消失而消失,若该对象是一个局部变量,那么它会在函数返回时被清除。

对于一个在堆中动态创建的窗口对象,其生命期却是任意长的。初学者在学习C++编程时,对new操作符的使用往往不太踏实,因为用new在堆中创建对象,就不能忘记用delete删除对象。读者在学习MFC的例程时,可能会产生这样的疑问,为什么有些程序用new创建了一个窗口对象,却未显式的用delete来删除它呢?问题的答案就是有些MFC窗口对象具有自动清除的功能。

如前面讲述非模态对话框时所提到的,当调用CWnd::DestroyWindow或::DestroyWindow删除一个窗口时,被删除窗口的PostNcDestroy成员函数会被调用。缺省的PostNcDestroy什么也不干,但有些MFC窗口类会覆盖该函数并在新版本的PostNcDestroy中调用delete this来删除对象,从而具有了自动清除的功能。此类窗口对象通常是用new操作符创建在堆中的,但程序员不必操心用delete操作符去删除它们,因为一旦调用DestroyWindow删除窗口,对应的窗口对象也会紧接着被删除。

不具有自动清除功能的窗口类如下所示。这些窗口对象通常是以变量的形式创建的,无需自动清除功能。

所有标准的Windows控件类。

1. 从CWnd类直接派生出来的子窗口对象(如用户定制的控件)。

2. 切分窗口类CSplitterWnd。

3. 缺省的控制条类(包括工具条、状态条和对话条)。

4. 模态对话框类。

具有自动清除功能的窗口类如下所示,这些窗口对象通常是在堆中创建的。

1. 主框架窗口类(直接或间接从CFrameWnd类派生)。

2. 视图类(直接或间接从CView类派生)。

读者在设计自己的派生窗口类时,可根据窗口对象的创建方法来决定是否将窗口类设计成可以自动清除的。例如,对于一个非模态对话框来说,其对象是创建在堆中的,因此应该具有自动清除功能。

综上所述,对于MFC窗口类及其派生类来说,在程序中一般不必显式删除窗口对象。也就是说,既不必调用DestroyWindow来删除窗口对象封装的窗口,也不必显式地用delete操作符来删除窗口对象本身。只要保证非自动清除的窗口对象是以变量的形式创建的,自动清除的窗口对象是在堆中创建的,MFC的运行机制就可以保证窗口对象的彻底删除。

MFC序列化追忆之旅.net 篇5

工作以来一直在做.NET方面的程序,以前自学的C++和MFC许久未碰了。今天恰逢周末休息,闲来翻看一本MFC的书,对序列化(Serialize)部分又研究了一番。在这次故地重游之旅中,我又再一次赞叹于Microsoft Application Framework小组专家们的聪明才智,为开发人员创造出了一个如此优秀的Framwork。

人们都说,“发表是最好的回忆”,我也不妨在此回忆一番,记录下这“MFC 序列化追忆之旅”。

下面是我写的一个MFC 序列化应用例程。展现了如何将一组CBook类型的对象写入文件以及如何再从文件中读取,使“对象永续(object persistence)”。

clearcase/“ target=”_blank“ >cccccc width=”90%“ align=center bgColor=#e7e9e9 border=1>Book.h

#include

class CBook : public CObject

{

DECLARE_SERIAL(CBook)

public:

CString m_strName;

CString m_strAuthor;

CString m_strPress;

public:

CBook

{

// 要使CBook对象实现序列化,必须定义默认构造函数

}

CBook(CString strName, CString strAuthor, CString strPress)

{

m_strName = strName; // 书名

m_strAuthor = strAuthor; // 作者

m_strPress = strPress; // 出版社

}

void Serialize(CArchive &); // 重载基类的Serialize函数

};

Book.cpp

#include ”Book.h“

IMPLEMENT_SERIAL(CBook, CObject, 1)

void CBook::Serialize(CArchive &ar)

{

CObject::Serialize(ar);

if(ar.IsStoring())

{

ar << m_strName << m_strAuthor << m_strPress;

}

else

{

ar >>m_strName >>m_strAuthor >>m_strPress;

}

}

主程序

CBook book1(”Programming Windows“, ”Charles Petzold“, ”Microsoft Press“);

CBook book2(”Programming Windows with MFC“, ”Jeff Prosise“, ”Microsoft Press“);

int nCount = 2;

// 序列化

CFile fileStore(_T(”mybooks.dat“), CFile::modeWrite | CFile::modeCreate);

CArchive arStore(&fileStore, CArchive::store);

CBook* pBooksStore[2] = { &book1, &book2 };

arStore << nCount;

for (int i=0; i

{

arStore << pBooksStore[i];

}

fileStore.Close();

// 反序列化

CFile fileLoad(_T(”mybooks.dat“), CFile::modeRead);

CArchive arLoad(&fileLoad, CArchive::load);

arLoad >>nCount;

CBook* pBooksLoad = new CBook[nCount];

for (int i=0; i

{

arLoad >>pBooksLoad[i];

}

fileLoad.Close();

MFC序列化注意事项:

・要想使某一类型能被序列化,在它类型声明文件(头文件,Book.h)和类型定义文件(Book.cpp)中要分别使用DECLARE_SERIAL和IMPLEMENT_SERIAL宏,

・能被序列化的只能指针型,不能是值型(pBooksStore数组中包含的就是两个CBook类型的指针)。

MFC个人心得 篇6

用MFC制作的工程由很多文件构成,它不能象一般C++程序那样随意在类外定义全局变量,在这里要想定义能被工程内多个文件共享的全局变量和函数必须用一些特殊方法才行。实际上有多种方法可以实现,这里只介绍两种方法。

一、在应用程序类中定义

用MFC生成的工程中都有一个名为CxxxApp的类,它派生于CWinApp类。这个类主要进行程序的初始化,生成文档、视图对象等工作。我们可以把需要全局访问的变量和函数定义为这个类的成员变量和成员函数,就可以实现全局访问了。

从严格意义上讲,这种变量和函数并不是全局的,因为它仍然只是类中的成员,只是由于我们很容易获得CxxxApp类的指针,所以我们可以在文档、视图、对话框以及各种自定义类中访问到它们,达到与全局变量类似的效果。访问时用函数“AfxGetApp”获得CxxxApp类的指针,用“AfxGetApp()->成员”访问变量或函数。

例:Test.h:(应用程序类头文件)

class CTestApp : public CWinApp

{ public:

int x; //全局变量

int f(int y); //全局函数

…………

};

Test.cpp:(应用程序类程序文件)

int CTestApp::f(int y) //全局函数定义

{ y++;

return y;

}

定义在CTestApp类中的变量和函数可以在其它类中被访问。比如在视图的某函数中要访问变量x和函数f():

void CTestView::xyz()

{

CTestApp *app = (CTestApp *)AfxGetApp(); //生成指向应用程序类的指针

app->x = 0; //访问变量x

int z = app->f(1); //访问函数f()

…………

}

这样,变量x和函数f()可以视作为全局的。

用这种方法实现的全局变量和全局函数虽比较简单,但也有缺点,一是访问不太方便,每次都需要获取应用程序类的指针;再就是把一些与应用程序类本身无关的变量和函数放在里面,使这个类看上去怪怪的,破坏了类的封装。

二、用静态变量和静态函数实现

API函数的那种调用方法,不论在哪个类中只要用“::API函数”就可以调用了。合理利用静态类型(static)可以实现与此相似的全局变量和全局函数。

静态变量和静态函数有如下性质:

若在一个类中用关键字static声明数据成员,则这个数据成员就只存在一个拷贝,无论该类创建了多少个实例,它始终只存在一个,即使该类的实例一个也没创建,它也存在。

若在一个类中用关键字static声明函数,该函数可以用“类名::函数名”方式访问,无需引用该类的实例,甚至这个类的实例可以不存在。

利用这个性质实现的全局变量和函数使用起来很方便。

值得注意的是,全局变量和全局函数最好集中封装,不要在文档、视图等类内部定义,这样用起来才有全局的感觉。

例:1、添加一个没有基类的新类,设类名起为CPublic,姑且称之为公用类

单击“Insert”菜单下的“New Class”命令,选择“Class type”为“Generic Class”,在“Name”栏中填入类名“CPublic”,单击“OK”,则新类建立完毕。

2、包含公用类的头文件,使各个类都能访问它

CPublic的头文件应包含在应用程序类的头文件中,这样在其它类中引用CPublic类时就不需要再包含了。

Test.h:(应用程序类头文件)

#include “Public.h” //包含公用类头文件

class CTestApp : public CWinApp

{

…………

};

3、在公用类中定义全局变量和全局函数,均使用static修饰,静态变量还必须在类外定义和初始化

Public.h:(公用类头文件)

class CPublic

{

public:

CPublic();

virtual ~CPublic();

public:

static int x; //全局变量

static int time; //全局变量

static int f(int y); //全局函数

…………

}

在公用类中对静态变量进行初始化和定义函数体:

Public.cpp:(公用类程序文件)

int CPublic::x = 0; //初始化全局变量

int CPublic::time; //定义全局变量

CPublic::CPublic()

{

}

CPublic::~CPublic()

{

}

int CPublic::f(int y) //全局函数,这里不要再加static

{

y++;

return y;

}

4、全局量的使用

使用变量:CPublic::变量名

使用函数:CPublic::函数()

如在视图的某函数中访问变量x和函数f():

void CTestView::xyz()

{

CPublic::x = 0; //访问变量x

CPublic::time = CPublic::f(1); //访问函数f()

…………

}

在其它类中访问x、time和f()的方法与此相同,

5、几点注意:

① 由于静态量可独立于类存在,不需要生成CPublic类的实例。

② 静态数据成员的定义和初始化必须在类外进行,如例中x的初始化;变量time虽然没有初始化,但也必须在类外进行定义。由于没有生成CPublic类的实例,所以它的构造函数和析构函数都不会被执行,在里面做什么工作都没有什么意义。

③ 如果静态函数需要访问CPublic类内的变量,这些变量也必须为静态的。因为非静态量在不生成实例时都不会存在。 如:

class CPublic

{

public:

int x; //内部变量

static int f(int y) //全局函数

{

x++;

return x;

};

…………

};

这里x虽为类内成员,但如果不生成CPublic类的实例,就会出现函数f()存在,而变量x不存在的问题。总之,用没有实例的类管理全局量是一个不错的选择,它具有集中管理,使用方便的好处。当然,除非特别必要,全局量还是少用为好,一个好的编程者决不会随意滥用全局量的,一个封装做得不好的程序,在修改维护时会让你吃足苦头。

春运个人心得体会心得总结 篇7

春运个人心得体会心得总结

2012 春运心得体会 1 月15 日,是我春运志愿者学习生活的第一天,早上6 点,带着倦意起床,洗漱完毕 后随便吃了点早餐,7 点踏上了去往福州火车站的公交车,快8 点的时候到达了目的地,火 车站。第一天,我被分配到了西进站口,主要是负责引导旅客有序进站和检票工作。在工作 中,我体会到了站内工作人员的辛苦和春运人流量的庞大,一天下来,感到非常的累,但在 引导旅客进站的过程中,锻炼了自己的毅力。16-19 日,我被分配到了重点旅客候车厅,在这几天的志愿者工作中,我觉得我们应该 更加积极的帮助那些行动不便的旅客,不管多苦多累不忘给他们一个微笑,让他们感到温暖, 毕竟他们回一趟家不容易。在帮助他们的过程中,我自己也很开心,而且还锻炼了自己与陌 �1�7�1�7�1�7人的沟通能力,这也算是社交能力有了提升吧!20-21 日,我被分配到了电梯口,负责电梯前的秩序,引导旅客乘上电梯和楼梯,在这 过程中,有了一些管理方面的感悟,怎样让人更有效率的上电梯。在过去的几天里,看到许多、听到许多、想过许多、学到许多。微笑、热情、承受, 无论如何,作为一个志愿者,首先要热情,学会微笑,并能够承受。让我明白“有困难就找 志愿者,有时间就做志愿者”的真正含义。在这 7 天的工作中,我学到了很多,锻炼了自己的毅力,沟通能力和耐力,还有很多 感悟,这些都使我受用终生。这种社会实践有很多好处,俗话说:“宝剑锋从磨砺出,梅花 香自苦寒来”。所以,我以后会多参加这类的实践,为将来打下基础。

论文心得-毕业论文的个人心得 篇8

在我看来,本科生的毕业论文不仅仅是一个理论课题的研究,它也包括了对于一个学生综合素质培养的最后一个整体式的强化,让我们能够养成科学的实验习惯,养成逻辑的思维方式,最关键、最重要的是让我们能够独立思考,我想这是毕业论文的根本目的所在,现在的大学教育,局部细化在滋生,总体水平在下降,作为一所有着悠久历史的名牌大学,她应该有着自己发展的明确目标,对于学生的整体素质的培养是一所学校持续发展并壮大的根本动力,如果一所学校连这种要求都达不到,那么衰落将会是最终结果。

当然会有人说,每所大学都是这样想的。我不否认不以培养学生为根本任务的大学确实占少数,但是我可以确定的说,没有引导学生向自主发展,向自我意识萌芽发展,向素质综合发展的学校,不在少数。

现在的社会发展的这么迅速,一方面,丰富了人们的物质生活,而另一方面也使人们的精神生活开始匮乏,那些所谓的可以减压的东西,不能称之为精神食粮,这方面可以从这个社会对于高技术人才,高思想高度人群的尊重程度来确定。最直接的例子是,近代的中国没出几个能够影响全中国社会的思想人物。

说这么多题外话,无非是为了回到主题,大学四年的生活,对于我来说是丰富多彩的,虽然没有在学习方面取得多么突破性的进展,但是过的很充实,因为我发现在这所名牌大学里,在这群优秀的同学旁边,自己进步了很多。学校的老师们传道、授业、解惑,一年年,一届届,而作为学生,我们应该怎样去自主发展,去自我萌芽,去填补自己的空白,加强自己的强项。我参加社团活动,努力加强策划及处理事情方面的能力;我参加多个社团,加强我协调自己时间的能力以及学会跟不同的人打交道;我进政府部门,了解政治最皮毛的习惯性思维方式;我进外企参观,了解让很多人向往的机构的运作;我参加社会实践,让自己的接触社会;我尝试创业,体验自己奋斗的艰辛;我应聘做管理者;为了证明自己的实力,验证自己的理论;我认识形形色色的人,为了加强沟通能力;我去做销售,为了培养自己交流以及心理学方面的能力。我做了这么多事情,不是为了让自己的大学更加完美,真正的目的是为了整体提高自己的综合素质。而做毕业论文,我依然有自己的看法,我在跟自己做斗争的时候,曾经想过放弃,简简单单的度过这段时间,做个平庸的毕业者,拿一份没有甚么含量的拼接的东西上交就可以了。但是最后我说服了我自己,既然花了这么多的时间去做了,为什么提高效率,把它做好呢?有了结论的我开始真正的投入自己的时间、精力以及思维。虽然我不是做实验最勤快的那个,但是我至少保证了自己百分百的去投入这件事情。

真正的投入,确实没有让我失望。渐渐的,我开始有了小小的成就感,从一开始的老师同师姐的领着做,逐渐的变成了跟老师商量着做,最后是一小段时间的自己做。虽然这段过程不算甚么大变化,但是在我的心理可是不小的变化,因为我不仅要有实验操作,还需要自己的思考,自己的判断。因为我不希望自己是一个类似操作实验员那样去被动的做些东西出来,我要的是自己整体的参与,我做这件事情,为什么要去做,为什么要这样去做,有没有比这更好的方法,可不可以进行优化,出现这种结果究竟为什么,怎么样去排除或者验证自己和别人的分析或猜测。这些为什么里面本身就是一个精彩的世界,况且一个精彩的过程让我也有了一个精彩的收获,虽然不能说最后得到的结果非常完美,但是我至少得到了比预期还要多的东西。我开始规范自己之前培养的实验技能;开始明白那些规范到底为什么是必要的;开始学会观察一些平常很多人会以为理所当然的东西,并从其中发现一些东西;开始用自己学过的理论知识去优化某些过程;会认真的思考;会非常潜心的研究一些仪器怎样才能实现更快更准的操作;开始对于我没有接触过的仪器有了操作的欲望和信心。这些对于一个本科学生来说都是非常大的突破。而我认为最重要的一点是:心态。了解我的人都知道,我做事是风风火火那种,脾气又比较急,很多事情处理起来很快,但却不是很周到,因为要做实验,所以经常在实验室的时候一待就是接近一天,那种疲倦自然不言而喻,但是,更令人沮丧的是,修改了又修改的方案,在测试中完全得不到预期的结果。还有一些时候读数不稳定,本来只需要读三次数据的同一个试样竟然要读三十几次才能稍微稳定些,本着对于实验数据的忠实,我不得不一遍又一遍的去做重复过千百次的事情。渐渐的,我开始有了小小的耐心,渐渐的我开始在非常嘈杂的环境中能够平心静气的去滴定,开始远离烦躁,心静如水的心情,让自己思想又上了一个台阶。

一个人就一个人读书心得体会 篇9

有一天,当你面临了诸如是否继续求学,或者是否改行之类的人生大难题时,你会怎样解决问题呢?一般来说,面对问题有三种解决方式,一种是不去管它,船到桥头自然直;一种是找别人要答案,父母亲人、朋友或者专业人士;第三种方式是自己找自己要答案。

不去管它,问题仿佛会自然而然消失……其实只是潜伏成更棘手的问题;找别人要答案,除非你是没有自己思想的提线木偶,否则他人的建议,怎么能那么合你心意?到最后,我们终究还是要学会自己给自己答案。

学会自己向自己提问,自己思考,自己解决,自己承担——是刘同认为一个人独立最重要的呈现方式。独立是指单独的站立或者指关系上不依附、不隶属。依靠自己的力量去做某事。很多人谈:经济独立、精神独立、思想独立……但不论是哪种独立,其实都代表着一个人依靠自己解决问题的能力。

刘同在《一个人就一个人》这本书中,将独立的能力化为个体“一个人”的能力。一个独立的人,不是单纯地和身边人相互扶持相互依靠;而是因其足够独立,所以能够吸引独立的他们。很多人认识刘同,是从《谁的青春不迷茫》、《你的孤独,虽败犹荣》开始,这两本书指引了无数年轻人成长。而《一个人就一个人》,更加展现了刘同思想的成熟。

若说前两本如烈酒入喉,能够激起人一时的激情;那《一个人就一个人》便如佳酿,余味无穷。

一个人,那就一个人

有两种阶段你必须度过:难过的事情找不到人倾诉;开心的事情找不到人分享。——刘同

人天生就有集群属性。出生希望有小家、大家一起组成家庭,学习希望有班级群体,进入社会希望有守望相助的小团体……很多初入社会的青年觉得自己要做的第一件事是找几个人,建立几段稳固的社会关系,获得友情、爱情、事业,才算不枉走一遭。但其实一个人只有不再依赖任何关系,都能独立面对世界,才能与外面的世界平等对待;否则,我们在世界面前永远是渺小无力的。

你站在那里,就是一个人,是一道风景。如果你失去一个人的能力,那你哪怕在自己的世界里,也是扮演配角;而配角,永远是依赖主角生存的。刘同笔下的所有人,卖鱼粉凤姐也好,陈默也好,刘同本人也好,他们都有一种共同的能力:在自己的世界里,做主角;在他人的世界里,做配角。

无论相遇时间短长,遇见过,珍惜过;虽然最后我还是一个人走,但不遗憾,也不惶恐。一个人,那就一个人;一个人是所有世界,也是所有生活。

两个人,也要一个人

如果你能够在某个人面前直言不讳,那么一定要珍惜他,因为在他面前,你是你自己。——八月长安

独立是每个人都应该具备的能力,但独立并不等于孤独。亲情、友情、事业,并不应以独立之名不被重视。刘同要强调的是:哪怕你是两个人,也要保持一个人。在任何亲密关系中,都要保持自己独立的状态。这是让任何亲密关系保鲜最重要的原则。就像婚姻,有人婚后渐渐麻木,觉得失去了自己,全靠小孩维持婚姻;而有的夫妻,每天都有各自的世界,不时互相分享,仿佛在过两段人生。

好的亲密关系,亲密又疏离,相互依赖又相互独立。在你的世界里,你做主角,我做配角;在我的世界里,你也要主动地做配角。这本书流露出的人生感慨和豁达情怀,非处世不深的年轻人所能经历。就像刘同本人说的:多年前的“孤独”,能让他逐渐拥有自己的世界,不羡慕别人;现在的《一个人就一个人》,则是他拥有了自己的世界之后,开始用这样的目光去欣赏和探索外界。

个人工作心得 篇10

从2018年到现在,我一直很庆幸参加了这次的srp项目。不论从团队性的项目本身,还是在这过程中通过老师、学姐、同学的帮助,或是从中对严重的环境污染的感触,任何一项都足以让我获益良多。重点表现在一下几个方面:

1.个人的学习能力的培养。在项目的最初,除了老师的指导外,更需要我们自己查阅资料、编写材料、处理数据、分析数据等过程。通过这些的亲自实践操作,我学会了怎样高效地查阅资料,怎样从中提炼出有用的东西,怎样利用手里、身边有用的资源;同时,也锻炼了我写材料的能力,熟悉了写材料的过程,学习到怎样才能写出有水平的好材料、论文。在团队中也学习到了别人有效的学习方法。对本专业污水中所含物质,处理方法,都有了更深的了解。学会了如何去比较、筛选、判断去选择适合我们研究的方案。三人行必有我师,在一次次对项目的讨论中,自己总能从别人中学习到忽视的东西。

2.协同合作的能力。本项目是一个团队合作的项目,所以一定要在团队合作下才能很好的完成。我们的项目负责人,为每位小组成员分配好任务,为小组工作的顺利进行提供好前提条件。在本次项目中实践阶段,我和另一位小组成员一起完成了由温度对电化学反应效率的实验,我们在遇到温度不能得到很好的控制时,并没有相互抱怨,而是共同想办法,最终也成功的解决,完成了。在团队中,我们不能把所有责任推到一个人的头上,要站在别人角度去思考问题。既然是团队合作,就要有团队精神,学会宽容,也要学会承担,分配到自己头上的任务要尽全力去完成,不推脱、不拖沓,为小组贡献自己的力量,才能保证高效率的完成。

3.创新的思维能力。在项目初期对资料的阅读,我们看到了对此类项目的许多研究,但我们要做这个,就要有自己的创新性,才能与众不同。每个人的观点也会不尽相同,我们要学会说出自己的想法,创新的基点就是胆量,我们要学会在科学的方法上,去培养对事物的认知,锻炼我们的创新力。众所周知的总归不能出彩,别人的成果也终究是别人的,有创新的精神,在研究中便显得尤为重要。

4.不惧失败。在项目过程中,我们也走过不少弯路,本来已经确定的目标在经调查,竟然不能实施,每步我们走的跌跌撞撞,总会有或大或小的问题出现,也受到了很多挫折和打击,但在这种时候,我和我的小组成员都咬牙坚持了下来,并一一克服了重重困难,所以才能取得今天的成果。所以,通过这次的项目,我更加深刻的明白坚持的重要性,无论是学习、工作还是生活,不能轻言放弃,要有迎难而上的精神,才能取得最终的胜利。

个人读书心得 篇11

读书时一门学问,是一门很深很深的学问。。正所谓:“要想皮肤好,早晚用大宝。”读书也是同样的道理,如果你想一下写出一万字的文章,没办法你就得每天都写。海纳百川有容乃大,错不了的,每一个爷爷都是由孙子走过来的,今天我们吃苦卖力的在点灯熬油,为的是什么?此处省略许多字。。读书破万卷,下笔如有神!多么亲切而又俗气的话语,让人不禁想起了那遥远的孩提时代。在那个美好的时代里,网络是初生的,是神圣的,那时候大家上网为的是学习,那时候网络的天空还是蓝蓝的,那时候的文学是纯粹的,那时候抬头仰望45°,是留不下眼泪的,那时候手凉的女孩还是因为贫血缺钙,写的这里我不禁要发出一声呐喊:“到底是世界改变了我们,还是我们改变的世界?”彷徨在人生的大路上,思考着到底是生存还是毁灭?这的确是个问题,或者你会微笑着语重心长的告诉我,走自己的路让别人说去吧。对。这就是要告诉大家的,书曰:“穿自己的鞋,走自己的路,让别人说去吧。”

罗曼罗兰在那个时代就提出过:“从来没有人为了读书而读书,只有在书中读自己,在书中发现自己,或检查自己。”那天翻阅杂史,从中提取了王阳明先生的一句一针见血的名言:“为学大病在好名”读书为了去装,这时候这个读书就像吃饭,善于吃饭的人长个,不善于吃饭的人长膘,你光去吃了,最后个子没长,却增添了一身膘子肉,人家彼得拉克不是也说:“书籍使一些人博学多识,但也使一些食而不化的人疯疯癫癫。”但是我们又不能因噎废食,(心得体会)一日学一日功,一日不学十日空,此处省略一万字。。大家懂得。

其实大家不用为了作业而读书,读书真的是个好事,最后换用余秋雨老先生的话来共勉一下:“读书的最大理由是想摆脱平庸,早一天就多一份人生的精彩,迟一天就多一天平庸的困扰。”

上一篇:沙盘游戏室使用制度下一篇:护理风险管理实施方法