VC++笔记.docx
- 文档编号:24470499
- 上传时间:2023-05-27
- 格式:DOCX
- 页数:12
- 大小:23.46KB
VC++笔记.docx
《VC++笔记.docx》由会员分享,可在线阅读,更多相关《VC++笔记.docx(12页珍藏版)》请在冰豆网上搜索。
VC++笔记
一、对话框初始化函数中做那些事情?
设置按钮显示的图标
BOOLCBUTTONDlg:
:
OnInitDialog()
{
//TODO:
Addextrainitializationhere
m_OK.SetIcon(LoadIcon(AfxGetResourceHandle(),MAKEINTRESOURCE(IDI_BUTTONCON)));//
m_ToolTip.Create(this);//
m_ToolTip.AddTool(&m_OK,"推出");//
}
类似“成员变量.函数”其后的函数是那里的函数?
是自己所属“类”或继承其“基类”的成员函数吗?
如果一个类的成员变量是“普通类型”如:
int、unsignedint、floate等类型的变量,则不会有“成员变量.函数”这种形式,若该成员变量本身就是另一个类(对象),即另一个类的对象作为该类的成员变量,则存在这种“成员变量.函数”,但其调用的函数是其所属类的成员函数吗?
还包括该类的成员吗?
二、在输入对象的成员函数时系统并不给提示?
Visualc++中使用了一种所谓的IntelliSense技术,就是在你定义了一个类函数、一个变量后。
再一次输入该类后,在类后面键入"."或"->"可以自动列出该类的所有函数,这样极大地方便了编程并减少了拼写错误,但有时这种功能会莫名其妙地不能用了,或对某个特定的类无法使用了。
我在编程中就遇到这类问题。
最后终于在MSDN上找到了解决方案。
原因1:
在当前光标之前有语句错误。
解决方案:
检查语句。
原因2:
在注释语句中。
解决方案:
在注释语句中,IntelliSense是无法使用的。
原因3:
在字符串中的双引号内。
解决方案:
在双引号内,IntelliSense是无法使用的。
原因4:
语句自动完成设置有问题。
解决方案:
更改自动完成设置,一般在“工具”->“选项”中。
原因5:
.ncb文件有问题解决方案:
保存文件,退出VC,删除.ncb文件,打开VC即可(我的就是这么解决的)原因6:
包含头文件和目录有问题。
解决方案:
建议使用用VC的“工程”->"设置"来管理头文件。
三、获取主机中所有的逻辑驱动器,以驱动器根路径字符串返回,其函数原型如下:
DWORDGetLogicalDriveStrings(
DWORDnBufferLength,
LPTSTRlpBuffer);
参数:
nBufferLength:
参数lpBuffer所指向的内存空间的大小,以字节为单位。
lpBuffer:
指向存储返回结果字符串的内存空间
返回值:
函数的返回值指明了函数调用是否成功,如果成功则返回缓冲区中返回结果的总长度。
如果返回值大于nBufferLength,说明给定的缓冲区大小不够,返回值是实际需要的大小。
如果返回0,则说明函数运行出错。
使用说明:
这个API实现了与GetLogicalDrives同样的功能,却以一种更直观的方式返回执行结果。
函数执行结果放在lBuffer所指向的内存区域中,此内存区域大小有nBufferLength参数指定,使函数返回结果不至于溢出。
在调用此函数前需保证内存分配。
函数调用成功后,将在缓冲区中依次填入本机所具有的驱动器根路径字符串,假如系统中有5个逻辑驱动器“C:
\”、“D:
\”、“E:
\”,“F:
\”、“I:
\”。
执行后在缓冲区中的结果如下:
0x430x3a0x5c0x000x440x3a0x5c0x000x450x3a0x5c0x000x460x3a0x5c0x000x490x3a0x5c0x000x00
也就是连续存放了“C:
\”、“D:
\”、“E:
\”,“F:
\”、“I:
\”这五个字符串(会在每个字符串后加一个‘\0’结束符,在所有卷标字符串的最后在加一个结束符)。
实例代码如下:
#include
#include
#defineBUFSIZE1024
intmain(void){
CHARszLogicalDriveStrings[BUFSIZE];
DWORDiLength;
INTiSub;
ZeroMemory(szLogicalDriveStrings,BUFSIZE);
iLength=GetLogicalDriveStringsA(BUFSIZE-1,szLogicalDriveStrings);
for(iSub=0;iSub printf("%s",szLogicalDriveStrings+iSub); } printf("\n"); return0; } 四、MFCclass和Genericclass和FormClass使用详细区别 MFCclass: 建立基于MFC的类,比如视图,frame,控件等等,从MFC类库派生,可以在Baseclass中选择父类。 Genericclass: geniricclass就是自己写的类,普通C++类,没有派生始祖,包含头文件后,可以使用任何MFC类。 使用genericclass,它不选择MFC中的类作为基类,也就是没有基类,或者你手工在Baseclass中填上父类。 输入任何类做基类 genericclass,是一个一般的类,可以不从mfc的类中继承,也可以从mfc的类中继承,但自己一定要注意亲自加入mfc的头文件,同时不会有消息映射表,这些都要手动添加。 FormClass: 应该是指MFC中带界面资源模板的类,一般都需要选择模板ID,包括CFormView,CRecordView,CDAORecordView和CDialog四种类 但是VC会根据实际项目的类型是dialog,SDI,MDI来选择classvizard里面下拉框中的可选类。 基于dialog的项目,添加formclass时只显示CDialog,前三种不显示(它认为,那三个view类在对话框中不必要使用)基于SDI或MDI的项目,添加formclass时下拉框显示上述4种类。 FormClass是窗口类,一般情况下用这项时,VC会同时为你生成相应的窗口MFCClass表示从MFC类库派生,可以在Baseclass中选择父类。 FormClass表示从CDialog派生的类,可以在DialogID中选择对话框资源ID。 GenericClass表示从其它类型的类派生,可以在Baseclass中填上父类 _int64是个什么类型? 父类和基类是一个意思! 五、类的删除方法? 一般在文件视图中把那个类的h和cpp文件删掉,别忘了你的还有资源里的dialog资源,则可以选中该资源,然后用delete键删除。 再看看类视图中还有没有。 如果还有,到工程所在的目录,把*.clw和*.ncb*.opt文件还有你的那个类的文件删掉,再进到工程里检查。 六、一个最基本的单文档视图的MFC程序,包含CxxApp、CxxDoc、CMainFrame、CxxView和CAboutDlg五个类。 它们在程序开始运行时被创建的顺序是: CxxApp、CxxDoc、CMainFrame、CxxView、CAboutDlg。 C**App()定义了窗体加载之前需要做的预处理。 比如一个加密的软件,打开后提示用户输入密码。 这个事件的处理程序就要写在C**App()的InitInstance(中。 CMainFrame()包含了对工具栏、状态栏、窗口的定义。 C**View包含了最主要的处理功能,如菜单操作、快捷键、用户交互操作等。 CAboutDlg定义了ABOUT对话框。 其中,前四个都是在程序主窗口出现之前被创建的,CAboutDlg是在“关于”对话框弹出时被创建的 1CAboutDlg//这个是关于对话框里面是构造和析构2CMainFrame//主框架`是在窗口生成之前准备工作全在这吗? 3CTestApp//这个是什么`initlnstance()在这里也是初始化什么对象? 4CTestDoc//这是文档`是管理哪些文档`对初学者来说很少用呐? 5CTestView视图`这个常用OnDraw我了解一些`我想知道`是不是默认就调用一次? 还有个问题啊`我想加个音乐`虽然加成功了`但是`我一直不明白加在哪个函数里`运行就有音乐? 看过孙鑫的教程后来忘了`各位高手各抒已见,互相学习 需要系统地学习一下。 CTestApp是基于WinApp的,WinApp封装了程序的主入口WinMain,WinMain就和c语言的main函数地位一样,是Win32程序的入口。 在MFC的封装中,一个程序启动,Windows调用WinMain,这个WinMain函数现在由MFC事先写好藏好了,你不能也不需要修改,在这个预定义的WinMain里面会调用CWinApp的InitInstrance函数。 你仔细看你CTestApp: : InitInstrance函数,在这里一个CMainFrame的对象被创建,文档模板被创建,主窗口通过ShowWindow(SW_SHOW)被显示出来。 CMainFrame是个框架,是你整个应用程序的主窗口,他负责管理应用程序的菜单,工具栏,状态栏等。 中间的区域,成为客户区,由View类来管理,View类也是一个窗口,他是MainFrame的子窗口。 OnDraw函数负责绘制客户区的内容,该函数会被多次调用,他可以被你自己调用,比如你调用View类的UpdateWindow,或者在Document类中调用UpdateAllViews等等,MFC自动会调用OnDraw。 他还会被Windows调用,Windows在需要刷新窗口的时候发送给窗口WM_PAINT消息,MFC事先已经预定义了,在响应WM_PAINT消息的时候会调用OnDraw。 何时Windows会发送WM_PAINT呢,比如窗口从最小化还原,比如窗口被用户改变了大小等等。 这部分内容最好看看WindowsGDI,WindowsGDI是Windows操作系统整个可视化界面的基础。 然后你最后一个问题,何时才能被播放音乐。 你仔细想想就容易得到答案了,整个程序从App类的InitInstrance开始,在InitInstranc 学过PE文件格式,你就明白,程序在进入WinMain之前要做很多事情,比如初始Dos头,分配函数表,初始化全局变量。 之后才进入程序入口(WinMain) MFC对WindowsAPI进行了封装。 在用向导编译成的二进时代码,MFC编译器链接器把源文件编译成PE文件格式存储在磁盘上。 程序执行的时候,从PE文件头开始执行,在进入Winmain函数之前,进行一系列的必备的初始化。 MFC对这一系列的过程进行了封装。 提供给编程人员的第一个裸露程序入口就是CWinApp的InitInstance(),其实程序的入口依然是WinMain()函数。 大家都知道,每个程序都有拥有一个进程,每个进程至少有一个线程就是主线程。 CWinThread类是MFC用来封装线程的,这个主线程就是在WinMain函数中创建的,包括UI线程和工作者线程。 因此每个MFC程序至少使用一个CWinThread派生类。 被MFC程序员熟知的CWinApp应用类就从这里派生。 InitInstance是CWinThread的一个虚函数,InitInstance就是“初始化实例”的意思,可见,它是在实例创建时首先被调用的。 应用程序总要重载这个虚函数,进行系统设置,创建运行环境。 例如,主窗口一定要在InitInstance()中创建,因为该函数退出后就进入该线程的消息循环。 MFC执行流程。 _tWinMain(WinMain的别名,用define替换的)-》AfxWinMain->初始化线程,调用InitInstance初始化窗口,调用Run函数进入消息循环。 七、MFC中dodataexchange的作用: 将界面上的控件与一个变量或者一个类对象相关联! 数据交换。 例如文本框控件当关联了一个变量的时候就需要在这个控件和这个变量之间通过DoDataExchange建立联系;然后通过调用UpdateData选择当用户更改了输入的时候是否更新变量值或更改程序变量值后是否更新界面 操作注意问题: . 1.调用UpdateData选择当用户更改了输入的时候是否更新变量值 2.当在按钮中,引入另一个类时,必须在未设置按钮函数时候,就已经创建好将要引入的类,否则会造成无法读取要引入的类,! ! ! 八、GetBuffer()主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。 CString: : GetBuffer有两个重载版本: LPTSTRGetBuffer();LPTSTRGetBuffer(intnMinBufferLength); 在第二个版本中,当设定的长度小于原字符串长度时,nMinBufLength=nOldLen,该参数会被忽略,不分配内存,指向原CString; 当设定的长度大于原字符串本身的长度时就要重新分配(reallocate)一块比较大的空间出来。 而调用第一个版本时,应如通过传入0来调用第二个版本一样。 是否需要在GetBufer后面调用ReleaseBuffer(),是根据你的后面的程序是否需要继续使用该字符串变量,并且是否动态改变其长度而定的。 如果你GetBuffer以后程序自函数就退出,局部变量都不存在了,调用不调用ReleaseBuffer没什么意义了。 这是一个非常容易被用错的函数,主要可能是由于大家对它的功能不太了解。 其实点破的话,也不是那么深奥。 GetBuffer(intsize)是用来返回一个你所指定大小可写内存的成员方法。 它和被重载的操作符LPCTSTR还是有点本质区别的,LPCTSTR是直接返回一个只读内存的指针,而GetBuffer则是返回一个可以供调用者写入的内存,并且,你可以给定大小。 下面是个简单的,但也是非常典型的例子: intreadFile(CString&str,constCString&strPathName) { FILE*fp=fopen(strPathName,"r");//打开文件 fseek(fp,0,SEEK_END); intnLen=ftell(fp);//获得文件长度 fseek(fp,0,SEEK_SET);//重置读指针 char*psz=str.GetBuffer(nLen); fread(psz,sizeof(char),nLen,fp);//读文件内容 str.ReleaseBuffer();//千万不能缺少 fclose(fp); } 上面的函数是GetBuffer函数最典型的用法了,其实它就相当于申请一块nLen大小的内存,只不过,这块内存是被引用在CString对象的内部而已,这是非常有效的一种用法,如果不直接用GetBuffer函数来申请的话,那么你必须用new操作符(或者malloc()函数)在CString的外部申请,然后再将申请的内存拷贝到CString对象中,显然这是一个非常冗余的操作,会使你函数的效率大大下降。 ReleaseBuffer函数是用来告诉CString对象,你的GetBuffer所引用的内存已经使用完毕,现在必须对它进行封口,否则CString将不会知道它现在所包含的字符串的长度,所以在使用完GetBuffer之后,必须立即调用ReleaseBuffer函数重置CString的内部属性,其实也就是头部信息。 补充一下: GetBuffer说白了就两个功能: 1: 就是将CString里面的内存交到外部一个来处理,外部可以直接修改它的内容。 2: 重新修改CString的内存大小,这个数值不包含null结尾符。 另一个典型的用法: 就是将CString里面的内容变为int或long型,需要先获取里面的内存指针。 这样就可以先GetBuffer(内存大小)方便直接转换。 如果在外部修改了CString里面的内容,在重新使用CString之前,需调用ReleaseBuffer()也就是说,ReleaseBuffer不需要每次都调用。 CString: : ReleaseBuffer只是一个形象的说法,完全是跟GetBuffer对应而起的名字。 我觉得如果函数名改为UpdateBuffer的就不会出现这种误解 先来看一段代码: CStrings="hello"; LPTSTRps=s.GetBuffer(); strcpy(ps,"hi"); s.ReleaseBuffer(); 此时调用s.GetLength()获取的值是2,正确无误。 但如果注释掉s.ReleaseBuffer()这一行,s.GetLength()获取的值则是5,哈哈,错了。 怎么会这样呢,我们来看看MFC中ReleaseBuffer的代码: voidReleaseBuffer(intnNewLength=-1) { if(nNewLength==-1) { nNewLength=StringLength(m_pszData); } SetLength(nNewLength); } 很明显ReleaseBuffer只有一个作用,就是更新字符串的长度。 CString内,GetLength获取字符串长度并不是动态计算的,而是在赋值操作后计算并保存在一个int变量内的,当通过GetBuffer直接修改CString时,那个int变量并不可能自动更新,于是便有了ReleaseBuffer。 其实,计算长度还能用strlen(),这个就算不ReleaseBuffer也不会出错,但如果不ReleaseBuffer,在+=这种赋值时字符串很可能会跟想要得到的不同。 九、给类添加函数与添加消息相应有何区别? 消息相应的添加和类函数的添加方式有何不同? 什么时候用消息相应? 何种情况下采用类函数? 如: OnCancel()函数的添加和WM_TIMER消息相应的添加 十、resource.h中的宏定义都用作什么? 例如: #defineIDM_ABOUTBOX0x0010 #defineIDD_ABOUTBOX100 #defineIDS_ABOUTBOX101 #defineIDD_OUTPUTGIF_DIALOG102 #defineIDR_MAINFRAME128 #defineIDC_FILENAME1000 #defineIDC_BROWSE1001 //Nextdefaultvaluesfornewobjects #ifdefAPSTUDIO_INVOKED #ifndefAPSTUDIO_READONLY_SYMBOLS #define_APS_NEXT_RESOURCE_VALUE129 #define_APS_NEXT_COMMAND_VALUE32771 #define_APS_NEXT_CONTROL_VALUE1002 #define_APS_NEXT_SYMED_VALUE101 #endif #endif 注意: IDC_BROWSE类似的标识是用户自己设定的各个控件的ID号,这些ID号系统会自动赋给相应的数字值以便在程序运行过程中用于实现相应的控件的操作。 在学习过程中,必须保证例程中控件的ID号等标识符与自己所建立的控件的标识符一致才能进行对比分析,负责往往分析不出结果,特别使用beyondcompare软件进行对比分析时,这一点也是自己常常出错的地方。 当然,还有一部分是系统自行设定的ID号,如: #defineIDOK1这些是在系统\VC98\Include\WINUSER.H。 在Include文件夹中存放这系统自带的许多头文件,其中定义了众多常用的系统标识符。 #defineIDOK1 #defineIDCANCEL2 #defineIDABORT3 #defineIDRETRY4 #defineIDIGNORE5 #defineIDYES6 #defineIDNO7 #if(WINVER>=0x0400) #defineIDCLOSE8 #defineIDHELP9 十一、对话框构造函数中为什么初始化部分的程序为什么是灰色标识? 十二、下列是程序中给出的一些提示信息。 //NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32 //NOTE: theClassWizardwilladdDDXandDDVcallshere //NOTE: theClassWizardwilladddatamembershere //TODO: Addextrainitializationhere 十三、控件的ID号与联系控件的变量之间的关系? CStaticm_ImageDemo;这些与控件关联的变量的类型怎么理解? CEditm_WaterText; CEditm_FileName; UINTm_OriginX; UINTm_OriginY; 十四、为什么要将 //#ifdef_DEBUG //#definenewDEBUG_NEW //#undefTHIS_FILE //staticcharTHIS_FILE[]=__FILE__; //#endif 注释起来,而不注释时结果显示new错误? 十五、怎么建立一个新的对话框类? 在模型树中建立一个对话框类,但没有和对话框资源连接起来。 如何连接? 分别建立对话框类和对话框资源,在选中对话框资源利用类向导建立两者之间的联系;另一种方法是先建立对话框资源,在利用对话框资源类向导建立新对话框类,并同时建立两者之间的联系。 十六、通常建立的程序缺少对话框类是由于其对话框资源设置不合理所导致,通过检查对话框资源的个属性,可以解决这个问题。 十七、complie和bulid功能有什么区别? 十八、对调试中各种变量及数据的变化并没有深刻的理解。 例如this指针、消息、地址等。 。 可以查找一些相关的详细介绍书籍。 十九、怎么理解数据在内存中的存放形式? 如: 地址内存上存储的数据值 0012FE98296B(低位)D600(高位)060000其中自左向右: 按照167+166+165+164+163+162+161+160=00D66B29 其中: 32位计算机其内存地址用了8位十六进制数据表示,该地址上存放的数据也是用8位二进制数据表示(自左向右8位数据,多余的数据位无效! ) 若是32位计算机则表示: 该内存存放的数据为32
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC 笔记