第一篇:MFC编程学习心得
//
1、将C语言变量简单重新定义 UINT、INT(32位,4字节)
LONG、DWORD(32位,4字节)WPARAM、LPARAM(32位,4字节)SHORT、WORD(16位,2字节)LONG、LRESULT BOOL(TRUE、FALSE)PINT
PSTR、LPSTR、LPCSTR(字符串指针,只读和可写)
//
2、H开头,Windows句柄类型变量 HANDLE of Windows =>HWND HANDLE of Instance =>HINSTANCE HANDLE of Icon =>HICON
//3结构体类型
SIZE、POINT、RECT
MFC所有封装类一共有200多个,但是MFC的内部技术不只是简单地封装。MFC内部总共有六大关键技术,构架起了整个MFC开发平台。
一、MFC的六大关键技术包括: a)MFC程序的初始化过程: b)消息映射机制;
c)运行时类型识别(RTTI); d)动态创建; e)永久保存; f)消息传递;
六大关键技术的目的是为了提高开发效率,开发者只需要在局部做简单的修改,即可处理大部分窗口事物。
二、SendMessage和PostMessage函数的功能:
a)能够向指定的窗口内发送窗口消息,既可以是本进程内窗口也可以是其他进程的; b)既可以发送系统内部消息,消息编号的范围是:1-WM_USER-1; 例如:WM_LBUTTONDONW,WM_MOUSEMOVE等; c)也可以发送非系统消息(开发者定义的消息),范围是WM_USER-0x7FFF。
三、SendMessage和PostMessage两个函数的区别是:
a)SendMessage是阻塞型函数,PostMessage是非阻塞型函数:
SendMessage用于调用指定窗口的内部程序,直到窗口程序处理完成以后再返回: PostMessage是将一个消息寄送到一个窗口内的消息队列后就立即返回。b)两个函数的返回值不同:
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM,lParam);BOOL PostMessage(HWND hWnd,UNIT Msg,WPARAM wParam,LPARAM,lParam);SendMessage的返回值依赖于消息处理函数
c)跨线程或者跨进程发送消息,推荐使用PostMessage函数。
一、更具主窗口类型,MFC软件工程可以分为以下几种构架模型:
1、SDI(Single Document Interface):单文档界面,一个主框架窗口下只能编辑一份文档。例如:记事本和画笔等。
2、MDI(Multiple Document Interface):多文档界面,一个主框架窗口下可以同时编辑多份文档。
例如:VC++6.0,Photoshop等软件。
3、基于对话框的软件模型:主窗口是通过资源管理器,在对话框模板内摆放控件编辑而成的。
多数用于开发小规模软件,例如:任务管理器。
4、其他自定义窗口做主窗口:主窗口既不是框架也不是对话框,而是直接开发通用窗口类CWind而成。
例如:输入法窗口、QQ和360软件等,有时这类软件都可以使用框架和对话框模式来代替开发而成。
对话框常用消息映射函数:
二、对话框初始化消息:
1、WM_CREATE:通用窗口初始化消息
窗口还未显示出来,只有父窗口,子窗口还没创建
2、WM_INITDIALOG:对话框窗口专用消息
子窗口已经全部创建完成,可以调用和操作子窗口
三、对话框关闭过程消息:
1、WM_SYSCOMMAND:管理所有系统菜单和系统按钮消息 包括通过最大化、最小化、移动、大小和关闭等
2、WM_CLOSE:是WM_SYSCOMMAND消息的一个专用关闭的分支 再次消息处理过程可以取消本次关闭任务
3、IDCANCEL按钮消息:不但用于按钮回调消息,也是系统按钮关闭窗口的回调 执行真正关闭对话框函数是EndDialog,在此消息处理过程可以取消本次关闭任务
4、WM_DESTROY:通用窗口销毁消息
窗口已经在屏幕中消失了,但是自身窗口和窗口内的控件都还可以调用 在此消息处理过程可以取消本次关闭任务
四、非模式对话框:
1、在调用EndDialog函数关闭时,非模式对话框只是隐藏没有真正关闭;
2、在调用DestroyWindow函数关闭时,只是隐藏没有真正关闭;
3、DestroyWindow函数是通用摧毁窗口的函数,适用于对话框、控件、框架和视图等。
一个MFC软件工程由至少一个CWind派生类和一个CWinApp派生类,因此这两个类是MFC工程中最重要的两个类。
一、CWind成员函数:主要就是一个核心成员变量m_hWnd。
1、DestroyWindow:摧毁窗口。
2、Create和CreateEx:创建窗口,CreateEx创建时可以指定扩展风格。
3、获取窗口句柄:
a)pWnd->m_hWnd:直接调用前最好判断一下指针是否为空。b)operator HWND():自动类型转换,将对象转换为句柄。
c)GetSafeHwnd():可以避免的a方法,因为指针为空造成软件崩溃。
4、由句柄转化为CWnd对象:
a)CWnd::FromHandle:生成一个临时性窗口类指针
b)Attach和Detach:为一个CWnd对象嫁接和移除窗口句柄; c)SubclassWindow和UnsubclassWindow:子类化和反子类化; d)SubclassDlgItem:子类化指定ID对应的控件窗口。
5、获取和设置窗口信息:
a)GetWindowText和SetWindowText:获取和设置窗口的标题文字。b)GetStyle和ModifyStyle:获取和设置窗口的基础风格。c)GetExStyle和ModifyStyleEx:获取和设置窗口的扩展风格。
6、计时器: a)SetTimer: b)KillTimer:
7、窗口操作: a)ShowWindow: b)EnableWindow: c)MoveWindow: d)CenterWindow:
二、CWinApp类成员变量:
三、CWinApp类成员函数:
//匈牙利命名法: //变量:
int long定义:int nSel;long nTel HANDLE hInst;CString szName,szPass;CString strAddr;LPCSTR pszName;DWORD dwID;//如果是成员变量,以“m_”开头 //如果是全局变量,以“g_”开头
第二篇:MFC编程讲稿(二)
一、打字功能
1.加入数据成员
选择ClassView,双击CMyView,光标直接停留在类CMyView的定义处。在类CMyView中加入如下部分: class CMyView : public CView { protected: // create from serialization only
CMyView();
DECLARE_DYNCREATE(CMyView)
// Attributes public:
CMyDoc* GetDocument();
// Operations public: //代码编写开始
POINT Caret;
//用于存放插入符当前坐标位置 //代码编写结束 // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMyView)public: virtual void OnDraw(CDC* pDC);// overridden to draw this view virtual BOOL PreCreateWindow(CREATESTRUCT& cs);protected: virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);//}}AFX_VIRTUAL
// Implementation public: virtual ~CMyView();#ifdef _DEBUG virtual void AssertValid()const;virtual void Dump(CDumpContext& dc)const;#endif
protected:
// Generated message map functions protected: //{{AFX_MSG(CMyView)afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);//}}AFX_MSG DECLARE_MESSAGE_MAP()};2.加入消息:WM_CREATE(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。
(2)选择 Message Maps。(3)分别选择:
Project: 打字
Class Name: CMyView Objects: CMyView Messges: WM_CREATE(4)单击Add Function按钮。
(5)单击Edit Code按钮。在OnCreate()函数体中加入以下部分。
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct){ if(CView::OnCreate(lpCreateStruct)==-1)
return-1;//代码编写开始
TEXTMETRIC tm;
//声明TEXTMETRIC结构类型对象tm,用于存放字符信息。
CClientDC dc(this);
//生成应用程序窗口设备情景对象
//调用CDC类成员函数GetTextMetrics()取得字符信息,并存入变量tm中。
dc.GetTextMetrics(&tm);//调用CWnd类成员函数CreateSolidCaret()创建黑色矩形条插入符,插入符宽度为tm.tmAveCharWidth/8,高度为tm.tmHeight。
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);//设置插入符的初始位置
Caret.x=0;
} Caret.y=tm.tmHeight;SetCaretPos(Caret);//在初始位置显示插入符 ShowCaret();//代码编写结束 return 0;3.加入键盘消息:WM_CHAR(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。
(2)选择 Message Maps。(3)分别选择:
Project: 打字
Class Name: CMyView Objects: CMyView Messges: WM_CHAR(4)单击Add Function按钮。
(5)单击Edit Code按钮。在OnChar()函数体中加入以下部分。
void CMyView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags){
// TODO: Add your message handler code here and/or call default
//代码编写开始
SIZE size;
//存放字符的宽度和长度。
static UINT dy=Caret.y;
//声明静态变量dy,存放插入符Y轴坐标。CString a;
//声明CString类对象a,存放键盘检索到的字符nChar。a=nChar;CClientDC dc(this);//生成应用程序窗口设备情景对象
} CView::OnChar(nChar, nRepCnt, nFlags);for(UINT i=0;i } //代码编写结束 HideCaret(); //隐藏光标,使得显示字符使插入符消失。switch(nChar){ case 'r': //将插入符移动到下一行的开头 Caret.x=0;Caret.y+=Caret.y;break;default: } //将插入符移动到字符后面,并显示出来。SetCaretPos(Caret);ShowCaret();dc.TextOut(Caret.x,Caret.y,a,1);//输出字符 size=dc.GetTextExtent(a);//获得字符大小 Caret.x+=size.cx;//将字符的宽度加入到插入符的当前坐标位置 二、绘图功能 (一)生成Draw程序框架 (二)鼠标绘图 用鼠标绘制图形,一般分三个环节: (1)确定绘图位置:按下鼠标左键,产生WM_LBUTTONDOWN消息(2)确定图形显示范围:拖动鼠标,产生WM_MOUSEMOVE消息(3)完成图形显示:放开鼠标左键,产生WM_LBUTTONUP消息 1.在视图类CDrawView中加入数据成员 选择ClassView视图,双击CdrawView,光标直接停留在类CdrawView的定义处。在类CdrawView的定义中加入如下代码。 class CDrawView : public CView { //代码开始编写 protected: int m_Dragging; CPoint m_PointOld;CPoint m_PointOrigin;//代码编写结束 protected: // create from serialization only // Attributes public: // Operations CDrawView();DECLARE_DYNCREATE(CDrawView)CDrawDoc* GetDocument();public: // Overrides // Implementation public: virtual ~CDrawView();// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CDrawView)public: virtual void OnDraw(CDC* pDC);// overridden to draw this view virtual BOOL PreCreateWindow(CREATESTRUCT& cs);protected: virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);//}}AFX_VIRTUAL #ifdef _DEBUG virtual void AssertValid()const;virtual void Dump(CDumpContext& dc)const;#endif protected: // Generated message map functions protected: //{{AFX_MSG(CDrawView)// NOTEthe ClassWizard will add and remove member functions here.// DO NOT EDIT what you see in these blocks of generated code!//}}AFX_MSG DECLARE_MESSAGE_MAP()21 4.定义函数CdrawDoc::AddLine()选择FileView,展开SourceFiles,双击DrawDoc.cpp,打开执行文件DrawDoc.cpp,在其末尾,加入以下代码。 //代码编写开始 // AddLine()生成新的Cline对象,并调用CObArray成员函数Add()向m_LineArray添加Cline对象指针。 void CDrawDoc::AddLine(int X1,int Y1,int X2,int Y2){ } //代码编写结束 CLine *pLine=new CLine(X1,Y1,X2,Y2);m_LineArray.Add(pLine);5.定义函数CdrawDoc::GetLine()选择FileView,展开SourceFiles,双击DrawDoc.cpp,打开执行文件DrawDoc.cpp,在其末尾,加入以下代码。 //代码编写开始 // CObArray成员函数GetUpperBound()返回加入的最后一个指针的索引,即最大的有效索引,CObArray成员函数GetAt()返回对应的CLine指针。如果索引号小于0或大于最大的有效索引号,GetLine()返回0;否则,返回对应的CLine指针。 CLine *CDrawDoc::GetLine(int Index){ } //代码编写结束 if(Index<0||Index>m_LineArray.GetUpperBound())return 0;return(CLine *)m_LineArray.GetAt(Index);22 6.定义函数CdrawDoc::GetNumLines()选择FileView,展开SourceFiles,双击DrawDoc.cpp,打开执行文件DrawDoc.cpp,在其末尾,加入以下代码。 //代码编写开始 // 通过调用CObArray成员函数GetSize(),GetNumLines()返回m_LineArray当前存放的CLine指针的个数。 int CDrawDoc::GetNumLines(){ } //代码编写结束 return m_LineArray.GetSize();7.修改函数视图类消息处理函数OnLButtonUp()调用GetDocument()和AddLine()来存放新直线。 回到Workspace,选择ClassView,单击CDrawView,展开CdrawView成员变量和成员函数。双击OnLButtonUp(),在函数OnLButtonUp()中定义后加入以下代码。 void CDrawView::OnLButtonUp(UINT nFlags, CPoint point){ // TODO: Add your message handler code here and/or call default int b; CRect Rect(40,40,600,400);b=Rect.PtInRect(point);if(b)::SetCursor(m_HCross);else ::SetCursor(m_HArrow);if(m_Dragging&&b){ m_Dragging=0;CClientDC dc(this);dc.SetROP2(R2_NOT); dc.MoveTo(m_PointOrigin);dc.LineTo(m_PointOld);dc.MoveTo(m_PointOrigin);dc.LineTo(point);//代码开始编写 //调用函数GetDocument()取得文档类的指针,并存入pDoc中。CDrawDoc * pDoc=GetDocument(); //通过指针pDoc调用加入的文档类成员函数AddLine()向m_LineArray加入 Cline类直线对象。 pDoc->AddLine(m_PointOrigin.x,m_PointOrigin.y,point.x,point.y); // 当一条新的直线绘制完成,视图类OnLButtonUp(nFlags, point)函数通过上面的工作将新绘制的直线存入文档类中。 } } CView::OnLButtonUp(nFlags, point);//代码编写结束 8.修改视图类成员函数OnDraw()void CDrawView::OnDraw(CDC* pDC){ CDrawDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data here pDC->MoveTo(40,40); pDC->LineTo(600,40); pDC->LineTo(600,400); pDC->LineTo(40,400); pDC->LineTo(40,40); //代码编写结束 } 9.编译、运行 //代码开始编写 int Index=pDoc->GetNumLines();while(Index--)pDoc->GetLine(Index)->Draw(pDC); (六)图形的删除 下面向Draw程序加入图形的编辑功能。选择“编辑/撤销”菜单命令就可以删除最近绘制的直线,选择“编辑/全部删除”菜单命令可以清除掉视图窗口中所有的直线。 函数DeleteContents专门负责文档数据的删除工作,可以在文档类中加入该函数删除存放的直线。我们的目的是通过菜单命令答道编辑的功能,因此需要加入“编辑/撤销”和 “编辑/全部删除”菜单命令的消息处理函数,在它们的消息处理函数中调用函数DeleteContents()。 1. 加入“编辑”菜单命令“全部删除” (1)选择ResourceView视图,打开Menu项目下的IDR_MAINFRAME标志符,在Edit菜单下面加入菜单命令 “全部删除”。 ID标志符为:ID_EDIT_CLEAR_ALL,Caption为:全部删除(&A)tCtrl+A(2)双击Accelerator项目下面的IDR_MAINFRAME标志符,打开快捷键编辑器。双击快捷键编辑框底部的空框,在ID文本框中输入ID_EDIT_CLEAR_ALL,在Key文本框中输入A,并选择Ctrl。 2. 加入虚函数DeleteContents()25(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects: CDrawDoc Messges: DeleteContents(4)单击Add Function按钮。 (5)单击Edit Code按钮。在DeleteContents()函数体中加入以下部分。void CDrawDoc::DeleteContents(){ } 3. 加入ID_EDIT_CLEAR_ALL的COMMAND消息处理函数OnEditClearAll()(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects IDs: ID_EDIT_CLEAR_ALL Messges: COMMAND // TODO: Add your specialized code here and/or call the base class //代码编写开始 int Index=m_LineArray.GetSize();while(Index--)delete m_LineArray.GetAt(Index);m_LineArray.RemoveAll();//代码编写结束 CDocument::DeleteContents();(4)单击Add Function按钮。 (5)单击Edit Code按钮。在OnEditClearAll()函数体中加入以下部分。void CDrawDoc::OnEditClearAll(){ // TODO: Add your command handler code here //代码编写开始 DeleteContents(); } 4. 加入ID_EDIT_CLEAR_ALL的UPDATE_COMMAND_UI消息处理函数(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects IDs: ID_EDIT_CLEAR_ALL Messges: UPDATE_COMMAND_UI(4)单击Add Function按钮。 (5)单击Edit Code按钮。在OnUpdateEditClearAll()函数体中加入以下部分。void CDrawDoc::OnUpdateEditClearAll(CCmdUI* pCmdUI){ } 5. 加入ID_EDIT_UNDO的COMMAND消息处理函数 UpdateAllViews(0);//代码编写结束 // TODO: Add your command update UI handler code here //代码编写开始 pCmdUI->Enable(m_LineArray.GetSize());//代码编写结束(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects IDs: ID_EDIT_UNDO Messges: COMMAND(4)单击Add Function按钮。 (5)单击Edit Code按钮。在OnEditUndo()函数体中加入以下部分。void CDrawDoc::OnEditUndo(){ // TODO: Add your command handler code here //代码编写开始 int Index=m_LineArray.GetUpperBound(); } 6. 加入ID_EDIT_UNDO的UPDATE_COMMAND_UI消息处理函数 (1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects IDs: ID_EDIT_UNDO if(Index>-1){ } UpdateAllViews(0);//代码编写结束 delete m_LineArray.GetAt(Index);m_LineArray.RemoveAt(Index);Messges: UPDATE_COMMAND_UI(4)单击Add Function按钮。 (5)单击Edit Code按钮。在OnUpdateEditUndo()函数体中加入以下部分。void CDrawDoc::OnUpdateEditUndo(CCmdUI* pCmdUI){ // TODO: Add your command update UI handler code here //代码编写开始 pCmdUI->Enable(m_LineArray.GetSize());//代码编写结束 } (七)图形的存取 (八)滚动窗口 (九)分割窗口 (十)拖放与注册 MFC 对话框编程--总结 一、创建对话框对象 1.首先利用资源编辑器创建对话框资源,并针对该对话框资源定义一个对话框类:classCTestDlg :public CDialog 2.创建话话框对象 模态对话框的创建: 如: CTestDlgdlg; dlg.DoModal(); 非模态对话框创建: 如: CTestDlgdlg; dlg.Create(IDD_DIALOG, this); 但这样是得不到一个正常显示的非模态对话框的。因为模态与非模态对话框的实现方式并不相同,这里我们还要注意几点。 非模态对话框创建完成后是隐藏着的,必须调用ShowWindow来进行显示。 对于模态对话框,当执行到DoModal 函数以创建对话框时,程序会暂停执行,直至模态对话框关闭。所以创建模态对话框可以采用局部对象。 但是,对于非模态对话框,当执行Create函数时并不会暂停执行,当执行到大括号“}后Dlg局部对象被销毁生命周期结束,于是异常出现了。 解决方法有两个: 一、在View类中定义一个CTestDlg 成员变量。 二、动态创建一个CTestDlg 变量,并重写CTestDlg 类的 PostNcDestroy函数,在该函数里销毁对象 deletethis; 无论创建的是模态对话框,还是非模态对话框,当我们单击确定或取消按钮后对话框都会消失。但这时低层的操作却是不同的。 对于模态对话框,此时对话框对象的确是被销毁了,但对于非模态对话框,这时只是隐藏起来不再显示。这需要我们自己调用DestoryWindow函数来进行销毁工作。 这时我们必须重写 CTestDlg 的 OnOK、OnCancel 两个函数(这两个是基类CDialog的虚函数),在这两个函数内调用DestroyWindow函数,并注意不再调用基类CDialog相应的函数。正确地创建非模态对话框的代码如下: CTestDlg*pDlg = new CTestDlg; pDlg->Create(IDD_DIALOG, this); pDlg->ShowWindow(SW_SHOW); 同时,在CTestDlg 类的 PostNcDestroy函数中销毁对象:deletethis; 二、动态创建按钮 1.在对话框类CTestDlg 中定义一个 CButton 类对象,作为其成员变量。 2.在相应的消息处理中,调用 CButton类的Create函数创建按钮。 要注意两点: 如果在调用CButton::Create创建按钮时没有指定WS_VISIBLE 风格,那么随后一定要调用这个按钮对象的ShowWindow函数,来将该按钮显示出来。 为防止该CButton关联多个按钮,这里需要进行一些设置,如下: if(!m_btn.m_hwnd) { // CButton 对象m_btn 未关联一个按钮 m_btn.Create(....); } else { // CButton 对象m_btn 已关联一个按钮 其他操作...} 当然,方法并不只这一种。但这是最漂亮的方法。 三、设置控件文本文字 1.下面列举几个用来设置控件文本文字的函数: // 取得对话框中指定控件的窗口句柄。控件通过ID标识来指定 CWnd*GetDlgItem(int nID)const; void CWnd::GetDlgItem(int nID, HWND* phWnd)const; // 取得窗口文本 intGetWindowText(LPTSTR lpszStringBuf, int nMaxCount)const; voidGetWindowText(CString& rString)const; // 设置窗口文本 voidSetWindowText(LPCTSTR lpszString); // 取得指定控件窗口文本。控件通过ID标识来指定 intGetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount)const; intGetDlgItemText(int nID, CString& rString)const; // 设置指定控件窗口文本。控件通过ID标识来指定 void SetDlgItemText(int nID, LPCTSTR lpszString); // 取得指定控件窗口文本,并转化为UINT 类型返回。控件通过ID标识来指定 UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE)const;// 设置指定控件窗口文本,由UINT类型转化为字符。控件通过ID标识来指定 voidSetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE); 2.可以为对话框控件关联一个变量,在CTestDlg 类的DoDataExchange来完成数据的更新与交换。这里我们需要重点说明 DoDataExChange 函数: 首先引用MSDN的一段解释吧:Called by the framework to exchange and validate dialog data。意指框架调用此函数来改写与确认对话框数据。 其实DoDataExChange函数主要是通过DDX_TEXT(....)或 DDX_CONTROL(....)来实现数据的实时关联的。 我从我的MSDN中随便拿来一个定义: void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, BYTE& value); 其实这个要关联的话也很简单,没有那么复杂。如下: value = GetDlgItemInt(nIDC); SetDlgItemInt(nIDC, value); 而DoDataExchange 函数是在UpdateData函数内部调用的。 该函数只有一个布尔型参数,b31.org 它决定了数据传送的方向: 调用UpdateData(TRUE),将数据从对话框的控件中传送到对应的数据成员中。 调用UpdateData(FALSE),则将数据从数据成员中传送给对应的控件。 UpdateData(FALSE)是将变量的值传到控件.UpdateData(TRUE)是从控件中取值到关联的变量 四、对话框伸缩功能的实现 只关联到两个函数: // 取得指定窗口边框折尺寸 void GetWindowRect(LPRECT lpRect)const; // 设置指定窗口(控件)的位置同尺寸 BOOL SetWindowPos(const CWnd* pWndInsertAfter, intx, inty, int cx, intcy, UINTnFlags); 五、逃跑按钮的实现 1.创建一个基于对话框的MFC 程序,删除原有的控件后,再添加两个按钮,更改两按钮名为”你能抓到我吗?“ 2.打开类视图,定义一个新类CNewButton,这个新类的基类为CButton。并为此类添加一个成员变量:CNewButton*m_pbtn; 3.打开资源视图,分别为两个按钮创建两个CNewButton类关联变量:m_btn1, m_btn2; 4.在CXXXDlg中改写其OnInitDialog函数。主要添加: m_btn1.m_pbtn = &m_btn2; m_btn2.m_pbtn = &m_btn1; 5.对于CNewButton 类,必定其OnMouseMove函数。主要添加: ShowWindow(SW_HIDE); m_pbtn->ShowWindow(SW_SHOW); 编译,连接。OK 六、属性页、属性表单与向导的建立 1.创建属性页 打开资源编辑器,点击Dialog 资源并在列出的选项中,选择:IDD_PROPPAGE_LARGE。建立属性页资源。 之后,我们就可以其上添加其他控件来完善我们的属性页。关于属性页的完善操作我们在后面会谈到。 属性页资源完善后,再为每一个属性页关联一个类。 2.创建属性表单 打开类视图,添加新类CPropSheet,其基类为CPropertySheet。 之后再为其添加属性页类对象,并在其构造函数中利用AddPage函数将属性页添加到表单上。 3.消息响应 再主菜单的最后再增加一个菜单项,并为此菜单添加消息响应函数。 在此响应函数中创建属性表单: CPropSheetpropSheet(TEXT(”属性表单")); propSheet.DoModal(); 4.向导的创建 创建一个向导类型的对话框,应该遵循创建一个标准属性表单的步骤来实现。 但在调用属性表单对象的DoModal函数之前,应该先调用SetWizardMode函数,来声明建立的是一个作为向导的属性表单。 所以,应在DoModal函数之前添加如下代码: propSheet.SetWizardMode(); 5.属性页的完善操作 首先我们要注意到属性页,澳门新濠天地官网66bb.org 在三个不同时期的关键性操作:当属性表单中的某属性页被选中,从而成为一个活动的页面时,应用程序框架就会调用OnSetActive函数。 OnSetActive 是其基类的一个虚函数,我们可以重写这个函数并在其中进行一些操作。 假设当前我们处于属性表单中的某属性页,当我们点击下一步并将进入下一个属性页时,应用程序框架会调用OnWizardNext函数。 OnWizardNext 是其基类的一个虚函数,我们可以重写这个函数并在其中进行一些操作。类似的还有OnWizardBack 同 OnWizardFinish函数。 当一个属性页被创建时,会调用其OnInitDialog函数。 我们可以在这个函数里对属性页中的控件进行一些操作。如为列表框或下拉框添加字符串等。 MFC编程实验总结报告 知识总结+个人心得 2011年暑期MFC编程实验报告 / 6 MFC编程实验个人总结报告 一、MFC类、函数等知识小结: 1、SetTimer(1, m_intLevel, NULL);在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了于是SetTimer函数的原型变为: UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD)) 当使用SetTimer函数的时候,就会生成一个计时器。函数中nIDEvent指的是计时器的标识,也就是名字。nElapse指的是时间间隔,也就是每隔多长时间触发一次事件。第三个参数是一个回调函数,在这个函数里,放入你想要做的事情的代码,你可以将它设定为NULL,也就是使用系统默认的回调函数,系统默认认的是onTime函数。这个函数怎么生成的呢?你需要在需要计时器的类的生成onTime函数:在ClassWizard里,选择需要计时器的类,添加WM_TIME消息映射,就自动生成onTime函数了。然后在函数里添加代码,让代码实现功能。每隔一段时间就会自动执行一次。 例: SetTimer(1,1000,NULL); 1:计时器的名称; 1000:时间间隔,单位是毫秒; NULL:使用onTime函数。 当不需要计时器的时候调用KillTimer(nIDEvent); 例如:KillTimer(1); KillTimer(1); 2、typedef struct{};(1)struct{ int x;int y;}test1;好,定义了 结构 test1,test1.x 和 test1.y 可以在语句里用了。 (2)struct test {int x;int y;}test1;定义了结构 test1,test1.x 和 test1.y 可以在语句里用了。与(1)比,省写 了 test (3)typedef struct test / 6 {int x;int y;}text1,text2; 此处时说了这种结构体(类型)别名 叫 text1 或叫 text2,而不是定义了结构体变量.真正在语句里用,还要写: text1 test1;//定义结构体变量 然后好用 test1.x test1.y 或写 text2 test1;//定义结构体变量 然后好用 test1.x test1.y 3、Invalidate();//让客户区无效,即时重新绘制客户区 void Invalidate(BOOL bErase = TRUE); 该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。 4、CDC::Rectangle(左上x,左上y,右下x,右下y);使用该函数画一个矩形,可以用当前的画笔画矩形轮廓,用当前画刷进行填充。 函数原型:BOOL Rectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); hdc:设备环境句柄。 nLeftRect:指定矩形左上角的逻辑X坐标。 nTopRect:指定矩形左上角的逻辑Y坐标。 nRightRect:指定矩形右下角的逻辑X坐标。 nBottomRect:指定矩形右下角的逻辑Y坐标。 5、CBrush:: CBrush//画刷类 eg:CBrush brushStick(RGB(127, 127, 127));四种构造函数: CBrush(); CBrush(COLORREF crColor); CBrush(int nIndex, COLORREF crColor); CBrush(CBitmap* pBitmap); / 6 参数说明: crColor指定画刷的前景色(RGB方式)。如果画刷是阴影线型的,则指定阴影线的颜色。 nIndex指定画刷阴影线采用的风格,取值如下: HS_BDIAGONAL45度的向下影线(从左到右) HS_CROSS水平和垂直方向以网格线作出阴影 HS_DIAGCROSS 45度的网格线阴影 HS_FDIAGONAL 45度的向上阴影线(从左到右) HS_HORIZONTAL 水平的阴影线 HS_VERTICAL 垂直的阴影线 pBitmap指向CBitmap对象的指针,该对象指定了画刷要绘制的位图。 构造函数说明: 类CBrush一共有四个覆盖的构造函数。不带参数的那个构造函数构造一个未初始化的CBrush对象,在使用该对象之前需要另外初始化。如果使用了不带参数的那个构造函数,则必须用CreateSolidBrush、CreateHatchBrush、CreateBrushIndirect、CreatePatternBrush或CreateDIBPatternBrush来初始化返回的CBrush对象。如果使用了带参数的构造函数,则不再需要初始化CBrush对象。带参数的构造函数在出错时会产生一个异常,而不带参数的构造函数总是成功返回。只带有一个参数COLORREF的构造函数用指定的颜色构造一个实线型的画刷。颜色是一个RGB值,可以用WINDOWS.H中的宏RGB构造出来。带两个参数的构造函数构造一个阴影线型的画刷,参数nIndex指定了阴影线模式的指数(index)。参数crColor指定了画刷的颜色。带有一个CBitmap型参数的构造函数构造一个模式化的画刷。参数指定一个位图。该位图应该是已经用CBitmap::CreateBitmap、CBitmap::CreateBitmapIndirect、CBitmap::LoadBitmap或CBitmap::CreateCompatiableBitmap建立或加载的位图。填充模式下的位图的最小尺寸为8像素×8像素。 6、MessageBox(“Game Over!”);MessageBox(NULL,“text”,“title”,BUTTON);参数title:string类型,指定消息对话框的标题。text:指定消息对话框中显示的消息,该参数可以是数值数据类型、字符串或boolean值。icon:Icon枚举类型,可选项,指定要在该对话框左侧显示的图标。button:Button枚举类型,可选项,指定显示在该对话框底部的按钮。default:数值型,可选项,指定作为缺省按钮的按钮编号,按钮编号自左向右依次计数,缺省值为1,如果该参数指定的编号超过了显示的按钮个数,那么MessageBox()函数将使用缺省值返回值Integer。函数执行成功时返回用户选择的按钮编号(例如1、2、3等),发生错误时返回-1。如果任何参数的值为NULL,4 / 6 MessageBox()函数返回NULL。 函数原型:MessageBox.Show(Text,Title,MessageBoxButtons,MessageBoxIcon ,MessageBoxDefaultButtons) 参数说明: (1)Text:必选项,消息框的正文。(2)Title:可选项,消息框的标题。 (3)MessageBoxButtons:可选项,消息框的按钮设置,默认只显示【确定】按钮。 OK――确定 OKCancel――确定和取消 AbortRetryIgnore――终止、重试和忽略 YesNoCancel――是、否和取消 YesNo――是和否 RetryCancel――重试和取消 (4)MessageBoxIcon:对话框中显示的图标样式,默认不显示任何图标。 Question――问号 Information、Asterisk――i号 Error、Stop、Hand――错误号 Warning、Exclamation――!号 None――不显示任何图标 (5)MessageBoxDefaultButtons:可选项,对话框中默认选中的按钮设置。 DefaultButton1――第1个button是默认按钮 DefaultButton2――第2个button是默认按钮 DefaultButton3――第3个button是默认按钮 7、Memcpy(拷贝目的地,拷贝对象,拷贝长度);包含在头文件#include 函数原型: extern void *memcpy(void *destin, void *source, unsigned n);功能: 由source指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。eg: int a=5,b=9;memcpy(a,b,sizeof(a));//将b按位拷给a;说明: 1.source和destin所指内存区域不能重叠,函数返回指向destin的指针。 2.与strcpy相比,memcpy并不是遇到' '就结束,而是一定会拷贝完n个字节。 / 6 3.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。 //注意,source和destin都不一定是数组,任意的可读写的空间均可。 二、MFC个人学习心得: 1、问题的解决:: 绘制窗口时会出现严重的刷屏问题,问了解决这一问题,通过改变背景位图来替代过多的部分的重绘达到更好效果。 一个满载的二维、三维数组都可以用一个足够长的一维数组来装下。 2、MFC基础细节学习: 学习了位图的使用,CBrush类,CDC类,CDialog类的基本使用,对于菜单的设置初步了解了。 3、mfc编程的初步理解: 通过自学了解到mfc编程的实现是通过建立消息映射表来实现各个函数的调用。(1)通过DECLARE_MESSAGE_MAP声明消息映射;(2)通过BEGIN_MESSAGE_MAP和宏END_MESSAGE_MAP来包含消息映射宏,创建消息映射列表;(3)为消息处理函数添加代码,实现需要的响应。通过以上三大步实现消息映射。 每种对话框的操作要通过先建立相应的CDialog类来具体进行。 MFC编程只是一种工具,而编程的核心还是代码的实现。我们在使用MFC编程时要想学得更好就要不断练习,更具体的了解其中的各种类、函数,各种工具,MFC是一个巨大的工具箱,但是如果不知道工具箱里面的工具怎么用,那在好的工具也无用武之地。所以,我认为此次编程小实习主要是让我初步接触了MFC如何实现可视化编程。未来要想真正掌握MFC编程还要不断的深入了解各种MFC工具,真正的与代码结合起来实现高效实用的编程效果。 4、这次编程实习过程中,另一点感受最深的就是团队合作,一支团队要想有好的工作效率和质量就必须有足够的队伍成员间的默契。如果仅仅靠个别人去完成,其实是很不科学的,不仅费时而且可能会白白做很多无用功,因此,在以后的小组中一定要加强团队合作意识。另一点就是一个队伍的成员可以不是特别出色,但是队伍的领导者一定要负责,领导者可以不是特别杰出的技术骨干人员,但必须懂得怎样协调、安排工作,这也是实现高效团队的关键因素。 通过这次暑期编程实验,不仅充实了暑期生活,也让我学到了一些新的知识,让我更加深刻的理解了团队合作的重要性。在以后的学习生活要积极参加类似的活动,加强知识学习,能力提高,为未来的职业生涯逐渐打下一个坚实的基础。谢谢! / 6 中南大学 本科生课程设计(实践)任务书、设计报告 (大学计算机基础) 题 目 学生姓名 指导教师 学 院 专业班级 学生学号 MFC程序设计实践报告 张雪宁 童 键 土木工程学院 土木国际1602班 1209160225 计算机基础教学实验中心 2017年 6 月 26日 一、任务描述 这次实践主要采用的是自主学习的方式,在我们已有的C++知识基础上,自学MFC编程,并完成《C++语言课程设计任务书》中指定任务与要求,在这次实践中,要求学会使用visual C++ MFC编程来完成《C++语言课程设计任务书》中的任务,任务涵盖以基本对话框为应用程序的框架,完成单文档界面(SDI)应用程序。要求学会运用常用的基本控件,如静态文本框、命令按钮、编辑框、复选框、列表框、组合框、滚动条等。 本次实践可分为两个主要内容: 1、基于对话框的Windows应用程序: 这部分以知识要点掌握与编程实例主辅结合的方式求我们基本掌握基于对话框的应用程序的创建过程,建立基于对话框的 MFC 应用程序框架,放置控件并设置控件属性,以及为控件连接变量(即为控件命名),添加并且编写消息处理函数。在这部分实践中,按照任务书中要求按照任务书所给的实例,要求基本掌握基于对话框的 MFC 应用程序中各常用的基本控件的使用。 2、文档/视图结构应用程序: 文档/视图结构的思想是将数据的管理与显示分离,其中文档用于管理应用程序的数据,而视图是用户界面,用于显示、打印文档中的数据,并管理与用户的交互。在这部分实践过程中,要求对任务书中介绍的几种SDI结构的典型应用程序来了解其结构及设计方法,学习和实践了典型应用包括:利用画笔、画刷等工具及位图处理的方法实现文字和图形的输出。利用定时器控件制作动画程序。对鼠标和键盘进行编程的基本方法。文件、字体、颜色等几种通用对话框的使用方法及自定义对话框的设计、调用方法以及菜单的设计方法。 3、多文档界面(MDI)应用程序:这类程序可以同时打开多个文档并进行处理,处理的过程中很容易地进行切换。要求将1、2两点中所涉及到的程序,任选3到5个,做成一个综合程序,要求通过菜单调用各部分功能。可自行组织和发挥,使其安排合适。 二、系统设计思想 对话框是一种特殊类型的窗口,绝大多数Windows程序都通过对话框与用户进行交互。在Visual C++中,对话框既可以单独组成一个简单的应用程序,又可以成为文档/视图结构程序的资源。 文档/视图结构的思想是将数据的管理与显示分离,其中文档用于管理应用程序的数据,而视图是用户界面,用于显示、打印文档中的数据,并管理与用户的交互。SDI具有文档/视图结构的应用程序框架,该框架包括应用程序类、窗口框架类、文档类和视图类,编程的任务是在文档类和视图类中添加适当的代码。其中文档类中一个重要的成员函数是OnNewDocument(),用户在此添加代码完成对数据的初始化;而视图类中最重要的成员函数是OnDraw(),通过在该函数中添加代码实现窗口内容的输出。 三、系统功能 编写的不同的小程序拥有不同的功能。以下是不同小程序对应的功能。 1、单击“复制”按钮,则把上面的编辑框中的内容复制到下面的编辑框中;单击“结束”按钮,则退出程序的运行。 2、输入一元二次方程 ax2 +bx+c=0 的系数 a、b、c,计算并输出两个根 x1、x2。 3、对列表框进行项目添加、修改和删除操作的应用程序 4、选定了“日期”或“时间”复选框,则在对应的只读编辑框中显示系统当前日期或时间。 5、击“确定”按钮后,在列表框中显示选择的信息。 6、-2π~2π 之间的 sin 曲线。 7、按下鼠标右键画圆,按住鼠标左键移动画线。 8、定时器控制蝴蝶在窗口中飞舞 9、用户单击左键,则弹出输入成绩对话框,选择 OK 后平均成绩和总分在窗口的客户区输出。 10、设计如图所示的菜单,并编写相应用的消息处理函数。 四、设计过程 以第一题为例,介绍其设计过程。 (1)建立基于对话框的 MFC 应用程序框架。 ①选择“文件 | 新建”命令; ②在“工程”选项卡中,选定“ MFC AppWizard(exe)”,输入工程名称,选择“确定”。 ③选定“ D 基本对话”,即创建基于对话框的应用程序,选择“完成”。 (2)放置控件 删除原有的控件。 放置所需的控件:两个编辑框和两个命令按钮。方法是:先单击控件工具栏上的控件图标选择所需的控件,然后在对话框设计界面上按住鼠标左键拖拉出所需要的大小后释放。(3)设置控件属性 选定控件,在其快捷菜单中选择“属性”命令,在弹出如图所示的对话框中进行设置。上面编辑框的属性设置为: 选定“ Multiline ”复选框,编辑框中可以输入多行文本。 选定“ Vertical scroll ”和“ Auto Vscroll ”,编辑框将有垂直滚动条。 选定“ Want return ”。 下面编辑框属性的设置与上面编辑框基本一样,只是可以不选定“ Want return ”。(4)连接变量 为控件连接变量就是为控件起一个名称。每一个控件都是一个对象,调用 MFC 类库中的函数都是通过对象来实现的。为 IDC_EDIT1 连接变量 m_e1 的步骤为: ①在 IDC_EDIT1 编辑框的快捷菜单中选“建立类向导”,弹出 “ MFC ClassWiard ”对话框。 ②在“ Member Variables ”中,选定“ IDC_EDIT1 ”,再选择“ Add Variable ”命令。 ③在 “ Add Member Variable ”对话框中输入以下的数据: Member Variable name(内存变量名): m_e1 ; Category(类别): Control ; Variable type(类型):Cedit 用同样的方法再为 IDC_EDIT2 连接一个变量 m_e2。 (5)添加并且编写消息处理函数。 本例要求单击“复制”按钮后上面编辑框中的内容复制到下面的编辑框中。也就是说,在程序运行时,在“复制”按钮上发生单击事件后,Windows 向对话框发出了一个 BN_CLICKED 消息,CTESTDlg 类应有一个处理该消息的函数。 添加和编写这个消息处理函数的过程是: ①双击“复制”按钮,弹出的“ Add Member Function ”对话框,输入函数名(缺省函数名为 OnButton1),选择“确定”按钮后,添加了一个空函数。另一个方法是在“ MFC ClassWiard ”对话框“ Message Maps ”选项卡中,选定 IDC_BUTTON1 和 BN_CLICKED 消息,然后选择“ Add Function ”按钮即可。 五、运行情况 经过多次的修改和完善,编译后各程序均能够正常运行,并且很好的发挥其设计初衷的作用。与预想中的系统功能相符。 六、心得体会 本次的MFC实践课,让我收获了很多。因为实践课的时间很紧张,所以一开始显得有点无从下手,甚至有害怕和畏难的情绪存在,对自己很没有信心。即使已经有了一个学期的C++基础知识的学习,但MFC对于我们来说任然是一个崭新的领域。我觉得实践课带给我们的,不仅仅是如何使用Visual C++进行MFC编程这一项技能,更是如何自我学习与自我提升的又一次实践。通过这次实践,我懂得了如何用 MFC编写可视化界面的应用程序,加强了对C++的认识,巩固了已有的知识,从而提升了逻辑思考能力。也让我们对Microsoft Visual C++ 6.0又有了更进一步的认识和体会。 七、参考文献 1、杨长兴,刘卫国.C++程序设计.北京:中国水利水电出版社,2012 2、刘卫国,杨长兴.C++程序设计实践教程.北京:中国水利水电出版社,2012 3、MFC编程基础 第1章 基于对话框的Windows应用程序 第2章 文档/视图结构应用程序第三篇:MFC 对话框编程 -- 总结
第四篇:MFC编程实验个人总结报告
第五篇:2017中南大学C++实践报告MFC编程