MFC_Session1

MFC包含的基本四个类

  • 框架类
  • 应用程序类
  • 文档类
  • 视图类

MFC程序运行启动

AFX_MODULE_STATE aaa;//当前程序模块状态信息aaa(臆造的名字)
AFX_MODULE_THREAD_STATE bbb;//当成程序线程状态信息

CWinAPP::CWinApp()//构造全局对象CMyWinApp theApp
{  
	AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); 
    	//获取全局变量&aaa,_AFX_CMDTARGET_GETSTATE()为AfxGetModuleState()的宏定义
    
    AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread
        //获取全局变量&bbb

    pThreadState->m_pCurrentWinThread = this;
    	//谁调用构造函数,谁就是this,即theApp的地址保存在变量m_pCurrentWinThread,bbb的一个成员中
    
    AfxGetThread(){
        AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取全局变量&bbb
        CWinThread* pThread = pState->m_pCurrentWinThread;
        return pThread;//返回&theApp
    }
    //ASSERT断言判断
    
    pModuleState->m_pCurrentWinApp = this;//将&theApp的赋给aaa的一个成员
    
    AfxGetApp(){
        return afxCurrentWinApp;
        //afxCurrentWinApp是一个宏,AfxGetModuleState()->m_pCurrentWinApp,即return &theApp
    }
    
}
  • 程序的启动,构造theApp的对象,调用父类CWinApp的构造函数:
    • 将theAPP对象的地址保存在线程状态信息中;
    • 将theApp对象的地址保存在模块状态信息中;
    • 进入WinMain函数,调用AfxWinMain函数。

程序的执行

//theApp是不是指导程序流程
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,_In_ LPTSTR lpCmdLine, int nCmdShow){
	AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow){
    	CWinThread* pThread = AfxGetThread();
		CWinApp* pApp = AfxGetApp();//均为获取&theApp
        pApp->InitApplication();//利用theApp对象调用应用程序类成员虚函数****初始化,多态性
        pThread->InitInstance()//利用theApp对象调用应用程序类成员虚函数****创建并显示窗口
        pThread->Run()//利用theApp对象调用应用程序类成员虚函数****消息循环
        {
            for(;;)
            {
                while(没有消息时)
                    OnIdle();//利用theApp对象调用应用程序类成员虚函数 空闲处理
                do
                {
                    if(getMessage捉到WM_QUIT)
                        return ExitInstance();
                    //程序结束前,利用theApp对象调用应用程序类成员虚函数****善后处理
                }while(...)
            }
        };
    }
	
}
  • 进入入口函数WinMain

    • 获取应用程序类对象theApp的地址;
    • 利用theApp地址调用InitApplication,初始化当前应用程序的数据;
    • 利用theApp地址调用InitInstance虚函数初始化程序,在函数中我们创建窗口并显示;
    • 利用theApp地址调用CWinApp的Run虚函数进行消息循环;
    • 如果没有消息,利用theApp地址调用OnIdle虚函数实现空闲处理;
    • 程序退出利用theApp地址调用ExitInstance虚函数实现退出前的善后处理工作。
  • 成员变量

    m_pMainWnd——当前应用程序的主窗口

钩子函数

  • Win32的技术,MFC借用了这个技术,大量用于木马病毒;
  • 优先读取消息,把消息钩过来,所以称为钩子函数。

创建钩子

HHOOK SetWindowsHookEX(
int idHook,//钩子类型,在MFC里面一般为WH_CBT,即钩取WM_CREATE信息
HOOKPROC Lpfn,//钩子处理函数
HINSTANCE hMod,//应用程序实例句柄
DWORD dwThreadId//线程ID
);

钩子处理函数

LRESULT CALLBACK CBTProc(
int nCode,//钩子码,一般 为HCBT_CREATEWND
WPARAM wParam,//刚刚创建成功的窗口句柄
LPARAM lParam//...
)

更改窗口处理函数

LONG_PTR SetWindowLongPtr(
	HWND  hWnd,//窗口句柄
    int nIndex,//GWLP_WNDPROC
    LONG_PTR dwNewLong//新的窗口处理函数名(函数地址)
)

MFC的窗口如何创建

CMyFrameWnd *pFrame = new CMyFrameWnd;
pFrame->Create(NULL, "MFCBase");
//即Create的运行过程
  • 加载菜单
  • 调用CWnd::CreateEx函数创建窗口

{

​ 调用PreCreateWindow函数设计和注册窗口类

​ {

​ 调用AfxDeferRegisterClass函数

​ }

}

  • 调用AfxHookWindowCreate函数,埋下钩子
  • 调用CreateWindowEx函数创建窗口,马上调用钩子处理函数
  • 钩子处理函数_AfxCbtFilterHook
    • 将窗口句柄和框架类对象地址建立一对一的绑定关系
    • 使用SetWindowLong函数,将窗口处理的函数设置为AfxWndProc

消息映射机制

  • 在不重写WindowProc虚函数的大前提下,即可处理消息

  • 类必须具备的条件

    • 类内必须添加声明宏——DECLARE_MESSAGE_MAP()
    • 类外必须添加实现宏
      • BEGIN_MESSAGE_MAO(theClass, baseClass)
      • END_MESSAGE_MAP()
  • 总结:当一个类具备上述两个条件,这个类就可以按照消息映射进制来处理消息

  • example

    class CMyFrameWnd :public CFrameWnd {
    	DECLARE_MESSAGE_MAP()
    public:
    	LRESULT OnCreate(WPARAM wParam, LPARAM lParam);
    };
    
    BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
    	ON_MESSAGE(WM_CREATE,OnCreate)
    END_MESSAGE_MAP()
    
    LRESULT CMyFrameWnd::OnCreate(WPARAM wParam, LPARAM lParam) {
    	AfxMessageBox("WM_CREATE");
    	return 0;
    }
    
  • 运行机制——遍历链表(本类的静态变量和静态数组,父类的静态变量和静态数组),当消息产生的时候,带着消息的ID遍历链表寻找对应的消息函数完成相应的处理。

消息的分类

  • 标准windows消息

    ON_WM_XXX

    class CMyFrameWnd :public CFrameWnd {
    	DECLARE_MESSAGE_MAP()
    public:
    	int OnCreate(LPCREATESTRUCT pcs);
    };
    
    BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
    	ON_WM_CREATE()
    END_MESSAGE_MAP()
    
    int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
    	AfxMessageBox("WM_CREATER IDLE");
    	return CFrameWnd::OnCreate(pcs);//防止父类的create函数被屏蔽
    }
    
  • 自定义消息

    ON_MESSAGE

  • 命令消息

    ON_COMMAND

菜单

  • 菜单相关问题

    • Win32-HMENU
    • MFC-CMenu类对象
  • CMenu封装了一个重要的成员变量m_hMenu(菜单句柄)

  • 菜单的创建方法

    • 添加菜单资源rc文件,同时注意#include “resource.h”,可视化操作新增菜单对象

    • 将菜单设置到窗口

      • 方法一:利用pFrame调用Create函数时,传参;

      • 方法二:在处理框架窗口的WM_CREATE消息时,

        CMenu menu;
        menu.LoadMenu(...);
        
  • example

#include<afxwin.h>
#include "resource.h"
class CMyFrameWnd :public CFrameWnd {
	DECLARE_MESSAGE_MAP()
public:
	int OnCreate(LPCREATESTRUCT pcs);
public:
	CMenu menu;//保证生命周期
};

BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
	ON_WM_CREATE()
END_MESSAGE_MAP()

int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
	menu.LoadMenu(IDR_MENU1);//绑定菜单句柄和menu对象
	this->SetMenu(&menu);
	return CFrameWnd::OnCreate(pcs);
}

class CMyWinApp :public CWinApp {
public:
	virtual BOOL InitInstance();
};

BOOL CMyWinApp::InitInstance() {
	CMyFrameWnd *pFrame = new CMyFrameWnd;
    //方法一,传参
	//pFrame->Create(NULL, "MFCMenu",WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,
	//	NULL,(CHAR*)IDR_MENU1);
	pFrame->Create(NULL, "MFCMenu");
	m_pMainWnd = pFrame;
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;
}

CMyWinApp theApp;//爆破点
  • 命令消息的处理顺序

    对于ON_COMMMADE而言,框架类>应用程序类(对于同一个消息)

  • 下拉菜单、菜单状态选项、右键菜单的例子

#include<afxwin.h>
#include "resource.h"
class CMyFrameWnd :public CFrameWnd {
	DECLARE_MESSAGE_MAP()
public:
	afx_msg int OnCreate(LPCREATESTRUCT pcs);
	afx_msg void OnNew();
	afx_msg void OnInitMenuPopup(
		CMenu* pPopupMenu,
		UINT nIndex,
		BOOL bSysMenu);
	afx_msg void OnContextMenu(CWnd* pWnd, CPoint pos);
public:
	CMenu menu;//保证生命周期,代表整个大菜单
};

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
	ON_COMMAND(ID_new, OnNew)
	ON_WM_CREATE()
	ON_WM_INITMENUPOPUP()
	ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()


//右键菜单
void CMyFrameWnd::OnContextMenu(CWnd* pWnd, CPoint pos) {
	方法一:调用win32api 
	//HMENU hPopup = ::GetSubMenu(menu.m_hMenu, 0);//获取顶层菜单某一菜单的下一菜单
	//::TrackPopupMenu(hPopup, TPM_LEFTALIGN | TPM_TOPALIGN, pos.x, pos.y, 0,
	//	this->m_hWnd, NULL);

	//方法二:采用MFC对象
	CMenu *pPopup = menu.GetSubMenu(0);
	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, pos.x, pos.y,this);


}

//设置菜单项状态
void CMyFrameWnd::OnInitMenuPopup(
	CMenu* pPopupMenu,
	UINT nIndex,
	BOOL bSysMenu) {
	pPopupMenu->CheckMenuItem(ID_new, MF_CHECKED);
	//::CheckMenuItem(pPopupMenu->m_hMenu, ID_new, MF_CHECKED);
}


//菜单选项消息响应
void CMyFrameWnd::OnNew() {
	AfxMessageBox("新建");
}


//绑定UI菜单到程序
int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
	menu.LoadMenu(IDR_MENU1);//绑定菜单句柄和menu对象
	this->SetMenu(&menu);
	return CFrameWnd::OnCreate(pcs);
}


class CMyWinApp :public CWinApp {
public:
	virtual BOOL InitInstance();
};

//基本应用框架
BOOL CMyWinApp::InitInstance() {
	CMyFrameWnd *pFrame = new CMyFrameWnd;

	//绑定菜单
	//pFrame->Create(NULL, "MFCMenu",WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,
	//	NULL,(CHAR*)IDR_MENU1);

	pFrame->Create(NULL, "MFCMenu");
	m_pMainWnd = pFrame;
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;
}

CMyWinApp theApp;

工具栏

  • 相关的类
    • CToolBarCtrl——父类为CWnd,封装了关于工具栏控件的各种操作。(不是工具栏,是工具栏里面的一个一个的按钮)
    • CToolBar——父类CControlBar,封装了关于工具栏的操作,以及和框架窗口的关系。(这个才是工具栏)
  • 工具栏的创建使用
    • 添加工具栏资源(rc文件,可视化操作)
    • 创建工具栏 CToolBar::CreateEx
    • 加载工具栏CTool::LoadToolBar
    • 设置工具栏的停靠(看看就好)
      • CToolBar::EnableDocking
      • CFrameWnd::EnableDocking
      • CFrameWnd::DockControlBar
  • example
#include<afxwin.h>
#include "resource.h"
#include<afxext.h>//CToolBar类为拓展类

class CMyFrameWnd :public CFrameWnd {
	DECLARE_MESSAGE_MAP()
public:
	afx_msg int OnCreate(LPCREATESTRUCT pcs);
	afx_msg void OnNew();
	afx_msg void OnSet();
public:
	CMenu menu;
	CToolBar toolbar;
};

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
	ON_COMMAND(ID_set,OnSet)
	ON_COMMAND(ID_new,OnNew)
	ON_WM_CREATE()
END_MESSAGE_MAP()

//绑定菜单、工具栏
int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs){
	//绑定菜单
	menu.LoadMenu(IDR_MENU1);//绑定菜单句柄和menu对象
	this->SetMenu(&menu);

	//绑定工具栏
	toolbar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP);
	toolbar.LoadToolBar(IDR_TOOLBAR1);
	return CFrameWnd::OnCreate(pcs);
}


void CMyFrameWnd::OnSet(){
	AfxMessageBox("green");
}
void CMyFrameWnd::OnNew() {
	AfxMessageBox("new");
}

class CMyWinApp :public CWinApp {
public:
	virtual BOOL InitInstance();
};

BOOL CMyWinApp::InitInstance() {
	CMyFrameWnd *pFrame = new CMyFrameWnd;
	pFrame->Create(NULL, "MFCToolBar");
	m_pMainWnd = pFrame;
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;

}

CMyWinApp theApp;

运行时类信息机制

  • MFC六大机制

    • 程序启动机制
    • 窗口创建机制
    • 消息映射机制
    • 运行时类信息机制
    • 动态创建机制
    • 序列化机制
  • 含义:在程序运行过程中可以获知对象的类的相关信息(例如:对象是否属于某个类)

  • 运行时类信息机制的使用(具备三个要件)

    • 类必须派生自CObject
    • 类内必须添加声明宏 DECLARE_DYNAMIC(theClass)
    • 类外必须添加实现宏 IMPLEMENT_DYNAMIC(theClass,baseClass)
    • 当一个类具备上述三个要件后,CObject::IsKindOf函数就可以正确判断对象是否属于某个类
  • example

#include<afxwin.h>
#include <iostream>
using namespace std;

class CAnimal :public CObject {
	DECLARE_DYNAMIC(CAnimal)
};
IMPLEMENT_DYNAMIC(CAnimal,CObject)

class CDog :public CObject {
	DECLARE_DYNAMIC(CDog)
};
IMPLEMENT_DYNAMIC(CDog,CAnimal)

int main()
{
	CDog yellowdog;
	if (yellowdog.IsKindOf(RUNTIME_CLASS(CDog))) {
		cout << "yellowdog is dog";
	}
	else {
		cout << "yelllowdog isnot dog";
	}
    
	return 0;
}
  • 运行机制:还是宏展开链表追踪,重点的宏展开是RUNTIME_CLASS(class)

动态创建机制

  • 作用:在不知道类名的情况下,将类的对象创建出来。

  • 使用方法

    • 类必须派生自CObject

    • 类内必须添加声明宏 DECLARE_DYNCREATE(theClass)

    • 类外必须添加实现宏 IMPLEMENT_DYNCREATE(theClass,baseClass)

    • 当一个类具备上述三个要件后,CRuntimeClass::CreateObject(对象加工厂)

      函数就可以将类的对象创建出来

  • example

#include<afxwin.h>
#include <iostream>
using namespace std;

class CAnimal :public CObject {
	DECLARE_DYNAMIC(CAnimal)
};
IMPLEMENT_DYNAMIC(CAnimal,CObject)

class CDog :public CObject {
	DECLARE_DYNCREATE(CDog)
};
IMPLEMENT_DYNCREATE(CDog,CAnimal)

int main()
{
	CObject *pob= RUNTIME_CLASS(CDog)->CreateObject();//对象加工厂函数
	if (pob) {
		cout << pob<<endl;
	}
	else {
		cout << "对象创建失败";
	}
	return 0;
}

  • 抛弃单兵作战的思想,你设置对象,MFC帮你创建

视图窗口

  • 提供一个用于显示数据的窗口

  • CView类,封装了关于视图窗口的各种操作,以及和文档类(后台处理数据)的数据交互,其父类为CWnd类。

  • 命令消息的处理顺序(暂时)

    对于ON_COMMMADE而言,视图类>框架类>应用程序类(对于同一个消息)

  • 视图窗口的使用

    • 定义一个自己的视图类(CMyView),派生自CView,并重写父类成员纯虚函数OnDraw(可用于绘图)
    • 其余框架类和应用层程序类代码不变
    • 在处理框架窗口的WM_CREATE消息时,定义CMyView类对象,并调用Create函数创建视图窗口,视图窗口的ID设置为AFX_IDW_PANE_FIRST(设置其大小同框架类画布)
  • example

#include<afxwin.h>
class CMyView : public CView {
public:
	void OnDraw(CDC *pDC);
};

//重写纯虚函数
void CMyView::OnDraw(CDC *pDC) {
}

class CMyFrameWnd : public CFrameWnd {
	DECLARE_MESSAGE_MAP()
public:
	afx_msg int OnCreate(LPCREATESTRUCT pcs);
};
BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
	ON_WM_CREATE()
END_MESSAGE_MAP()

int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
	CMyView * pView = new CMyView;
	pView->Create(NULL, "MFCVIEW", WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(0, 0, 200, 200),
		this, AFX_IDW_PANE_FIRST);//视图ID设置为平铺在整个框架窗口上
	this->m_pViewActive = pView;//视图类对象地址绑定
	return CFrameWnd::OnCreate(pcs);
}

class CMyWinAPP : public CWinApp {
	virtual BOOL InitInstance();
};

BOOL CMyWinAPP::InitInstance() {
	CMyFrameWnd *pFrame = new CMyFrameWnd;
	pFrame->Create(NULL, "MFCVIEW");
	this->m_pMainWnd = pFrame;//框架类对象地址绑定
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;
}

CMyWinAPP theApp;//爆破点
  • 对象关系
this->m_pMainWnd = pFrame;//框架类对象地址绑定
this->m_pViewActive = pView;//视图类对象地址绑定
——theApp
    ->m_pMainWnd(pFrame框架类对象)
    	->m_pViewActive(pView视图类对象地址)
一一绑定,获得theApp即可得到所有的类地址

文档类

  • CDocument:提供了一个用于管理数据的类,封装了关于数据的管理(数据管理,数据转换,数据存储等),并和视图类进行数据交互。

  • 程序的创建过程

    • 利用框架类对象地址pFrame调用LoadFrame函数,创建框架窗口;
    • (父类)在处理框架窗口的WM_CREATE的消息时,动态创建视图类对象,并创建视图窗口;
    • (父类)在处理视图窗口的WM_CREATE的消息时,将文档类对象和视图类对象建立关联关系。
  • 对象关系图

    • 文档类对象用一个链表成员变量,保存视图类对象地址;
    • 视图类对象用一个普通成员变量,保存文档类对象地址;
——theApp
    |->m_pMainWnd(pFrame框架类对象地址)
    	|->m_pViewActive(pView视图类对象地址,活动视图类对象地址,视图可以有多个,但活动视图只有一个)
    		|->m_pDocument(文档类对象地址pDoc)
    			|->m_viewList(所有视图类对象地址,一个链表,m_viewList.AddTail(pView))
//一一绑定,获得theApp即可得到所有的类地址;
//一个视图对应一个文档;一个文档可以对应多个视图;
  • example
#include<afxwin.h>
#include<afxext.h>
#include "resource.h"
class CMyDoc :public CDocument {
};

class CMyView :public CView {
	DECLARE_DYNCREATE(CMyView)//动态创建机制
	DECLARE_MESSAGE_MAP()//消息映射机制
public:
	virtual void OnDraw(CDC * pDC);//重写纯虚函数
	afx_msg int OnCreate(LPCREATESTRUCT pcs);
};
IMPLEMENT_DYNCREATE(CMyView,CView)
BEGIN_MESSAGE_MAP(CMyView,CView)
	ON_WM_CREATE()
END_MESSAGE_MAP()

int CMyView::OnCreate(LPCREATESTRUCT pcs) {
	//return 0;//文档类和视图类没法关联
	return CView::OnCreate(pcs);//将文档类对象和视图类对象建立关联关系
}

void CMyView::OnDraw(CDC * pDC) {
	pDC->TextOut(100, 100, "this is view window");//父类处理视图动态创建的说明
}

class CMyFrameWnd :public CFrameWnd {
	DECLARE_MESSAGE_MAP()
public:
	afx_msg int OnCreate(LPCREATESTRUCT pcs);//pcs这个参数可以获取::CreateWindowEx的12个参数
};
BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
	ON_WM_CREATE()
END_MESSAGE_MAP()

int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
	//return 0;//MFC父类自动创建视图窗口的证明
	return CFrameWnd::OnCreate(pcs);
}


class CMyWinApp :public CWinApp {
public:
	virtual BOOL InitInstance();
};

BOOL CMyWinApp::InitInstance() {
	CMyFrameWnd *pFrame = new CMyFrameWnd;
	CMyDoc *pDoc = new CMyDoc;

	CCreateContext cct;
	cct.m_pCurrentDoc = pDoc;//文档类对象地址
	cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);//&CMyView::classCMyView,即视图类的静态变量的地址
	
	pFrame->LoadFrame(IDR_MENU1, WS_OVERLAPPEDWINDOW, NULL,&cct);//创建框架窗口
	m_pMainWnd = pFrame;
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;
}

CMyWinApp theApp;

窗口切分

  • 相关类

    CSplitterWnd——不规则框架窗口类,封装了关于不规则框架窗口的操作;

  • 窗口切分的使用

    重写CFrameWnd类的成员虚函数OnCreateClient

    • 在虚函数中调用CSplitterWnd::CreateStatic创建不规则框架窗口
    • 在虚函数中调用CSplitterWnd::CreateView创建视图窗口
  • example

#include<afxwin.h>
#include<afxext.h>
#include "resource.h"
class CMyDoc :public CDocument {
};

class CMyView :public CView {
	DECLARE_DYNCREATE(CMyView)//动态创建机制
	DECLARE_MESSAGE_MAP()//消息映射机制
public:
	virtual void OnDraw(CDC * pDC);//重写纯虚函数
	afx_msg int OnCreate(LPCREATESTRUCT pcs);
};
IMPLEMENT_DYNCREATE(CMyView,CView)
BEGIN_MESSAGE_MAP(CMyView,CView)
	ON_WM_CREATE()
END_MESSAGE_MAP()

int CMyView::OnCreate(LPCREATESTRUCT pcs) {
	//return 0;//文档类和视图类没法关联
	return CView::OnCreate(pcs);//将文档类对象和视图类对象建立关联关系
}

void CMyView::OnDraw(CDC * pDC) {
	pDC->TextOut(100, 100, "this is view window");//父类处理视图动态创建的说明
}

class CMyFrameWnd :public CFrameWnd {
	DECLARE_MESSAGE_MAP()
public:
	CSplitterWnd split;//提高生命周期
public:
	afx_msg int OnCreate(LPCREATESTRUCT pcs);//pcs这个参数可以获取::CreateWindowEx的12个参数
	afx_msg BOOL OnCreateClient(LPCREATESTRUCT pcs, CCreateContext *pContext);
};
BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
	ON_WM_CREATE()
END_MESSAGE_MAP()

BOOL CMyFrameWnd::OnCreateClient(LPCREATESTRUCT pcs, CCreateContext *pContext) {
	//创建两个视图窗口,父类处理OnCreate消息时自动把两个视图和唯一的文档类关联
	split.CreateStatic(this, 1, 2);//父类,1行两列
	split.CreateView(0, 0, pContext->m_pNewViewClass, CSize(100, 100), pContext);
	split.CreateView(0, 1, pContext->m_pNewViewClass, CSize(100, 100), pContext);
	return TRUE;
}

int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
	//return 0;//MFC父类自动创建视图窗口的证明
	return CFrameWnd::OnCreate(pcs);
}

class CMyWinApp :public CWinApp {
public:
	virtual BOOL InitInstance();
};

BOOL CMyWinApp::InitInstance() {
	CMyFrameWnd *pFrame = new CMyFrameWnd;
	CMyDoc *pDoc = new CMyDoc;

	CCreateContext cct;
	cct.m_pCurrentDoc = pDoc;//文档类对象地址
	cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);//&CMyView::classCMyView,即视图类的静态变量的地址
	
	pFrame->LoadFrame(IDR_MENU1, WS_OVERLAPPEDWINDOW, NULL,&cct);//创建框架窗口
	m_pMainWnd = pFrame;
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;
}

CMyWinApp theApp;
  • 命令消息的处理顺序

    对于ON_COMMMADE而言,视图类>文档类>框架类>应用程序类(对于同一个消息)

  • 文档类成员函数

    ​ 当文档类数据发生变化是,调用UpDateAllViews函数刷新和文档类对象相关联的视图类对象(视图窗口)

    void CMyDoc::OnNew() {
    	this->str = "hello world!";//表示接收到的数据,比如网络的socket等
    	//this->UpdateAllViews(NULL);//刷新和这个文档类对象(this)关联的所有视图窗口
    	//刷新单独的窗口
    	POSITION pos = this->GetFirstViewPosition();//GetFirstXXXPosition,迭代器函数,获取链表头结点的上一个结点
    	CView *pView = this->GetNextView(pos);//GetNextXXXPosition,迭代器函数,获取链表的下一个结点
    	this->UpdateAllViews(pView);//刷新和这个文档类对象this关联的除了pView指向的视图窗口
    }
    
    //---------------------------------------------------
    void CMyView::OnDraw(CDC * pDC) {
    	CMyDoc *pDoc = (CMyDoc*)this->m_pDocument;
    	pDC->TextOut(100, 100, pDoc->str);//父类处理视图动态创建的说明
    }
    
    #include<afxwin.h>
    #include<afxext.h>
    #include "resource.h"
    class CMyDoc :public CDocument {
    	DECLARE_MESSAGE_MAP()
    public:
    	afx_msg void OnNew();
    public:
    	CString str;//数据
    };
    BEGIN_MESSAGE_MAP(CMyDoc, CDocument)
    	ON_COMMAND(ID_NEW, OnNew)
    END_MESSAGE_MAP()
    
    void CMyDoc::OnNew() {
    	this->str = "hello world!";//表示接收到的数据,比如网络的socket等
    	//this->UpdateAllViews(NULL);//刷新和这个文档类对象(this)关联的所有视图窗口
    	
    	//刷新单独的窗口
    	POSITION pos = this->GetFirstViewPosition();//GetFirstXXXPosition,迭代器函数,获取链表头结点的上一个结点
    	CView *pView = this->GetNextView(pos);//GetNextXXXPosition,迭代器函数,获取链表的下一个结点
    	this->UpdateAllViews(pView);//刷新和这个文档类对象this关联的除了pView指向的视图窗口
    }
    
    class CMyView :public CView {
    	DECLARE_DYNCREATE(CMyView)//动态创建机制
    	DECLARE_MESSAGE_MAP()//消息映射机制
    public:
    	virtual void OnDraw(CDC * pDC);//重写纯虚函数
    	afx_msg int OnCreate(LPCREATESTRUCT pcs);
    	afx_msg void OnNew();
    };
    IMPLEMENT_DYNCREATE(CMyView,CView)
    BEGIN_MESSAGE_MAP(CMyView,CView)
    	ON_WM_CREATE()
    	//ON_COMMAND(ID_NEW,OnNew)
    END_MESSAGE_MAP()
    
    void CMyView::OnNew() {
    	AfxMessageBox("view class deal with WM_COMMAND message");
    }
    
    int CMyView::OnCreate(LPCREATESTRUCT pcs) {
    	//return 0;//文档类和视图类没法关联
    	return CView::OnCreate(pcs);//将文档类对象和视图类对象建立关联关系
    }
    
    void CMyView::OnDraw(CDC * pDC) {
    	CMyDoc *pDoc = (CMyDoc*)this->m_pDocument;
    	pDC->TextOut(100, 100, pDoc->str);//父类处理视图动态创建的说明
    }
    
    class CMyFrameWnd :public CFrameWnd {
    	DECLARE_MESSAGE_MAP()
    public:
    	CSplitterWnd split;
    public:
    	afx_msg int OnCreate(LPCREATESTRUCT pcs);//pcs这个参数可以获取::CreateWindowEx的12个参数
    	afx_msg BOOL OnCreateClient(LPCREATESTRUCT pcs, CCreateContext *pContext);
    };
    BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)
    	ON_WM_CREATE()
    END_MESSAGE_MAP()
    
    BOOL CMyFrameWnd::OnCreateClient(LPCREATESTRUCT pcs, CCreateContext *pContext) {
    	//创建两个视图窗口,父类处理OnCreate消息时自动把两个视图和唯一的文档类关联
    	split.CreateStatic(this, 1, 2);//父类,1行两列
    	split.CreateView(0, 0, pContext->m_pNewViewClass, CSize(100, 100), pContext);
    	split.CreateView(0, 1, pContext->m_pNewViewClass, CSize(100, 100), pContext);
    	this->m_pViewActive = (CView*)split.GetPane(0, 0);//设置活动窗口0行0列
    	return TRUE;
    }
    
    int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
    	//return 0;//MFC父类自动创建视图窗口的证明
    	return CFrameWnd::OnCreate(pcs);
    }
    
    class CMyWinApp :public CWinApp {
    public:
    	virtual BOOL InitInstance();
    };
    
    BOOL CMyWinApp::InitInstance() {
    	CMyFrameWnd *pFrame = new CMyFrameWnd;
    	CMyDoc *pDoc = new CMyDoc;
    
    	CCreateContext cct;
    	cct.m_pCurrentDoc = pDoc;//文档类对象地址
    	cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);//&CMyView::classCMyView,即视图类的静态变量的地址
    	
    	pFrame->LoadFrame(IDR_MENU1, WS_OVERLAPPEDWINDOW, NULL,&cct);//创建框架窗口
    	m_pMainWnd = pFrame;
    	pFrame->ShowWindow(SW_SHOW);
    	pFrame->UpdateWindow();
    	return TRUE;
    }
    
    CMyWinApp theApp;
    
  • 视图类成员函数

    获取和视图类对象关联的文档类对象,调用GetDocument(),这是公有函数,和m_pDocument的保护成员不一样,但返回的都是文档的地址。

代码基本同上

void CMyView::OnDraw(CDC * pDC) {
	//CMyDoc *pDoc = (CMyDoc*)this->m_pDocument;
	CMyDoc *pDoc = (CMyDoc*)this->GetDocument();
	pDC->TextOut(100, 100, pDoc->str);//父类处理视图动态创建的说明
}

单文档视图架构

  • 特点:只能有一个文档类对象,只能有一份数据

  • 参与架构的类

    CFrameWnd/ CWinApp/ CView /CDocument

  • 需要用到的类

    • CDocTemplate(文档模板类)

      ​ |->CSingleDocTemplate(单文档模板类)

    • CDocManager(文档管理类)

  • win32程序书写:参与架构的四个类除了应用程序外,其余三个类均支持动态创建机制

  • 执行过程

theApp
    |->m_pDocManager//文档管理类对象地址
    	|->m_templateList//单文档模板类对象地址
            |->CSingleDocTemplate *pTemplate
                |->m_pOnlyDoc//唯一的文档类对象地址
                |->m_pDocClass//RUNTIME_CLASS(CMyDoc),
                |->m_pFrameClass//RUNTIME_CLASS(CMyFrameWnd), 
                |->m_ppViewClass//RUNTIME_CLASS(CMyView),
  • example
#include <afxwin.h>
#include "resource.h"

class CMyDoc: public CDocument{
	DECLARE_DYNCREATE(CMyDoc)
};
IMPLEMENT_DYNCREATE(CMyDoc,CDocument)

class CMyView :public CView {
	DECLARE_DYNCREATE(CMyView)
public:
	virtual void OnDraw(CDC *pDC);
};
IMPLEMENT_DYNCREATE(CMyView,CView)

void CMyView::OnDraw(CDC *pDC) {
	pDC->TextOut(100, 100, "view window");
}

class CMyFrameWnd :public CFrameWnd {
	DECLARE_DYNCREATE(CMyFrameWnd)
};
IMPLEMENT_DYNCREATE(CMyFrameWnd,CFrameWnd)


class CMyWinApp :public CWinApp {
public:
	virtual BOOL InitInstance();
};

BOOL CMyWinApp::InitInstance(){
	CSingleDocTemplate *pTemplate = new CSingleDocTemplate(IDR_MENU1,
		RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMyFrameWnd), RUNTIME_CLASS(CMyView));
	AddDocTemplate(pTemplate);
	OnFileNew();
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();
	return TRUE;
};
CMyWinApp theApp;

  • MFC自动生成:善用类向导,创建消息、命令函数。(类视图和类向导,神器)

多文档视图架构

  • 可以管理多份文档,可以有多份数据

  • 参与架构的类(5个)

    CMDIFrameWnd/ CMDIChildWnd/ CWinApp/ CView / CDocument

  • 需要用到的类

    • CDocTemplate(文档模板类)

      ​ |->CMultiDocTemplate(单文档模板类)

    • CDocManager(文档管理类)

  • 两个框架窗口,一个主框架,一个子框架

  • 执行过程

theApp
    |->m_pDocManager//文档管理类对象地址
    	|->m_templateList//多文档模板类对象地址
    		|->CMultiDocTemplate *pTemplate
    			|->m_docList//保存多个文档类对象地址
    			|->m_pDocClass//RUNTIME_CLASS(CMyDoc)
    			|->m_pFrameClass//RUNTIME_CLASS(CMyChild)
    			|->m_pViewClass//RUNTIME_CLASS(CMyView)

MFC绘图

  • WINDOWS下的绘图,需要 绘图设备

    • WIN32——绘图设备句柄(HDC)

    • MFC——类对象

    • 所以类对象要和HDC绑定一对一的关系才行

  • 绘图相关类

    • CDC类(绘图设备类):封装了各种绘图相关的函数,以及两个非常重要的成员变量m_hDC和m_hAttribDC(这两个成员变量保存着绘图设备句柄)
      • CPaintDC类,封装了在WM_PAINT消息中绘图的绘图设备
      • CClientDC类,封装了在客户区绘图的绘图设备
    • CGdiObject(绘图对象类):封装了各种绘图对象相关的操作,以及一个非常重要的成员变量m_hObject(绘图对象句柄)
      • CPen类,封装了画笔的操作;
      • CBrush类,封装了画刷的操作;
      • CFont类,封装了字体的操作;
      • CBitmap,封装了位图的操作;
  • example:在view类下面创建消息(使用类向导)

//窗口一变即OnPaint,可以一直存在,即WM_PAINT消息
void CMFCDrawView::OnPaint()
{
	CPaintDC dc(this); // device context for painting
					   // TODO: 在此处添加消息处理程序代码
					   // 不为绘图消息调用 CView::OnPaint()
	//dc.Rectangle(100, 100, 300, 300);//画家在视图窗口上画矩形
}


//不能一直保持,窗体大小改变即消失,需要重现点击
void CMFCDrawView::OnClient()
{
	// TODO: 在此添加命令处理程序代码
	CClientDC dc(this);
	dc.Ellipse(300, 300, 500, 500);
}

//画笔绘制矩形
void CMFCDrawView::OnPen()
{
	// TODO: 在此添加命令处理程序代码
	CClientDC dc(this);//创建设备
	CPen pen(PS_SOLID, 2, RGB(255, 0, 0));//内部句柄已经绑定
	CPen *oldpen= dc.SelectObject(&pen);//把笔给设备,并返回老的笔
	dc.Rectangle(100, 100, 300, 300);//绘图设备绘图
	dc.SelectObject(oldpen);//选择老的笔
	pen.DeleteObject();//销毁创建的笔
}


//画刷填充矩形蓝色
void CMFCDrawView::OnBrush()
{
	// TODO: 在此添加命令处理程序代码
	CClientDC dc(this);
	CBrush brush(RGB(0, 0, 255));
	CBrush *oldbrush = dc.SelectObject(&brush);
	dc.Rectangle(100, 100, 300, 300);
	dc.SelectObject(oldbrush);
	brush.DeleteObject();
}


//输出不同字体
void CMFCDrawView::OnFont()
{
	// TODO: 在此添加命令处理程序代码
	CClientDC dc(this);

	CFont font;
	VERIFY(font.CreatePointFont(120, _T("黑体"), &dc));//断言判断

	CFont* def_font = dc.SelectObject(&font);
	dc.TextOut(5, 5, _T("Hello"), 5);
	dc.SelectObject(def_font);
	font.DeleteObject();

}


void CMFCDrawView::OnBitmap()
{
	/*
	//添加位图资源,可视化,不需写代码
	//创建一个和当前DC相匹配的内存DC
	CClientDC dc(this);
	CDC memdc;
	memdc.CreateCompatibleDC(&dc);

	//将位图数据送给内存DC
	CBitmap bmp;
	bmp.LoadBitmap(IDB_BITMAP1);
	CBitmap *oldbmp = memdc.SelectObject(&bmp);
	
	//成像
	dc.BitBlt(100, 100, 100,100, &memdc, 0, 0, SRCCOPY);

	//将位图数据要回来
	memdc.SelectObject(oldbmp);
	//销毁位图
	bmp.DeleteObject();
	//销毁内存DC
	memdc.DeleteDC();
	*/

	//方式二:居中视图
	CClientDC dc(this);
	CBitmap bmp;
	if (bmp.LoadBitmap(IDB_BITMAP1))
	{
		// 获取文件大小
		BITMAP bmpInfo;
		bmp.GetBitmap(&bmpInfo);

		//创建一个和当前DC相匹配的内存DC
		CDC dcMemory;
		dcMemory.CreateCompatibleDC(&dc);

		//将位图数据送给内存DC
		CBitmap* pOldBitmap = dcMemory.SelectObject(&bmp);

		// 找到居中区域
		CRect rect;
		GetClientRect(&rect);
		int nX = rect.left + (rect.Width() - bmpInfo.bmWidth) / 2;
		int nY = rect.top + (rect.Height() - bmpInfo.bmHeight) / 2;

		//显示到居中区域
		dc.BitBlt(nX, nY, bmpInfo.bmWidth, bmpInfo.bmHeight, &dcMemory,
			0, 0, SRCCOPY);

		dcMemory.SelectObject(pOldBitmap);

		dcMemory.DeleteDC();
	}
	else
	{
		TRACE0("ERROR: Where's IDB_BITMAP1?\n");
		AfxMessageBox(_T("error"));
	}
	bmp.DeleteObject();
}

序列化机制

  • MFC六大机制

    • 程序启动机制
    • 窗口创建机制
    • 消息映射机制
    • 运行时类信息机制
    • 动态创建机制
    • 序列化机制
  • 文件操作相关类:

    • CFile——文件操作类,封装了关于文件读写等操作

      • CFile::Open//创建和打开文件
      • CFile::Write/Read
      • CFile::Close
      • CFile::SeekToBegin/SeekToEnd/Seek
      • example
      #include<afxwin.h>
      #include<iostream>
      using namespace std;
      void File() {
      	CFile file;
      	file.Open(_T("E:/pro_test/MFC/MFCFile/file.txt"), CFile::modeCreate | CFile::modeReadWrite);//没有就新建,有就读写
      	char str[] = "hello file";
      	file.Write(str, strlen(str));
      	file.SeekToBegin();//从头开始读写
      	char buf[256] = {0};//初始化
      	long nlen = file.Read(buf, 255);//返回字节数
      	cout << buf << " " << nlen << endl;
      	file.Close();
      
      }
      int main() {
      	File();
      	return 0;
      }
      
  • 序列化的基本类型

    • 以二进制流的形式读写硬盘文件,但效果很高。
    • 序列化机制的相关类
      • CFile——文件操作类,完成硬盘文件的读写操作;
      • CAchive——归档类,完成内存数据的读写操作;
  • 序列化机制的使用:

    • 创建或打开文件——CFile::Open
    • 定义归档类对象——CArchive ar
    • 数据序列化(存储/写) ar<<数据
    • 关闭归档类对象 ar.Close()
    • 关闭文件 CFile::Close()
  • example

void Store() {//序列化(创建/加载/写)
	CFile file;
	file.Open(_T("E:/pro_test/MFC/MFCFile/serial.txt"), CFile::modeCreate | CFile::modeWrite);
	CArchive ar(&file, CArchive::store, 4096);//归档类对象,维护缓冲区,大小4096字节
	long age = 18;
	ar << age;
	float score = 88.5;
	ar << score;
	CString name = "zhangsan";
	cout << name << endl;
	ar << name;
	ar.Close();
	file.Close();

}

void Load() {//反序列化(加载/读)
	CFile file;
	file.Open(_T("E:/pro_test/MFC/MFCFile/serial.txt"), CFile::modeRead);
	CArchive ar(&file, CArchive::load, 4096);
	long age;
	ar >> age;
	float score;
	ar >> score;
	CString name;
	ar >> name;
	ar.Close();
	file.Close();
	cout << age << " " << score << " " << name << endl;
}

int main() {
	Store();
	Load();
	return 0;
}

序列化对象

  • 序列化对象的使用方法

    • 类必须派生自CObject
    • 类内必须添加声明宏 DECLARE_SERIAL(theClass)
    • 类外必须添加实现宏 IMPLEMENT_SERIAL(theClass, baseClass, 1)
    • 类必须重写虚函数 Serialize
    • 当类满足以上四个要件的时候,类对象就可以序列化到文件中保存了。
  • example

#include<afxwin.h>
#include<iostream>
using namespace std;

class CMyDoc :public CDocument {
	DECLARE_SERIAL(CMyDoc)
public:
	CMyDoc(int age = 0,float score= 0.0,CString name=""):m_age(age),m_score(score),m_name(name){}
	int m_age;
	float m_score;
	CString m_name;
	virtual void Serialize(CArchive &ar);
};
IMPLEMENT_SERIAL(CMyDoc,CDocument,1)

void CMyDoc::Serialize(CArchive &ar) {
	if (ar.IsStoring()) {
		ar << m_age << m_score << m_name;
	}
	else {
		ar >> m_age >> m_score >> m_name;
	}
}

void Store() {//序列化(创建/加载/写)
	CFile file;
	file.Open(_T("E:/pro_test/MFC/MFCFile/serial_class.txt"), CFile::modeCreate | CFile::modeWrite);
	CArchive ar(&file, CArchive::store, 4096);//归档类对象,维护缓冲区
	CMyDoc data(18, 88.5, "zhangsan");
	ar << &data;
	ar.Close();
	file.Close();

}

void Load() {//反序列化(加载/读)
	CFile file;
	file.Open(_T("E:/pro_test/MFC/MFCFile/serial_class.txt"), CFile::modeRead);
	CArchive ar(&file, CArchive::load, 4096);
	CMyDoc *pdate = NULL;
	ar >> pdate;
	ar.Close();
	file.Close();
	cout << pdate->m_age << " " << pdate->m_score << " " << pdate->m_name << endl;
}

int main() {
	Store();
	Load();
	return 0;
}

无模式对话框

  • 创建方法

    • 添加对话框资源
    • 查找资源 FindResource
    • 加载资源 LoadResource
    • 锁定资源 LockResource
    • 创建无模式对话框 CreateDialogIndirect
  • 参与架构的类 CDialog/ CWinApp

  • 代码书写

    • 添加对话框资源
    • 定义一个自己的对话框类(CMyDlg),管理对话框资源,派生自CDialog或CDialogEx均可
    • 其余代码详见以下的

对象和控件绑定

  • 一定是在对话框类里面进行成员变量的绑定,而不是应用程序类

  • 将控件窗口和类对象绑定具有两大作用

    • 如果和数据类对象绑定(CString等),对象和控件可以进行数据交换
    • 如果和控件类对象绑定(CButton等),对象可以代表整个控件
  • 和数据类对象绑定的使用

    • 重写父类虚函数DoDateExchange,在函数内部通过一系列的DDX_xxx函数,实现控件和数据类型对象的数据交互
    • 如果需要实现数据交互,调用UPdateData函数
      • UpdataData(TRUE):控件->变量
      • UpdataData(TRUE):变量->控件

滑块控件——Slide Control

  • dialog资源文件设置,插入控件,更改ID
  • 设置成员变量,使用类向导,绑定控件
  • OnInit函数初始化
BOOL CMFCDialgDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	//滑块初始化
	m_slider.SetRange(0, 100);
	m_slider.SetPos(50);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
  • 消息映射机制,拉动使用,发出WM_COMMAND消息(通知码NM_CUSTOMDRAW)

PS:可双击控件直接创建,也可使用类向导创建

void CMFCDialgDlg::OnNMCustomdrawSlider1(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	int pos = m_slider.GetPos();//获取位置
	CString strPos;
	strPos.Format(_T("滑块位置%d"), pos);
	this->SetWindowText(strPos);
	*pResult = 0;
}

进度条控件——Progress Control

  • CProgressCtrl类
    • SetRange
    • SetPos
    • GetPos
  • 操作同滑块控件
BOOL CMFCDialgDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	//初始化
	m_slider.SetRange(0, 100);
	m_slider.SetPos(50);
	m_progress.SetRange(0, 100);
	m_progress.SetPos(50);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}


//联动滑块和进度条
void CMFCDialgDlg::OnNMCustomdrawSlider1(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	int pos = m_slider.GetPos();
	CString strPos;
	strPos.Format(_T("滑块位置%d"), pos);
	this->SetWindowText(strPos);
	m_progress.SetPos(pos);
	*pResult = 0;
}

下压式按钮——CButton类

  • 消息WM_COMMAND,消息码(BN_CLICKED)

  • 对话框类绑定成员变量——类向导

  • 双击即可创建消息函数

  • 一般没有数据交换

编辑框——Edit Control

  • 应该先输入完然后和按钮联动,这样效果比较好

  • //只是例子,效果是每一个输入都会有弹框,即都有反应
    void CMFCDialgDlg::OnEnChangeEdit1()
    {
    	// TODO:  在此添加控件通知处理程序代码
    	TCHAR bud[256];
    	int length=m_edit.GetWindowText(bud,256);
    	AfxMessageBox(bud);
    }
    

复选框按钮——Check Box

  • 勾选和非勾选两种状态
  • 仍然是CButton类
  • m_check.GetCheck()——勾选即返回1
  • m_check.SetCheck(!m_check.GetCheck())
  • 属性的push_like是那个更改为TRUE,即变成多态按钮

单选框按钮——Radio Button

  • 仍然是CButton类
  • 一组单选框只能选一个
  • 一般不出现在类向导里面,要在属性里面的group框选为TRUE才可以
  • 互斥的关系要在点击单选框的消息函数里面自己写

分组框按钮——gruop box

  • 提高界面友好性
  • 仍然是CButton类
  • 就是框选单选按钮,看的更清楚,就是示意
  • ID: IDC_STATIC——不会出现在类向导里,更改之后可出现

文本静态框——Static Text

  • SetWindowText可设置内容,这是父类CWin的函数,一般控件都可用;
  • 但是文本静态一般只是展示,提高界面友好性的
  • ID: IDC_STATIC——不会出现在类向导里,更改之后可出现

图像静态框——Picture Control

  • 属性的杂项的type->Icon/Bitmap,一般是这两种类型
  • 属性里面的image可以一开始设置图片
  • ID: IDC_STATIC——不会出现在类向导里,更改之后可出现,如更改成IDC_PS
  • 显示图像操作
    • CStatic::SetIcon
    • CStatic::SetBitmap
  • example
m_ps.SetBitmap(::LoadBitmap(AfxGetInstanceHandle,MAKEINTRESOURCE()));//需要位图的句柄;如果是加载本程序的资源位图ID的话就需要获取当前程序的实例句柄和资源ID

组合框——Combo Box

  • 一般是下拉式,支持组合框编辑
  • 下拉链表时,不支持组合框编辑
  • CComboBox::AddString()——添加组合框选项
  • CComboBox::DeleteString——删除选项
  • CComboBox::GetCurSel——获取选择性索引
  • 获取选项文本内容——CComboBox::GetLBText
  • 选择项发生变化的时候,会发送WM_COMMAND消息

列表框——List Box

  • CListBox类
  • 常见操作
    • 添加选项CListBox::AddString
    • 删除选项CListBox::DeleteString
    • 获取选择项索引 CListBox::GetCurSel
    • 获取选项文本内容 CListBox::GetItemText

列表控件——List Control

  • CListCtrl类
  • 风格
    • 图标(LVS_ICON)
    • 小图标(LVS_SMALLICON)
    • 列表(LVS_LIST)
    • 报表(详细信息)(LVS_REPORT)
  • 修改风格 CWnd::ModifyStyle
  • 常见操作
    • 添加选项
    • 删除选项
    • 添加列
    • 设置文本内容
    • 设置图像
    • 设置附加数据
    • 获取附加数据
  • 当列表被双击,发出WM_COMMAND消息,通知码(LBN_DBLCLK)

树控件——Tree Control

  • CTreeCtrl
  • 常见操作
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值