孙鑫VC教学视频笔记全.docx
- 文档编号:12756362
- 上传时间:2023-04-21
- 格式:DOCX
- 页数:47
- 大小:53.42KB
孙鑫VC教学视频笔记全.docx
《孙鑫VC教学视频笔记全.docx》由会员分享,可在线阅读,更多相关《孙鑫VC教学视频笔记全.docx(47页珍藏版)》请在冰豆网上搜索。
孙鑫VC教学视频笔记全
第一课
基础
1.MFC生成的C++源文件中都有StdAfx.h,此文件包含了常用的AFX函数的声明,其中有afxwin.h,此文件包含了CRECT,CPoint,CWnd等许多类及其方法的声明。
2.Project->Setting->Debug可以加入命令行参数。
3.在SDK中要加入"windows.h"和stdio.h。
因为LoadCursor,MessageBox等函数的声明在这个文件中。
4.创建一个完整的窗口的四个步骤SDK,1设计窗口类,2注册窗口类,3创建窗口,4显示窗口
5.函数名可以代表函数代码的首地址,即可作为函数指针。
6.要查看VC数据类型,可以在MSDN中输入“BOOL”然后选择“DATATYPE”。
7.atof将字符串转化为float,atoi将字符串转化为int型。
8.所有从CWnd类派生的类都有m_hWnd句柄。
9.变量的生命周期:
可以认为出了包含它的大括号,这个变量的生命周期结束。
所以全局变量的声明位于所有大括号之外。
但是用new声明的变量和用static声明的变量除外。
10.SDK示范程序,见下面。
11.sprintf格式化字符,其头文件为stdio.h,在MFC中格式化字符用CString.Format
12.GetDC()与ReleaseDC()要成对使用,否则会内存泄漏。
同样,BeginPaint()与EndPaint()。
13.GetStockObject()得到画笔、画刷、字体、调色板的句柄,使用时必须用类型转换。
14.什么时候用NULL,什么时候用0.答,对指针赋值时用NULL,对变量赋值时用0.
15.什么是野指针?
答:
将指针指向的变量的内存释放后,此指针即变成野指针!
如何避免野指针?
答:
将此指针指向NULL即可。
p=NULL;.
16.SDK代码流程:
#include"windows.h"//包含头文件LoadCursor,TextOut等函数#include"stdio.h"//包含sprintf,printf等函数LRESULTCALLBACKMyProc(...);//声明回调函数intWINAPIWinMain(){WNDCLASSwndcls;//设计窗口类wndcls.hcursor=LoadCursor();//初始化....RegisterClass(&wndcls);//注册窗口类hwnd=CreateWindow(...);//创建窗口ShowWindow(..);//显示窗口UpdateWindow(..);MSG;//定义消息结构体while(GetMessage(...))//消息循环{...}return0;}
LRESULTCALLBACKMyProc(...)//实现回调函数{switch(uMsg){caseWM_CHAR:
break;...}}
第2课
1.定义结构体和类时别忘记在最后加入";"号!
例如ClassPoint{intx;inty;};2.#include
<>不查找运行时目录,""查找运行时目录!
3.类的定义中,如果未指明成员类型,则缺省为private.而结构体中则缺省为public.
4.引用:
引用经常用在函数的传参上。
另外数值交换函数也经常用引用。
例change(int&x,int&y){inttemp;temp=x;x=y;y=x}调用时即可以用inta=3;intb=4;change(a,b);一般不用指针来作为参数进行数值交换。
因为会引起歧义。
5.通常将类的定义放.h文件,而将其实现放在cpp文件中,别忘记了在cpp文件中#include"xxx.h"
6.如何防止类的重复定义?
用#inndefPoint_H_H#definePoint_H_HclassPoint{};#endif来防止
7.源文件cpp文件单独编译成obj文件。
最后由链接器将与将要使用到的C++标准库类链接成exe文件,头文件不参加编译。
所以在cpp文件中别忘记了加入#include"xxx.h"
8.函数的覆盖,在子类中重写父类的函数,此时采用早期绑定的方法。
如果加入了virtual,则将采用迟绑定的技术,在运行时根据对象的类型确定调用哪一个函数。
此迟绑定技术是MFC的类的继承的精髓。
9.强制类型转换。
如果CFish从CAnimal派生而来。
则可以将鱼的对象转换为CAnimal的对象,而反之则不行。
从现实中理解也是正常的,鱼可以是动物,而动物却不是鱼。
再如int可以强制转换成char型。
而反之则出错。
第3课
VC基础
1.在main或WinMain之前,全局变量已经被分配内存并初始化了。
2.在MFC中在WinMain之前有个theApp全局变量先被构造并被初始化,而由于子类构造函数执行前,其父类的构造函数先被执行,所以CTestApp的父类CWinAPP的构造函数先执行。
产生了theApp对象后,在WinMain()中的指针*pThread和*pApp就有了内容。
3.MFC大致流程:
CTestApptheApp;//构造全局对象WinMain(){AfxWinMain();//调用下面的函数}AfxWinMain(){pThread->Initinstance();//初始化工作和注册窗口类,窗口显示和更新pThread->Run();//消息循环}而在BOOLCTestApp:
:
InitInstance()中的代码CSingleDocTemplate*pDocTemplate;pDocTemplate=newCSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CTestDoc),RUNTIME_CLASS(CMainFrame),//mainSDIframewindowRUNTIME_CLASS(CTestView));AddDocTemplate(pDocTemplate);完成了将这三个类关联起来的工作。
4.如何在单文档文件中显示一个CButton的对象?
在CMainFrame:
:
OnCreate()中定义一个CButton的对象btn;然后调用btn.Create("维新",WS_DISABLED|WS_CHILD|WS_VISIBLE|BS_AUTO3STATE,CRect(0,0,300,100),/*GetParent(),*/this,123);注意点:
(1).此处btn不能是局部变量,否则它的生命周期太短,将不能显示。
(2).在create函数的第二个参数中加入WS_VISIBLE参数才行。
否则必须调用ShowWindow也可以在view的OnCreate消息响应函数中加入(3).CButton类的定义头文件在afxwin.h中,而stdafx.h包含了afxwin.h,所以可以直接使用。
因为MFC中的每一个类中都有#include"stdafx.h"的声明。
第4课
画图
1.在单文档中view挡在MainFrame的前面。
此时如果编写针对MainFrame的mouseClick事件,将不会有反应。
2.消息响应会在3处修改代码,1处是在头文件中,//{{AFX_MSG(CDrawView)afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);afx_msgvoidOnLButtonUp(UINTnFlags,CPointpoint);afx_msgvoidOnMouseMove(UINTnFlags,CPointpoint);//}}AFX_MSGDECLARE_MESSAGE_MAP()另一处是cpp文件的beginMessageMap和EndMessageMap之间,BEGIN_MESSAGE_MAP(CDrawView,CView)//{{AFX_MSG_MAP(CDrawView)ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()//}}AFX_MSG_MAP//StandardprintingcommandsON_COMMAND(ID_FILE_PRINT,CView:
:
OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT,CView:
:
OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView:
:
OnFilePrintPreview)END_MESSAGE_MAP()最后是要有函数实现的代码。
voidCDrawView:
:
OnLButtonDown(UINTnFlags,CPointpoint){//TODAddyourmessagehandlercodehereand/orcalldefaultm_ptOrigin=m_ptOld=point;m_bDraw=TRUE;CView:
:
OnLButtonDown(nFlags,point);}
3.画线:
定义一个成员变量保存mouseDown的点m_Point1)API函数方法画线用HDC
2)用CDC类成员函数画线。
此时别忘记ReleaseDC3)用CClientDC4)用CWindowDC,用它甚至可以整个屏幕区域画线。
下面是上面4种方法的代码/*HDChdc;hdc=:
:
GetDC(m_hWnd);MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);LineTo(hdc,point.x,point.y);:
:
ReleaseDC(m_hWnd,hdc);必须成对使用。
*//*CDC*pDC=GetDC();pDC->MoveTo(m_ptOrigin);pDC->LineTo(point);ReleaseDC(pDC);必须成对使用。
*/
//CClientDCdc(this);/*CClientDCdc(GetParent());dc.MoveTo(m_ptOrigin);dc.LineTo(point);此处不需要ReleaseDC,因为CClientDC会自动释放DC*/
//CWindowDCdc(this);//CWindowDCdc(GetParent());/*CWindowDCdc(GetDesktopWindow());//此时可以在整个屏幕上画线。
dc.MoveTo(m_ptOrigin);dc.LineTo(point);*//*CPenpen(PS_DOT,1,RGB(0,255,0));CClientDCdc(this);CPen*pOldPen=dc.SelectObject(&pen);dc.MoveTo(m_ptOrigin);dc.LineTo(point);dc.SelectObject(pOldPen);*/
5)用Bitmap填充所画的矩形。
CBitmapbitmap;bitmap.LoadBitmap(IDB_BITMAP1);CBrushbrush(&bitmap);CClientDCdc(this);dc.FillRect(CRect(m_ptOrigin,point),&brush);//CBRUSH:
:
FromHandle是静态成员函数,所以可以用下面的方法调用。
CBrush*pBrush=CBrush:
:
FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));CBrush*pOldBrush=dc.SelectObject(pBrush);dc.Rectangle(CRect(m_ptOrigin,point));dc.SelectObject(pOldBrush);m_bDraw=FALSE;6)用其它颜色画线CClientDCdc(this);CPenpen(PS_SOLID,1,RGB(255,0,0));CPen*pOldPen=dc.SelectObject(&pen);//选中红色画笔if(m_bDraw==TRUE){dc.SetROP2(R2_BLACK);//设置绘画模式dc.MoveTo(m_ptOrigin);//dc.LineTo(point);dc.LineTo(m_ptOld);//dc.MoveTo(m_ptOrigin);dc.MoveTo(m_ptOld);dc.LineTo(point);//m_ptOrigin=point;m_ptOld=point;}dc.SelectObject(pOldPen);
4.MFC中隐式的包含了windows.h。
为什么?
因为在AFXV_W32.h文件中:
//ThisisapartoftheMicrosoftFoundationClassesC++library.//Copyright(C)1992-1998MicrosoftCorporation//Allrightsreserved.在AFXWIN.h中//Note:
WINDOWS.HalreadyincludedfromAFXV_W32.H5.如何从句柄获得对象的指针?
答FromHandle
6.类的静态成员函数可以由类名直接调用,也可以由对象调用。
可以认为静态成员函数并不属于某个对象,它属于类本身。
程序运行伊始,即使没有实例化类的对象,静态成员函数和静态成员变量已然有其内存空间。
静态成员函数不能访问非静态成员变量!
静态成员变量必须在类的外部初始化。
当然如果并不打算用到静态成员变量,此时你可以不初始它。
7.理解代码区,数据区,堆,栈!
请见下面的简介:
于一个进程的内存空间而言,可以在逻辑上分成3个部份:
代码区,静态数据区和动态数据区。
动态数据区一般就是“堆栈”。
“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。
进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。
一个堆栈可以通过“基地址”和“栈顶”地址来描述。
全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。
程序通过堆栈的基地址和偏移量来访问本地变量。
8.抽空看看李维的《悟透Delphi》有一回,我梦见自己变成了计算机时空世界里的一个对象。
随着计算机世界的不断发展,我们这些对象已经不再象原始时代的对象那样仅仅为了获得生存的资源而不停的忙碌。
我们的思想空前活跃,我门不但思考我们为什么要在计算机世界里生存和运行,而且还大胆的研究和探索计算机世界的未知奥秘。
我们已经知道整个计算机世界都是由字节这一基本粒子构成,而字节又是由八个更细小的位粒子构成;我们还知道物质不灭定律,即任何一个对象的灭亡,只意味着对象结构的解体,并不会减少计算机世界中的任何字节或位粒子,而着这些物质又可能成为别的对象的一部分;甚至,我们还知道我们所处的世界是一个球体,因为,在越过经度$FFFFFFFF又回到了原点$00000000的位置。
著名的物理学家对象牛顿早就发现各种对象之间存在一种普遍的联系,并且在对象的运动速度与对象大小的关系方面提出了著名的理论--牛顿力学。
可是,后来牛顿这个对象却一直搞不懂到底是什么力量在无形地推动各种对象的运动。
因此,他认为一定是创造整个计算机世界的上帝在推动各种对象的运动。
后来他成了上帝最虔诚的信徒。
在牛顿对象死后不久,我们的计算机世界又诞生了一个更伟大的对象。
他基于先有代码的执行才有执行的结果这一基本的因果论,提出了进程运动的时空是相对的这一伟大理论。
他认为,在一个运动中进程空间中看另一个运动中的进程空间,时间和空间都不是绝对的,空间会弯曲。
而且,任何对象的运动速度绝对不可能超过CPU的速度,CPU速度就是我们计算机世界里的光速。
这位伟大的科学对象的名字就叫爱因斯坦,他的相对论在一开始是不被对象们理解的,可是后来的科学探索都证明了这一理论的正确性。
他提出的代码能量和数据物质可以相互转换的理论,也后来制造的大规模毁灭性病毒核武器中得到验证。
在梦的世界里,我快乐极了。
我一会儿变一变我的属性,一会儿又动动我的方法,一会儿感受一下外来的事件。
没错,我确实就是一个实实在在的对象!
过了一会我突然明白,我本来就是一个对象,只是这个对象在梦中变成了现实世界的我……哈哈!
第5课
字
1.CWnd:
:
CreateSolidCaret创建插入符,ShowCaret()显示插入符。
GetTextMetrics(),获得当前字体的一些信息。
CWnd:
:
CreateCaret()创建图象插入符bitmap.LoadBitmap(IDB_BITMAP1);//此处的bitmap为成员变量!
!
!
CreateCaret(&bitmap);ShowCaret();TEXTMETRICtm;//字体结构体dc.GetTextMetrics(&tm);//m_ptOrigin.y+=tm.tmHeight;//获得字体高度。
2.VC中CString:
:
LoadString(ID号),比较方便。
3.路径层的概念:
有两种方法创建路径层:
(1)pDC->BeginPath();pDC->Rectangle(50,50,50+sz.cx,50+sz.cy);pDC->EndPath();pDC->SelectClipPath(RGN_DIFF);
(2)CSizesz=pDC->GetTextExtent(str);CRgnrn;rn.CreateRectRgn(0,50,sz.cx,sz.cy);pDC->SelectClipRgn(&rn,RGN_DIFF);路径层有什么作用?
可以保护我们先前的文本或者图像不被后来画的覆盖。
4.在View上输入文字的步骤。
CFontfont;//创建字体对象font.CreatePointFont(300,"华文行楷",NULL);//设置CFont*pOldFont=dc.SelectObject(&font);//将字体选择到DC中TEXTMETRICtm;//创建字体信息对象dc.GetTextMetrics(&tm);//获得当前字体信息if(0x0d==nChar)//处理回车键{m_strLine.Empty();m_ptOrigin.y+=tm.tmHeight;}elseif(0x08==nChar)//处理退格键{COLORREFclr=dc.SetTextColor(dc.GetBkColor());dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);m_strLine=m_strLine.Left(m_strLine.GetLength()-1);dc.SetTextColor(clr);}else{m_strLine+=nChar;}CSizesz=dc.GetTextExtent(m_strLine);
CPointpt;//处理光标的位置pt.x=m_ptOrigin.x+sz.cx;pt.y=m_ptOrigin.y;
SetCaretPos(pt);dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);//输出字体
dc.SelectObject(pOldFont);//将原先的字体选择回去。
5.模拟卡啦OK变色的步骤。
(1)设置定时器
(2)在定时器中加入如下代码//DELm_nWidth+=5;//此为view的成员变量,初始值为0//DEL//DEL//DELCClientDCdc(this);//DELTEXTMETRICtm;//DELdc.GetTextMetrics(&tm);//DELCRectrect;//DELrect.left=0;//DELrect.top=200;//DELrect.right=m_nWidth;//DELrect.bottom=rect.top+tm.tmHeight;//此长方形的长度随着定时器的触发,逐渐增大//DEL//DELdc.SetTextColor(RGB(255,0,0));//DELCStringstr;//DELstr.LoadString(IDS_WEIXIN);//DELdc.DrawText(str,rect,DT_LEFT);此函数的作用是将字符串输出到长方形中,但如果字符串的长度超过长方形的长度,多余的字符将被截断//DEL//DELrect.top=150;//DELrect.bottom=rect.top+tm.tmHeight;//DELdc.DrawText(str,rect,DT_RIGHT);//DEL//DELCSizesz=dc.GetTextExtent(str);获得字符串的长度//DELif(m_nWidth>sz.cx)当长方形的长度大于字符串的长度后,将其重新归0//DEL{//DELm_nWidth=0;//DELdc.SetTextColor(RGB(0,255,0));//DELdc.TextOut(0,200,str);//DEL}//DEL//DELCView:
:
OnTimer(nIDEvent);
6.SetTimer也可以用回调函数来操作,但并不方便。
以下是步骤
(1)在View的OnCreate消息响应函数中:
SetTimer(1,1000,Timer2Proc);
(2)回调函数的实现:
voidCALLBACKEXPORTTimer2Proc(HWNDhWnd,//handleofCWndthatcalledSetTimerUINTnMsg,//WM_TIMERUINTnIDEvent,//timeridentificationDWORDdwTime//systemtime){//MessageBox((((CMainFrame*)AfxGetMainWnd())->m_hWnd),"ddfaf","weixin",0);;CMainFrame*pMain=(CMainFrame*)AfxGetApp()->m_pMainWnd;//获得MainFrame的指针CTextView*pView=(CTextView*)pMain->GetActiveView();//获得view的指针CClientDCdc(pView);//构造DCdc.TextOut(333,222,"helloworld");
}//我们可以看出,使用回调函数时要获得窗口或者APP的指针,给我们的操作带来麻烦。
并不方便。
第6课
消息
1.当对某菜单添加消息响应函数时,4个类的消息响应优先次序分别是:
1.View
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 孙鑫 VC 教学 视频 笔记