MFC--简单实例
本实例可以作为MFC编程的入门实例:
基本框架:
1.Frame
2.Doc
3.View
4.App
5.Dialog
基本思想是:建立Dialog对话框,输入自定义字符串-->Doc获得对话框的字符串-->对话框发送消息到View-->View的消息处理函数更新View显示界面。
一、建立Dialog对话框
在资源里添加Dialog对话框,并更改其Caption和ID,然后再添加相应的Tool,比如静态框和编辑框。
UI布置好之后,为Dialog添加相应的操作类,利用ClassWizard会自动添加。本例中我添加的类为MyTextShow,那么程序中会出现MyTextShow.h和MyTextShow.cpp文件,其内容如下:
- // MyTextShow.h
- #pragma once
- // MyTextShow dialog
- class MyTextShow : public CDialog
- {
- DECLARE_DYNAMIC(MyTextShow)
- public:
- MyTextShow(CWnd* pParent = NULL); // standard constructor
- virtual ~MyTextShow();
- // Dialog Data
- enum { IDD = IDD_SHOWTEXT };
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- DECLARE_MESSAGE_MAP()
- };
- // MyTextShow.cpp
- #include "MyShowText.h"
- #include "MyTextShow.h"
- // MyTextShow dialog
- IMPLEMENT_DYNAMIC(MyTextShow, CDialog)
- MyTextShow::MyTextShow(CWnd* pParent /*=NULL*/)
- : CDialog(MyTextShow::IDD, pParent)
- {
- }
- MyTextShow::~MyTextShow()
- {
- }
- void MyTextShow::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- }
- BEGIN_MESSAGE_MAP(MyTextShow, CDialog)
- END_MESSAGE_MAP()
- // MyTextShow message handlers
// MyTextShow.h #pragma once // MyTextShow dialog class MyTextShow : public CDialog { DECLARE_DYNAMIC(MyTextShow) public: MyTextShow(CWnd* pParent = NULL); // standard constructor virtual ~MyTextShow(); // Dialog Data enum { IDD = IDD_SHOWTEXT }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support DECLARE_MESSAGE_MAP() }; // MyTextShow.cpp #include "MyShowText.h" #include "MyTextShow.h" // MyTextShow dialog IMPLEMENT_DYNAMIC(MyTextShow, CDialog) MyTextShow::MyTextShow(CWnd* pParent /*=NULL*/) : CDialog(MyTextShow::IDD, pParent) { } MyTextShow::~MyTextShow() { } void MyTextShow::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(MyTextShow, CDialog) END_MESSAGE_MAP() // MyTextShow message handlers
上面的代码只是建立一个Dialog空壳,但其中的代码值得研究,尤其是下面的宏,构成了Dialog在整个程序中的动态生成机制以及消息映射机制。
DECLARE_DYNAMIC(MyTextShow)
DECLARE_MESSAGE_MAP()
IMPLEMENT_DYNAMIC(MyTextShow, CDialog)
BEGIN_MESSAGE_MAP(MyTextShow, CDialog)
END_MESSAGE_MAP()
DoDataExchange虚函数是Dialog的数据交换函数:
virtual void DoDataExchange(CDataExchange* pDX);
二、获取Dialog对话框的信息
利用Wizard添加CString MyInput变量,并让此变量和IDC_MYEDIT(Dialog对话框中的编辑框)关联起来,程序中的代码变化如下:
- //MyShowText.h
- ...
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- DECLARE_MESSAGE_MAP()
- [b]public:
- CString MyInput;[/b]
- //MyShowText.cpp
- void MyTextShow::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- [b]DDX_Text(pDX, IDC_MYEDIT, MyInput);[/b]
- }
//MyShowText.h ... protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support DECLARE_MESSAGE_MAP() [b]public: CString MyInput;[/b] //MyShowText.cpp void MyTextShow::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); [b]DDX_Text(pDX, IDC_MYEDIT, MyInput);[/b] }
这时对话框中的编辑框中的内容就会自动保存到MyInput中。
三、Doc获得Dialog中保存变量的值
为了显示的保存Dialog中的值到Doc中,我在Menu中添加应用菜单,依此来触动Doc中的响应函数来保存相应的值。
利用Event Handle Wizard建立事件处理函数。
其代码修改如下:
- // MyShowTextDoc.h
- public:
- afx_msg void OnInput();
- // MyShowTextDoc.cpp
- BEGIN_MESSAGE_MAP(CMyShowTextDoc, CDocument)
- ON_COMMAND(ID_INPUT, &CMyShowTextDoc::OnInput)
- END_MESSAGE_MAP()
- void CMyShowTextDoc::OnInput()
- {
- // TODO: Add your command handler code here
- }
// MyShowTextDoc.h public: afx_msg void OnInput(); // MyShowTextDoc.cpp BEGIN_MESSAGE_MAP(CMyShowTextDoc, CDocument) ON_COMMAND(ID_INPUT, &CMyShowTextDoc::OnInput) END_MESSAGE_MAP() void CMyShowTextDoc::OnInput() { // TODO: Add your command handler code here }
这样就把菜单按钮和OnInput()处理函数联系在一起。
然后再OnInput()函数里添加要处理的代码:
- // MyShowTextDoc.h添加
- CString MyInput;
- // MyShowTextDoc.cpp
- void CMyShowTextDoc::OnInput()
- {
- // TODO: Add your command handler code here
- MyTextShow Dlg;
- if(Dlg.DoModal() == IDOK)
- {
- MyInput = Dlg.MyInput;
- }
- }
// MyShowTextDoc.h添加 CString MyInput; // MyShowTextDoc.cpp void CMyShowTextDoc::OnInput() { // TODO: Add your command handler code here MyTextShow Dlg; if(Dlg.DoModal() == IDOK) { MyInput = Dlg.MyInput; } }
这样就可以保存Dialog编辑框中的变量。
四、刷新CView界面,显示Doc中保存的变量值
当点击对话框的OK按钮时,发送一个消息到View类,View类中的相应的响应函数接收到消息后调用刷新函数来刷新界面。
这个消息发送是有Dialog-->CView
如何发送消息?又如何接收消息?
这里的消息是用户自定义消息,不是系统的消息。
那么用户如何定义自己的消息:
#define WM_自定义消息名 WM_USER+k 这里的k可以是任意的数,只要不和其他自定义消息相重即可,比如我自定义消息为:
#define WM_SHOWMESSAGE WM_USER+1
1.在 MyTextShow.h中自定义消息
#define WM_SHOWMESSAGE WM_USER+1
2.添加ok按钮的响应函数,并添加代码如下:
- void MyTextShow::OnBnClickedOk()
- {
- // TODO: Add your control notification handler code here
- OnOK();
- CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd; //先通过获取当前框架指针
- CView * active = pMF->GetActiveView();//才能获取当前视类指针
- if(active != NULL) //获取了当前视类指针才能发送消息
- active->PostMessage(WM_SHOWMESSAGE,0,0); //使用PostMessage发送消息
- }
void MyTextShow::OnBnClickedOk() { // TODO: Add your control notification handler code here OnOK(); CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd; //先通过获取当前框架指针 CView * active = pMF->GetActiveView();//才能获取当前视类指针 if(active != NULL) //获取了当前视类指针才能发送消息 active->PostMessage(WM_SHOWMESSAGE,0,0); //使用PostMessage发送消息 }
active->PostMessage(WM_SHOWMESSAGE,0,0); 是获得CView的指针后,通过PostMessage把自定义的消息WM_SHOWMESSAGE发送出去。
3.CView接收发送的消息
在 MyShowTextView.h头文件中添加代码如下:
1)自定义消息,这个自定义消息和Dialog中的自定义消息相同
#define WM_SHOWMESSAGE WM_USER+1
2)添加相应函数
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
注意这个响应函数的格式,afx_msg表示这是一个消息处理函数,返回值必需是LRESULT。
3)添加BEGIN_MESSAGE_MAP消息映射图
ON_MESSAGE(WM_SHOWMESSAGE, OnMyMessage)
这里是自定义的消息,必需用ON_MESSAGE
4)在响应函数里添加刷新函数
- LRESULT CMyShowTextView::OnMyMessage( WPARAM wParam, LPARAM lParam )
- {
- Invalidate();
- return 0;
- }
LRESULT CMyShowTextView::OnMyMessage( WPARAM wParam, LPARAM lParam ) { Invalidate(); return 0; }
五、利用OnDrow函数里显示接收的消息
其中OnDraw的代码更改如下:
- void CMyShowTextView::OnDraw(CDC* pDC)
- {
- CMyShowTextDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- if (!pDoc)
- return;
- // TODO: add draw code for native data here
- CRect rect;
- GetClientRect (&rect);
- pDC->DrawText (pDoc->MyInput, &rect,
- DT_SINGLELINE | DT_CENTER | DT_VCENTER);
- }
void CMyShowTextView::OnDraw(CDC* pDC) { CMyShowTextDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: add draw code for native data here CRect rect; GetClientRect (&rect); pDC->DrawText (pDoc->MyInput, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); }
到此整个程序设计完毕。