MFC 学习笔记
一.MFC编程基础:
概述:
常用头文件:
MFC控制台程序:
MFC库程序:
规则库可以被各种程序所调用,扩展库只能被MFC程序调用。
MFC窗口程序:
示例:
MFC库中类的简介:
具体详细细节可以参考离线文档
第一个MFC程序:
1.创建一个win32程序
2.设置使用MFC
3.添加类
#include <afxwin.h> class CMyFrameWnd : public CFrameWnd{ }; class CMyWinApp : public CWinApp{ public: CMyWinApp() { } virtual BOOL InitInstance(){//此函数内部的this为&theApp CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCBase"); this->m_pMainWnd = pFrame; pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE; } }; CMyWinApp theApp;//爆破点
4.效果:
MFC程序启动:
AFX_MODULE_STATE aaa;//当前程序模块状态信息 AFX_MODULE_THREAD_STATE bbb; //当前程序线程状态信息 CWinApp::CWinApp()//构造全局对象CMyWinApp theApp { AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); //获取全局变量&aaa AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; //获取全局变量&bbb pThreadState->m_pCurrentWinThread = this;//将&theApp保存到bbb的一个成员中 AfxGetThread() { AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb CWinThread* pThread = pState->m_pCurrentWinThread; return pThread;//返回的为&theApp } pModuleState->m_pCurrentWinApp = this;//将&theApp保存到aaa的一个成员中 AfxGetApp() { return AfxGetModuleState()->m_pCurrentWinApp;//返回&theApp } }
通过将断点打在InitInstance()这个方法,在调用堆栈里可以看到MFC里封装的WinMain方法。
WinMain(...)//程序流程是不是theApp对象指导向哪走 { AfxWinMain(...) { 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(...) } } } }
二.MFC窗口和消息:
钩子简介:
#include <afxwin.h> class CMyFrameWnd : public CFrameWnd{ public: virtual LRESULT WindowProc( UINT msgID, WPARAM wParam, LPARAM ); }; LRESULT CMyFrameWnd::WindowProc( UINT msgID, WPARAM wParam, LPARAM lParam ){ //此函数内部的this为pFrame switch( msgID ){ case WM_CREATE: AfxMessageBox( "WM_CREATE消息被处理" ); break; case WM_PAINT: { PAINTSTRUCT ps = { 0 }; HDC hdc = ::BeginPaint( this->m_hWnd, &ps ); ::TextOut( hdc, 100, 100, "hello", 5 ); ::EndPaint( m_hWnd, &ps ); } break; } return CFrameWnd::WindowProc(msgID, wParam, lParam); } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; CMyWinApp theApp;//爆破点 BOOL CMyWinApp::InitInstance( ){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCCreate"); m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); return TRUE; }
MFC窗口创建过程:
CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCCreate")//函数内部this为pFrame(自己new框架类对象地址) { //加载菜单 CreateEx(..., NULL,...)//函数内部this为pFrame { CREATESTRUCT cs; .... cs.lpszClass = NULL;//下面将更改 ... cs.hInstance = AfxGetInstanceHandle(); //MFC里获取winMain的第一个参数 PreCreateWindow(cs) { AfxDeferRegisterClass(...) { //注册窗口类 WNDCLASS wndcls; ... wndcls.lpfnWndProc = DefWindowProc;//消息处理存在问题,下面将进行修改 ... _AfxRegisterWithIcon(&wndcls, "AfxFrameOrView100sd"..) { &wndcls->lpszClassName = "AfxFrameOrView100sd"; ::RegisterClass(&wndcls) //在这里执行窗口注册 } } cs.lpszClass = _afxWndFrameOrView; //"AfxFrameOrView100sd" } AfxHookWindowCreate(pFrame) { _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); //获取全局变量&ccc(当前程序线程信息) ::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook,...); //利用Win32的API函数,埋下一个类型为WH_CBT的钩子 pThreadState->m_pWndInit = pFrame; //将自己new的框架类对象pFrame保存到全局变量ccc的一个成员中。 } ::CreateWindowEx(...);//此函数一旦执行成功,立即转到钩子处理函数。 } } 钩子处理函数 _AfxCbtFilterHook(.wParam.) { _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();//获取&ccc CWnd* pWndInit = pThreadState->m_pWndInit;//获取pFrame===pWndInit HWND hWnd = (HWND)wParam;//刚刚创建成功的框架窗口句柄 pWndInit->Attach(hWnd)//函数内部this为pFrame,参数为窗口句柄 { CHandleMap* pMap = afxMapHWND(TRUE) { AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb pState->m_pmapHWND = new CHandleMap(..); //new了一个映射类对象,并将对象地址保存到bbb的一个成员中 return pState->m_pmapHWND; //返回映射类对象地址 } pMap->SetPermanent(m_hWnd = hWnd, pFrame)//函数内部this为pMap { m_permanentMap[hWnd] = pFrame; } } (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,AfxWndProc); //将窗口处理函数更改为AfxWndProc(才是真正的窗口处理函数) }
处理消息:
//以WM_CREATE消息为例,捎带想着点WM_PAINT消息 AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { CWnd* pWnd = CWnd::FromHandlePermanent(hWnd) { CHandleMap* pMap = afxMapHWND() { AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb return pState->m_pmapHWND;//返回就是之前保存在bbb中的映射类对象地址 } pWnd = pMap->LookupPermanent(hWnd)//函数内部this为pMap { return m_permanentMap[hWnd];//返回的为pFrame } } AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam)//参数pWnd===pFrame { pWnd->WindowProc(nMsg, wParam, lParam);//回到自己的代码 } }
消息映射机制:
在不重写WindowProc虚函数的大前提下,仍然可以处理消息。
具体实现:
#include <afxwin.h> class CMyFrameWnd : public CFrameWnd{ DECLARE_MESSAGE_MAP() protected: static const AFX_MSGMAP* PASCAL GetThisMessageMap(); virtual const AFX_MSGMAP* GetMessageMap() const; 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; } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; CMyWinApp theApp;//爆破点 BOOL CMyWinApp::InitInstance( ){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCCreate"); m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); return TRUE; }
将这几个宏替换:
#include <afxwin.h> class CMyFrameWnd : public CFrameWnd{ // DECLARE_MESSAGE_MAP() protected: static const AFX_MSGMAP* PASCAL GetThisMessageMap(); virtual const AFX_MSGMAP* GetMessageMap() const; public: LRESULT OnCreate( WPARAM wParam, LPARAM lParam ); }; //BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) // ON_MESSAGE( WM_CREATE, OnCreate ) //END_MESSAGE_MAP() const AFX_MSGMAP* CMyFrameWnd::GetMessageMap() const { return GetThisMessageMap(); } const AFX_MSGMAP* PASCAL CMyFrameWnd::GetThisMessageMap() { static const AFX_MSGMAP_ENTRY _messageEntries[] = { { WM_CREATE, 0, 0, 0, AfxSig_lwl, (AFX_PMSG)(AFX_PMSGW) (static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > (&OnCreate)) }, {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } }; static const AFX_MSGMAP messageMap = { &CFrameWnd::GetThisMessageMap, &_messageEntries[0] }; return &messageMap; } LRESULT CMyFrameWnd::OnCreate( WPARAM wParam, LPARAM lParam ){ AfxMessageBox( "WM_CREATE" ); return 0; } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; CMyWinApp theApp;//爆破点 BOOL CMyWinApp::InitInstance( ){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCCreate"); m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); return TRUE; }
AFX_MSGMAP_ENTRY结构体的解释:
AFX_MSGMAP结构体的解释:
展开各部分作用介绍:
创建窗口的原理:
代码:
//以WM_CREATE消息为例,捎带想着点WM_PAINT,WM_COMMAND(到了CWnd::OnWndMsg函数路线不一样) AfxWndProc(...) { CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); //获取和hWnd绑定在一起的框架类对象地址(pFrame===pWnd) AfxCallWndProc(pWnd...)//参数pWnd===pFrame { pWnd->WindowProc(...)//函数内部this为pFrame===pWnd ************* { OnWndMsg(...)//函数内部this为pFrame===pWnd { const AFX_MSGMAP* pMessageMap = GetMessageMap(); //获取本类宏站开的静态变量的地址(链表头结点) const AFX_MSGMAP_ENTRY* lpEntry; for (; pMessageMap->pfnGetBaseMap != NULL;//此for就是在遍历链表 pMessageMap = (*pMessageMap->pfnGetBaseMap)()) { lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,message, 0, 0)); //如果找到返回找到的数组元素的地址,如果没找到返回NULL if(lpEntry != NULL ) { goto LDispatch; } } LDispatch: lpEntry->pfn; //CMyFrameWnd::OnCreate 调用CMyFrameWnd::OnCreate函数完成消息的处理 } } } }
三.MFC消息:
消息的分类:
示例:
#include <afxwin.h> #define WM_MYMESSAGE WM_USER+1001 class CMyFrameWnd : public CFrameWnd{ DECLARE_MESSAGE_MAP() public: int OnCreate( LPCREATESTRUCT pcs); void OnPaint( ); void OnMouseMove( UINT nKey, CPoint pt ); LRESULT OnMyMessage( WPARAM wParam, LPARAM lParam ); int m_x; int m_y; }; BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_WM_CREATE() ON_WM_PAINT() ON_WM_MOUSEMOVE() ON_MESSAGE( WM_MYMESSAGE, OnMyMessage) END_MESSAGE_MAP() LRESULT CMyFrameWnd::OnMyMessage( WPARAM wParam, LPARAM lParam ){ CString str; str.Format( "wParam=%d,lParam=%d", wParam, lParam ); AfxMessageBox( str ); return 0; } void CMyFrameWnd::OnMouseMove( UINT nKey, CPoint pt){ m_x = pt.x; m_y = pt.y; ::InvalidateRect( this->m_hWnd, NULL, TRUE ); } void CMyFrameWnd::OnPaint( ){ PAINTSTRUCT ps = { 0 }; HDC hdc = ::BeginPaint( this->m_hWnd, &ps ); ::TextOut( hdc, m_x, m_y, "hello", 5); ::EndPaint( m_hWnd, &ps ); } int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){ AfxMessageBox("WM_CREATE消息被处理"); ::PostMessage( this->m_hWnd, WM_MYMESSAGE, 1, 2 ); return CFrameWnd::OnCreate( pcs ); } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; CMyWinApp theApp;//爆破点 BOOL CMyWinApp::InitInstance( ){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCCreate"); m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); return TRUE; }
MFC菜单:
菜单的使用:
方法一:
方法二:
#include <afxwin.h> #include "resource.h" class CMyFrameWnd : public CFrameWnd{ DECLARE_MESSAGE_MAP( ) public: afx_msg int OnCreate( LPCREATESTRUCT pcs ); afx_msg void OnNew( ); public: CMenu menu; }; BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd ) ON_COMMAND( ID_NEW, OnNew ) ON_WM_CREATE( ) END_MESSAGE_MAP( ) void CMyFrameWnd::OnNew( ){ AfxMessageBox( "框架类处理了新建菜单项被点击" ); } int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){ //调用api(win32)的loadmenu方法拿到句柄,将菜单句柄和menu对象建立一对一的关系。 menu.LoadMenu( IDR_MENU1 ); // this->SetMenu( &menu ); ::SetMenu( this->m_hWnd, menu.m_hMenu); return CFrameWnd::OnCreate( pcs ); } class CMyWinApp : public CWinApp{ DECLARE_MESSAGE_MAP() public: virtual BOOL InitInstance( ); afx_msg void OnNew( ); }; BEGIN_MESSAGE_MAP(CMyWinApp, CWinApp) ON_COMMAND( ID_NEW , OnNew ) END_MESSAGE_MAP( ) void CMyWinApp::OnNew( ){ AfxMessageBox( "应用程序类处理了新建被点击" ); } BOOL CMyWinApp::InitInstance( ){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCCreate"); m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); return TRUE; } CMyWinApp theApp;
菜单项没有对应的消息处理,就会默认灰显。
命令消息处理顺序:
(仅针对command消息类,其他类只有框架类处理一条路径)
框架类 ——> 应用程序处理类
设置菜单项状态:
设置右键菜单(上下文菜单):
代码:
#include <afxwin.h> #include "resource.h" class CMyFrameWnd : public CFrameWnd{ DECLARE_MESSAGE_MAP( ) public: //afx_msg 占位符 标识这个方法是处理消息的 afx_msg int OnCreate( LPCREATESTRUCT pcs ); afx_msg void OnNew( ); afx_msg void OnInitMenuPopup( CMenu *pPopup, UINT nPos, BOOL i ); afx_msg void OnContextMenu( CWnd* pWnd, CPoint pt ); 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 pt ){ //获取整个大菜单顶层为0的子菜单 // HMENU hPopup = ::GetSubMenu(menu.m_hMenu,0); // ::TrackPopupMenu( hPopup, TPM_LEFTALIGN|TPM_TOPALIGN, pt.x, pt.y, // 0, this->m_hWnd, NULL ); CMenu* pPopup = menu.GetSubMenu(0); pPopup->TrackPopupMenu( TPM_LEFTALIGN|TPM_TOPALIGN, pt.x, pt.y, this ); } void CMyFrameWnd::OnInitMenuPopup( CMenu* pPopup, UINT nPos, BOOL i){ // pPopup->CheckMenuItem( ID_NEW, MF_CHECKED ); ::CheckMenuItem( pPopup->m_hMenu, ID_NEW, MF_CHECKED ); } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; BOOL CMyWinApp::InitInstance( ){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCCreate"); m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); return TRUE; } CMyWinApp theApp;
效果:
四.MFC工具栏以及两大机制:
工具栏:
相关类:
工具栏的使用:
代码:
#include <afxwin.h> #include "resource.h" #include <afxext.h> class CMyFrameWnd : public CFrameWnd{ DECLARE_MESSAGE_MAP( ) public: afx_msg void OnNew( ); afx_msg void OnSet( ); afx_msg int OnCreate( LPCREATESTRUCT pcs ); public: CToolBar toolbar; }; BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd ) ON_COMMAND( ID_SET, OnSet) ON_COMMAND( ID_NEW, OnNew ) ON_WM_CREATE() END_MESSAGE_MAP() void CMyFrameWnd::OnSet( ){ AfxMessageBox( "绿色工具按钮被点击" ); } int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){ toolbar.CreateEx( this, TBSTYLE_FLAT, WS_CHILD|WS_VISIBLE|CBRS_ALIGN_TOP|CBRS_GRIPPER); toolbar.LoadToolBar( IDR_TOOLBAR1 ); //想停哪儿 toolbar.EnableDocking( CBRS_ALIGN_ANY ); //允许停哪儿 this->EnableDocking( CBRS_ALIGN_ANY ); //临时停哪儿 this->DockControlBar( &toolbar, AFX_IDW_DOCKBAR_BOTTOM ); return CFrameWnd::OnCreate( pcs ); } void CMyFrameWnd::OnNew(){ AfxMessageBox( "新建菜单项被点击" ); } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; BOOL CMyWinApp::InitInstance(){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create( NULL, "MFCToolBar", WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault, NULL, (CHAR*)IDR_MENU1); m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); return TRUE; } CMyWinApp theApp;
运行时类信息机制:
在程序运行过程中可以获知对象的类的相关信息(例如:对象是否属于某个类)
使用:
代码:
#include <afxwin.h> #include <iostream> using namespace std; class CAnimal : public CObject{ DECLARE_DYNAMIC( CAnimal ) }; IMPLEMENT_DYNAMIC( CAnimal, CObject ) class CDog : public CAnimal{ // DECLARE_DYNAMIC( CDog ) public: static const CRuntimeClass classCDog; virtual CRuntimeClass* GetRuntimeClass() const; }; //IMPLEMENT_DYNAMIC( CDog, CAnimal ) //IMPLEMENT_RUNTIMECLASS(CDog, CAnimal, 0xFFFF, NULL, NULL) AFX_COMDAT const CRuntimeClass CDog::classCDog = { "CDog", sizeof(class CDog), 0xFFFF, NULL, // RUNTIME_CLASS(CAnimal), ((CRuntimeClass*)(&CAnimal::classCAnimal)), NULL, NULL }; CRuntimeClass* CDog::GetRuntimeClass() const { // return RUNTIME_CLASS(CDog); return ((CRuntimeClass*)(&CDog::classCDog)); } int main(){ CDog yellowdog; if( yellowdog.IsKindOf( RUNTIME_CLASS(CWnd) ) ){ cout << "yellowdog is CWnd" << endl; }else{ cout << "yellowdog isnot CWnd" << endl; } return 0; }
CRuntimeClass的数据结构:
宏展开各部分:
执行过程:
关注这个宏 RUNTIME_CLASS(CDog)
伪代码:
yellowdog.IsKindOf( RUNTIME_CLASS(CDog))//函数内部this为&yellowdog,参数为链表头 { CRuntimeClass* pClassThis = GetRuntimeClass(); //利用&yellowdog调用宏展开虚函数,获取链表头结点 return pClassThis->IsDerivedFrom(RUNTIME_CLASS(CDog)) //函数内部this为链表头,参数也为链表头 { const CRuntimeClass* pClassThis = this;//获取链表头 while (pClassThis != NULL) { if (pClassThis == RUNTIME_CLASS(CDog)) return TRUE; pClassThis = pClassThis->m_pBaseClass; } return FALSE; } }
动态创建机制:
在不知道类名的情况下,将类的对象创建出来。
使用:
#include <afxwin.h> #include <iostream> using namespace std; class CAnimal : public CObject{ DECLARE_DYNAMIC( CAnimal ) }; IMPLEMENT_DYNAMIC( CAnimal, CObject ) class CDog : public CAnimal{ // DECLARE_DYNCREATE( CDog ) public: static const CRuntimeClass classCDog; virtual CRuntimeClass* GetRuntimeClass() const; static CObject* PASCAL CreateObject(); }; //IMPLEMENT_DYNCREATE( CDog, CAnimal ) CObject* PASCAL CDog::CreateObject() { return new CDog; } AFX_COMDAT const CRuntimeClass CDog::classCDog = { "CDog", sizeof(class CDog), 0xFFFF, CDog::CreateObject, RUNTIME_CLASS(CAnimal), NULL, NULL }; CRuntimeClass* CDog::GetRuntimeClass() const { return RUNTIME_CLASS(CDog); } int main(){ CObject* pob = RUNTIME_CLASS(CDog)->CreateObject( );//对象加工厂 if( pob ){ cout << pob << endl; }else{ cout << "对象创建失败" << endl; } return 0; }
与运行时类信息机制区别:
代码:
RUNTIME_CLASS(CDog)->CreateObject()//函数内部this为本类(CDog)的静态变量地址(链表头 { CObject* pObject = (*m_pfnCreateObject)() //CDog::CreateObject { return new CDog; } return pObject; }
五.MFC视图和文档
视图窗口:
提供了一个用于显示数据的窗口
相关类:
CView及其子类,父类为CWnd类,封装了关于视图窗口的各种操作,以及和文档类的数据交互。
使用:
命令消息处理顺序:
视图类 -> 框架类 ->应用程序类
对象关系图:
代码:
#include <afxwin.h> #include "resource.h" class CMyView : public CView{ DECLARE_MESSAGE_MAP( ) public: void OnDraw(CDC* pDC); afx_msg void OnPaint( ); afx_msg void OnNew( ); }; BEGIN_MESSAGE_MAP( CMyView, CView ) // ON_COMMAND( ID_NEW, OnNew ) // ON_WM_PAINT() END_MESSAGE_MAP() void CMyView::OnNew( ){ AfxMessageBox( "视图类处理了WM_COMMAND消息" ); } void CMyView::OnPaint( ){ PAINTSTRUCT ps = { 0 }; HDC hdc = ::BeginPaint( this->m_hWnd, &ps ); ::TextOut( hdc, 200, 200, "CMyView::OnPaint", strlen("CMyView::OnPaint") ); ::EndPaint( this->m_hWnd, &ps ); } void CMyView::OnDraw( CDC* pDC ){ pDC->TextOut( 100, 100, "CMyView::OnDraw" ); } class CMyFrameWnd : public CFrameWnd{ DECLARE_MESSAGE_MAP() public: afx_msg void OnPaint( ); afx_msg int OnCreate( LPCREATESTRUCT pcs ); afx_msg void OnNew( ); }; BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd ) ON_WM_PAINT( ) // ON_COMMAND( ID_NEW, OnNew ) ON_WM_CREATE( ) END_MESSAGE_MAP( ) void CMyFrameWnd::OnNew( ){ AfxMessageBox( "框架类处理了WM_COMMAND消息" ); } 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 ); this->m_pViewActive = pView; //视图类对象地址 return CFrameWnd::OnCreate( pcs ); } void CMyFrameWnd::OnPaint( ){ PAINTSTRUCT ps = { 0 }; HDC hdc = ::BeginPaint( this->m_hWnd, &ps ); ::TextOut( hdc, 100, 100, "我是框架窗口客户区", strlen("我是框架窗口客户区")); ::EndPaint( this->m_hWnd, &ps ); } class CMyWinApp : public CWinApp{ DECLARE_MESSAGE_MAP( ) public: virtual BOOL InitInstance( ); afx_msg void OnNew( ); }; BEGIN_MESSAGE_MAP(CMyWinApp,CWinApp) ON_COMMAND( ID_NEW, OnNew ) END_MESSAGE_MAP( ) void CMyWinApp::OnNew( ){ AfxMessageBox( "应用程序类处理了WM_COMMAND消息" ); } BOOL CMyWinApp::InitInstance( ){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->Create( NULL, "MFCView", WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault, NULL, (CHAR*)IDR_MENU1); this->m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); return TRUE; } CMyWinApp theApp;
文档类:
程序的创建过程:
代码:
CMyFrameWnd* pFrame = new CMyFrameWnd; CMyDoc* pDoc = new CMyDoc; CCreateContext cct; cct.m_pCurrentDoc = pDoc;//文档类对象地址 cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);//&CMyView::classCMyView pFrame->LoadFrame(... &cct)//函数内部this为pFrame { Create(...,&cct)//函数内部this为pFrame { CreateEx(...&cct)//函数内部this为pFrame { CREATESTRUCT cs; .... cs.lpCreateParams = &cct; ::CreateWindowEx(...,&cct);//创建主框架窗口 } } } //处理框架窗口的WM_CREATE消息 CFrameWnd::OnCreate( pcs )//函数内部this为pFrame,参数可以获取::CreateWindowEx的12个参数 { CCreateContext* pContext = (CCreateContext*)pcs->lpCreateParams;//获取&cct OnCreateHelper(pcs, pContext)//函数内部this为pFrame,pContext===&cct { OnCreateClient(pcs, pContext)//函数内部this为pFrame,pContext===&cct { CreateView(pContext..)//函数内部this为pFrame,pContext===&cct { CWnd* pView = pContext->m_pNewViewClass->CreateObject(); //动态创建视图类对象,并返回对象地址 pView->Create(..,pContext)//函数内部this为pView,pContext===&cct { CreateEx(..,pContext)//函数内部this为pView,pContext===&cct { CREATESTRUCT cs; .... cs.lpCreateParams = pContext;//pContext===&cct ::CreateWindowEx(...,pContext);//创建视图窗口 } } } } } } //处理视图窗口的WM_CREATE消息 CView::OnCreate( pcs )//函数内部this为pView,参数可以获取::CreateWindowEx函数的12个参数 { CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;//获取&cct pContext->m_pCurrentDoc->AddView(pView)//函数内部this为pDoc,参数为视图类对象地址 { m_viewList.AddTail(pView);//文档类对象用一个链表成员变量,保存视图类对象地址 pView->m_pDocument = this;//视图类对象用一个普通成员变量,保存文档类对象地址 } }
对象关系图:
窗口切分:
代码:
#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 CView::OnCreate( pcs ); //将文档类对象和视图类对象建立关联关系。 } void CMyView::OnDraw( CDC* pDC ){ pDC->TextOut( 100, 100, "我是视图窗口" ); } class CMyFrameWnd : public CFrameWnd{ DECLARE_MESSAGE_MAP( ) public: afx_msg int OnCreate( LPCREATESTRUCT pcs ); afx_msg void OnPaint( ); virtual BOOL OnCreateClient( LPCREATESTRUCT pcs, CCreateContext* pContext); CSplitterWnd split;//不规则框架窗口 }; BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd ) ON_WM_PAINT( ) ON_WM_CREATE( ) END_MESSAGE_MAP( ) BOOL CMyFrameWnd::OnCreateClient( LPCREATESTRUCT pcs, CCreateContext* pContext ){ //创建两个视图窗口 split.CreateStatic( this, 1, 2 );//创建倒日型框架 split.CreateView( 0, 0, RUNTIME_CLASS(CMyView), CSize(100,100), pContext ); split.CreateView( 0, 1, pContext->m_pNewViewClass, CSize(100,100), pContext ); return TRUE; } void CMyFrameWnd::OnPaint( ){ PAINTSTRUCT ps = { 0 }; HDC hdc = ::BeginPaint( this->m_hWnd, &ps ); ::TextOut( hdc, 200, 200, "我是框架窗口客户区", strlen("我是框架窗口客户区")); ::EndPaint( this->m_hWnd, &ps ); } int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){ 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;
命令消息处理顺序:
代码:
//WM_COMMAND消息的路线 OnCommand(wParam, lParam)//函数内部this为pFrame { CWnd::OnCommand(..)//函数内部this为pFrame { OnCmdMsg(...)//函数内部this为pFrame *****CFrameWnd::OnCmdMsg 起点 { CView* pView = GetActiveView()//函数内部this为pFrame { return this->m_pViewActive;//活动视图窗口对象地址 }对象 pView->OnCmdMsg(..) ===>终点 CCmdTarget::OnCmdMsg 此函数内部this为pView m_pDocument->OnCmdMsg(.)==>终点CCmdTarget::OnCmdMsg 此函数内部this为文档类对象 CWnd::OnCmdMsg(..)==>终点 CCmdTarget::OnCmdMsg 此函数内部this为pFrame CWinApp* pApp = AfxGetApp();//获取&theApp pApp->OnCmdMsg(..)==>终点 CCmdTarget::OnCmdMsg 此函数内部this为&theApp } } }
文档类和视图类关系:
代码:
#include <afxwin.h> #include <afxext.h> #include "resource.h" class CMyDoc : public CDocument{ DECLARE_MESSAGE_MAP( ) public: afx_msg void OnNew( ); CString str; }; BEGIN_MESSAGE_MAP( CMyDoc, CDocument ) ON_COMMAND( ID_NEW, OnNew ) END_MESSAGE_MAP( ) void CMyDoc::OnNew( ){ this->str = "hello world"; //接受到的数据。 // this->UpdateAllViews( NULL );//刷新和这个文档类对象(this)关联的所有视图窗口 //this->m_viewList; POSITION pos = this->GetFirstViewPosition(); //GetFirstXXXPosition CView* pView = this->GetNextView(pos); //GetNextXXX 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_COMMAND( ID_NEW, OnNew ) ON_WM_CREATE( ) END_MESSAGE_MAP() void CMyView::OnNew( ){ AfxMessageBox( "视图类处理的WM_COMMAND消息" ); } int CMyView::OnCreate( LPCREATESTRUCT pcs ){ return CView::OnCreate( pcs ); //将文档类对象和视图类对象建立关联关系。 } void CMyView::OnDraw( CDC* pDC ){ // CMyDoc* pDoc = (CMyDoc*)this->m_pDocument; CMyDoc* pDoc = (CMyDoc*)this->GetDocument( ); pDC->TextOut( 100, 100, pDoc->str ); } class CMyFrameWnd : public CFrameWnd{ DECLARE_MESSAGE_MAP( ) public: afx_msg int OnCreate( LPCREATESTRUCT pcs ); afx_msg void OnPaint( ); virtual BOOL OnCreateClient( LPCREATESTRUCT pcs, CCreateContext* pContext); CSplitterWnd split;//不规则框架窗口 afx_msg void OnNew( ); }; BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd ) // ON_COMMAND( ID_NEW, OnNew) ON_WM_PAINT( ) ON_WM_CREATE( ) END_MESSAGE_MAP( ) void CMyFrameWnd::OnNew( ){ AfxMessageBox( "框架类处理了新建被点击" ); } BOOL CMyFrameWnd::OnCreateClient( LPCREATESTRUCT pcs, CCreateContext* pContext ){ //创建两个视图窗口 split.CreateStatic( this, 1, 2 ); split.CreateView( 0, 0, RUNTIME_CLASS(CMyView), CSize(100,100), pContext ); split.CreateView( 0, 1, pContext->m_pNewViewClass, CSize(100,100), pContext ); m_pViewActive = (CView*)split.GetPane(0,0); return TRUE; } void CMyFrameWnd::OnPaint( ){ PAINTSTRUCT ps = { 0 }; HDC hdc = ::BeginPaint( this->m_hWnd, &ps ); ::TextOut( hdc, 200, 200, "我是框架窗口客户区", strlen("我是框架窗口客户区")); ::EndPaint( this->m_hWnd, &ps ); } int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){ return CFrameWnd::OnCreate( pcs );//动态创建视图类对象,并创建视图窗口 } class CMyWinApp : public CWinApp{ DECLARE_MESSAGE_MAP( ) public: virtual BOOL InitInstance( ); afx_msg void OnNew( ); }; BEGIN_MESSAGE_MAP( CMyWinApp, CWinApp ) // ON_COMMAND( ID_NEW, OnNew ) END_MESSAGE_MAP( ) void CMyWinApp::OnNew( ){ AfxMessageBox( "应用程序类处理了WM_COMMAND消息" ); } 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;
六.MFC架构程序
单文档视图架构:
单文档视图架构特点:
只能管理一个文档(只有一个文档类对象)
单文档视图架构使用:
实现:
#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, "我是视图窗口" ); } 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;
执行过程:
伪代码:
OnFileNew( )//函数内部this为&theApp { m_pDocManager->OnFileNew()//函数内部this为文档管理类对象地址 { CDocTemplate* pTemplate = m_templateList.GetHead();//取出单文档模板类对象地址 pTemplate->OpenDocumentFile()//函数内部this为单文档模板类对象地址 { OpenDocumentFile(..)//函数内部this为单文档模板类对象地址 { pDocument = CreateNewDocument()//函数内部this为单文档模板类对象地址 { CDocument* pDocument = m_pDocClass->CreateObject(); //动态创建文档类对象,并返回对象地址 AddDocument(pDocument)//函数内部this为单文档模板类对象地址 { m_pOnlyDoc = pDocument; } } pFrame = CreateNewFrame(pDocument..)//函数内部this为单文档模板类对象地址 { CCreateContext context; ... context.m_pCurrentDoc = pDocument;//文档类对象地址 context.m_pNewViewClass = m_pViewClass;//RUNTIME_CLASS(CMyView) CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject(); //动态创建框架类对象,并返回对象地址 pFrame->LoadFrame(...., &context);//创建框架窗口 //后续过程看前一天的伪代码 } } } } }
关于类向导的使用:
类向导可以帮助我们在已有的框架创建基础上再进一步帮我们生成代码。
选择: 位置 ->类向导
再这个里面可以选择要添加的项目,添加到的文件,添加的内容,框架会帮我们生成规范化的内容,我们只需要实现具体细节。
多文档视图架构:
特点:
可以管理多个文档 (可以有多个文档类对象)
多文档视图架构使用:
执行过程:
代码:
#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, "我是视图窗口" ); } class CMyChild : public CMDIChildWnd{ DECLARE_DYNCREATE( CMyChild ) }; IMPLEMENT_DYNCREATE( CMyChild, CMDIChildWnd ) class CMyFrameWnd : public CMDIFrameWnd{ //自己造主框架窗口类的对象 }; class CMyWinApp : public CWinApp{//自己造应用程序类的对象 public: virtual BOOL InitInstance( ); }; BOOL CMyWinApp::InitInstance( ){ CMyFrameWnd* pFrame = new CMyFrameWnd; pFrame->LoadFrame( IDR_MENU1 ); m_pMainWnd = pFrame; pFrame->ShowWindow( SW_SHOW ); pFrame->UpdateWindow( ); CMultiDocTemplate* pTemplate = new CMultiDocTemplate( IDR_MENU2, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMyChild), RUNTIME_CLASS(CMyView)); AddDocTemplate( pTemplate ); OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联 OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联 OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联 return TRUE; } CMyWinApp theApp;
MFC绘图:
绘图相关类:
伪代码:
绘图相关的 *********************************************** CPaintDC dc(pView) === CPaintDC::CPaintDC(...)//函数内部this为&dc { Attach(::BeginPaint(pView->m_hWnd, &m_ps))//函数内部this为&dc { m_hDC = hDC;//将BeginPaint获取的绘图设备句柄 保存到dc对象的一个成员变量中 SetAttribDC(m_hDC)//函数内部this为&dc { m_hAttribDC = m_hDC;//dc对象的另一个成员变量也保存了绘图设备句柄 } } } CPen pen(PS_SOLID, 2, RGB(255,0,0)) === CPen::CPen(PS_SOLID, 2, RGB(255,0,0)) //函数内部this &pen { Attach(::CreatePen(PS_SOLID, 2, RGB(255,0,0)))//函数内部this &pen { m_hObject = hObject;//将::CreatePen获取的画笔句柄,保存到pen对象的一个成员变量中 } }
view类:
// MFCDrawView.cpp : implementation of the CMFCDrawView class // #include "stdafx.h" // SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail // and search filter handlers and allows sharing of document code with that project. #ifndef SHARED_HANDLERS #include "MFCDraw.h" #endif #include "MFCDrawDoc.h" #include "MFCDrawView.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFCDrawView IMPLEMENT_DYNCREATE(CMFCDrawView, CView) BEGIN_MESSAGE_MAP(CMFCDrawView, CView) // Standard printing commands ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview) ON_WM_PAINT() ON_COMMAND(ID_CLIENT, &CMFCDrawView::OnClient) ON_COMMAND(ID_PEN, &CMFCDrawView::OnPen) ON_COMMAND(ID_BRUSH, &CMFCDrawView::OnBrush) ON_COMMAND(ID_FONT, &CMFCDrawView::OnFont) ON_COMMAND(ID_BMP, &CMFCDrawView::OnBmp) END_MESSAGE_MAP() // CMFCDrawView construction/destruction CMFCDrawView::CMFCDrawView() { // TODO: add construction code here } CMFCDrawView::~CMFCDrawView() { } BOOL CMFCDrawView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs); } // CMFCDrawView drawing void CMFCDrawView::OnDraw(CDC* /*pDC*/) { CMFCDrawDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: add draw code for native data here } // CMFCDrawView printing BOOL CMFCDrawView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CMFCDrawView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CMFCDrawView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } // CMFCDrawView diagnostics #ifdef _DEBUG void CMFCDrawView::AssertValid() const { CView::AssertValid(); } void CMFCDrawView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMFCDrawDoc* CMFCDrawView::GetDocument() const // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCDrawDoc))); return (CMFCDrawDoc*)m_pDocument; } #endif //_DEBUG // CMFCDrawView message handlers void CMFCDrawView::OnPaint() { CPaintDC dc(this); //::BeginPaint // dc.Rectangle( 100, 100, 300, 300 );//::Rectangle(...) // ::Rectangle( dc.m_hDC, 100, 100, 300, 300 ); } void CMFCDrawView::OnClient() { CClientDC dc(this); dc.Ellipse( 300, 300, 500, 500 ); } void CMFCDrawView::OnPen() { CClientDC dc( this ); CPen pen(PS_SOLID, 2, RGB(255,0,0)); // CPen* oldpen = dc.SelectObject( &pen ); HGDIOBJ nOldPen = ::SelectObject( dc.m_hDC, pen.m_hObject ); // dc.Rectangle( 100, 100, 300, 300 ); ::Rectangle( dc.m_hDC, 100, 100, 300, 300 ); // dc.SelectObject( oldpen ); ::SelectObject( dc.m_hDC, nOldPen ); // pen.DeleteObject( ); ::DeleteObject( pen.m_hObject ); } void CMFCDrawView::OnBrush() { CClientDC dc(this); CBrush brush(RGB(0,255,0)); CBrush* oldbrush = dc.SelectObject( &brush ); dc.Rectangle( 100, 100, 300, 300 ); dc.SelectObject( oldbrush ); brush.DeleteObject( ); } void CMFCDrawView::OnFont() { CClientDC dc( this ); CFont font; font.CreatePointFont(300, "黑体");//::CreateFont(..............) CFont* oldfont = dc.SelectObject( &font ); dc.TextOut( 100, 100, "hello"); dc.SelectObject( oldfont ); font.DeleteObject(); } void CMFCDrawView::OnBmp() { //添加位图资源(操作资源无需写代码) //创建一个和当前DC,相匹配的内存DC CClientDC dc( this ); CDC memdc; memdc.CreateCompatibleDC( &dc ); //::CreateCompatibleDC //将位图的数据送给内存DC CBitmap bmp; bmp.LoadBitmap( IDB_BITMAP1 ); //::LoadBitmap CBitmap* oldbmp = memdc.SelectObject( &bmp );//::SelectObject //成像 dc.BitBlt( 100, 100, 48, 48, &memdc, 0, 0, SRCCOPY );//::BitBlt //将位图数据要回来 memdc.SelectObject( oldbmp );//::SelectObject //销毁位图 bmp.DeleteObject( );//::DeleteObject //销毁内存DC memdc.DeleteDC( );//::DeleteDC }
七、序列化机制:
文件序列化与反序列化:
文件操作相关类:
代码 :
#include <afxwin.h> #include <iostream> using namespace std; void File( ){ CFile file; file.Open( "E:/MFC/Day07/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; }
序列化机制使用:
反序列化机制使用:
代码:
#include <afxwin.h> #include <iostream> using namespace std; void Store( ){//序列化(存储、写)数据 CFile file; file.Open( "E:/MFC/Day07/serial.txt", CFile::modeCreate | CFile::modeWrite ); CArchive ar(&file, CArchive::store, 4096);//归档类对象,维护缓冲区。 long age = 18; ar << age;//将18保存当前指向的位置,并向后移动当前指向,相应字节数。 float score = 88.5; ar << score;//将88.5保存当前指向的位置,并向后移动当前指向,相应字节数。 CString name = "zhangsan"; ar << name; ar.Close( ); file.Close( ); } void Load( ){//反序列化(加载/读) CFile file; file.Open( "E:/MFC/day07/serial.txt", CFile::modeRead ); CArchive ar( &file, CArchive::load, 4096 );//维护一个buff,大小4096字节 long age; ar >> age;//当反序列化第一个数据时候,内部将文件中所有数据读入ar维护的buff中 float score; ar >> score;//当反序列化后续数据时候,不需要到硬盘文件中读取,直接到ar维护的buff中读取 CString name; ar >> name;//当反序列化后续数据时候,不需要到硬盘文件中读取,直接到ar维护的buff中读取 ar.Close( ); file.Close( ); cout << age << ' ' << score << ' ' << name << endl; } int main(){ Store( ); Load( ); return 0; }
执行过程:
序列化过程:
伪代码:
class CArchive{ enum Mode { store = 0, load = 1…}; BOOL m_nMode; //访问方式 int m_nBufSize; //buff的大小 CFile* m_pFile; //操作的文件对象 BYTE* m_lpBufCur; //当前指向 BYTE* m_lpBufMax; //终止指向 BYTE* m_lpBufStart; //开始指向 …. } CFile file; file.Open( "E:/MFC/Day07/serial.txt", CFile::modeCreate | CFile::modeWrite ); CArchive ar(&file, CArchive::store, 4096) === CArchive::CArchive(&file,0, 4096) { m_nMode = CArchive::store; // 0 m_pFile = &file;//“E:/....serial.txt” m_nBufSize = 4096; m_lpBufStart = new BYTE[m_nBufSize]; m_lpBufMax = m_lpBufStart + 4096; m_lpBufCur = m_lpBufStart; } long age = 18; ar << age === CArchive::operator<<(age)//函数内部this为&ar { if (m_lpBufCur + sizeof(LONG) > m_lpBufMax) { Flush(); } *m_lpBufCur = age; m_lpBufCur += sizeof(LONG); } float score = 88.5; ar << score === CArchive::operator<<(score)//函数内部this为&ar { if (m_lpBufCur + sizeof(float) > m_lpBufMax) { Flush(); } *m_lpBufCur = score;//88.5 m_lpBufCur += sizeof(float); } CString name = "zhangsan"; ar << name === CArchive::operator<<(name)//函数内部this为&ar { AfxWriteStringLength(ar, 8 ) { ar<<(unsigned char)nLength;//8 } Write(name, 8)//函数内部this为&ar { memcpy_s(m_lpBufCur, (size_t)(m_lpBufMax - m_lpBufCur), name, 8); m_lpBufCur += 8; } } ar.Close( )//函数内部this为&ar { Flush()//函数内部this为&ar { &file->Write(m_lpBufStart, ULONG(m_lpBufCur - m_lpBufStart)); m_lpBufCur = m_lpBufStart;//重置当前指向 } } m_lpBufCur 18 88.5 8 zhangsan| |--------------------------------------------------------------------| | | m_lpBufStart m_lpBufMax
反序列化:
序列化类对象:
就是序列化类对象的各个成员变量
序列化类对象的使用:
伪代码:
CFile file; file.Open("E:/MFC/Day08/serial.txt", CFile::modeCreate|CFile::modeWrite); CArchive ar(&file, CArchive::store, 4096);//归档类对象,维护缓冲区。 CMyDoc data(18, 88.5, "zhangsan"); ar << &data === operator<<(ar, const &data) { ar.WriteObject(&data)//函数内部this为&ar { CRuntimeClass* pClassRef = &data->GetRuntimeClass();//文档类静态变量 WriteClass(pClassRef);//将类的相关信息(类名/类大小/类版本)存入ar维护的buff中 (&data)->Serialize(ar)//函数内部this为&data { ar << this->m_age << this->m_score << this->m_name; //序列化基本类型变量 } } } CFile file; file.Open( "E:/MFC/day08/serial.txt", CFile::modeRead ); CArchive ar( &file, CArchive::load, 4096 );//维护一个buff,大小4096字节 CMyDoc* pdata = NULL;//???????????? ar >> pdata === operator>>(ar, pdata) { pdata = ar.ReadObject(RUNTIME_CLASS(CMyDoc))//函数内部this为&ar { CRuntimeClass* pClassRef = ReadClass(RUNTIME_CLASS(CMyDoc),...); //从文件读取 类的相关信息,和 RUNTIME_CLASS(CMyDoc)中信息进行比对, //如果相同返回RUNTIME_CLASS(CMyDoc),如果不同返回NULL CObject*pOb = RUNTIME_CLASS(CMyDoc)->CreateObject(); //动态创建CMyDoc类的对象,并返回对象地址 pOb->Serialize(ar)//函数内部this为刚刚创建的CMyDoc类对象(pOb) { ar >> m_age >> m_score >> m_name;//反序列化基本类型变量 } return pOb; } }
代码:
#include <afxwin.h> #include <iostream> using namespace std; class CMyDoc : public CDocument{ // DECLARE_SERIAL( CMyDoc ) _DECLARE_DYNCREATE(CMyDoc) //动态创建机制的声明宏 AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, CMyDoc* &pOb);//操作符重载函数 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 ) /* 动态创建机制实现宏站出来的东西 CArchive& AFXAPI operator>>(CArchive& ar, CMyDoc* &pOb) { pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(CMyDoc)); return ar; } */ void CMyDoc::Serialize( CArchive& ar ){ if( ar.IsStoring() ){ ar << this->m_age << this->m_score << this->m_name; //序列化基本类型变量 }else{ ar >> m_age >> m_score >> m_name;//反序列化基本类型变量 } } void Store( ){//序列化(存储、写)数据 CFile file; file.Open("E:/MFC/Day08/serial.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( "E:/MFC/day08/serial.txt", CFile::modeRead ); CArchive ar( &file, CArchive::load, 4096 );//维护一个buff,大小4096字节 CMyDoc* pdata = NULL; ar >> pdata; ar.Close( ); file.Close( ); cout << pdata->m_age << ' ' << pdata->m_score << ' ' << pdata->m_name << endl; } int main(){ Store( ); Load( ); return 0; }
八.对话框机制
win32创建无模式对话框:
#include <windows.h> #include "resource.h" HINSTANCE g_hInstance = 0; INT CALLBACK DlgProc( HWND hwndlg, UINT msgID, WPARAM wParam, LPARAM lParam ){ switch( msgID ){ case WM_DESTROY: MessageBox( NULL, "我要死了", "Infor", MB_OK ); break; case WM_SYSCOMMAND: if( wParam == SC_CLOSE ){ HWND hWnd = GetParent( hwndlg ); EnableWindow( hWnd ,TRUE ); DestroyWindow( hwndlg );//销毁无模式对话框, 切忌不能EndDialog // EndDialog( hwndlg, 1001 );//只能隐藏无模式对话框, 可以销毁模式对话框 } break; } return FALSE;//对话框的消息交给真正对话框窗口处理函数处理。 } void OnNoModel( HWND hWnd ){ EnableWindow( hWnd, FALSE ); // HWND hDlg = CreateDialog( g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DlgProc );//直接创建 HRSRC hRs = FindResource( g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), RT_DIALOG ); HGLOBAL hGl = LoadResource( g_hInstance, hRs ); LPCDLGTEMPLATE pTemplate = (LPCDLGTEMPLATE)LockResource( hGl ); HWND hDlg = CreateDialogIndirect( g_hInstance, pTemplate, hWnd, DlgProc ); ShowWindow( hDlg, SW_SHOW ); } void OnCommand( HWND hWnd, WPARAM wParam ){ switch(LOWORD(wParam)){ case ID_NOMODEL: OnNoModel( hWnd ); break; } } //窗口处理函数( 自定义,处理消息) LRESULT CALLBACK WndProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam ){ switch(msgID){ case WM_COMMAND: OnCommand( hWnd, wParam ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; } return DefWindowProc( hWnd, msgID, wParam, lParam ); } //入口函数 int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow){ g_hInstance = hIns; //注册窗口类 WNDCLASS wc = { 0 }; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.hCursor = NULL; wc.hIcon = NULL; wc.hInstance = hIns; wc.lpfnWndProc = WndProc; wc.lpszClassName = "Main"; wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);//(CHAR*)IDR_MENU1; wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClass( &wc );//将以上所有赋值全部写入操作系统。 //在内存创建窗口 HWND hWnd = CreateWindowEx( 0, "Main", "window", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, NULL ); //显示窗口 ShowWindow( hWnd, SW_SHOW ); UpdateWindow( hWnd ); //消息循环 MSG nMsg = { 0 }; while( GetMessage(&nMsg,NULL,0,0) ){ TranslateMessage( &nMsg ); DispatchMessage( &nMsg );//将消息交给窗口处理函数来处理。 } return 0; }
MFC对话框:
分类:模式对话框(假)、无模式对话框
参与架构的类: CDialog、CWinApp
无模式对话框:
执行过程:
伪代码:
AFX_MODULE_STATE aaa;//当前程序模块状态信息 AFX_MODULE_THREAD_STATE bbb; //当前程序线程状态信息 CWinApp::CWinApp()//构造全局对象CMyWinApp theApp { AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); //获取全局变量&aaa AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; //获取全局变量&bbb pThreadState->m_pCurrentWinThread = this;//将&theApp保存到bbb的一个成员中 AfxGetThread() { AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb CWinThread* pThread = pState->m_pCurrentWinThread; return pThread;//返回的为&theApp } pModuleState->m_pCurrentWinApp = this;//将&theApp保存到aaa的一个成员中 AfxGetApp() { return AfxGetModuleState()->m_pCurrentWinApp;//返回&theApp } } 进入入口函数 WinMain(...) { AfxWinMain(..) { CWinThread* pThread = AfxGetThread(); CWinApp* pApp = AfxGetApp();//获取&theApp pApp->InitApplication();//利用theApp调用应用程序类的成员 虚函数(初始化) pThread->InitInstance()//利用theApp调用应用程序类的成员 虚函数(创建并显示无模式对话框) { CMyDlg* pdlg = new CMyDlg; pdlg->Create( IDD_DIALOG1 )//函数内部this为pdlg(自己new的对话框类对象地址) { CDialog::Create(MAKEINTRESOURCE(IDD_DIALOG1), ..)//函数内部this为pdlg { HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG); HGLOBAL hTemplate = LoadResource(hInst, hResource); //以上两行代码,查找并加载对话框资源 CreateIndirect(MAKEINTRESOURCE(IDD_DIALOG1), ...) { LPCDLGTEMPLATE lpDialogTemplate = LockResource(hDialogTemplate); CreateIndirect(lpDialogTemplate..) { CreateDlgIndirect(...) { ::CreateDialogIndirect(...);//以间接方式创建无模式对话框 } } } } } } pThread->Run()//函数内部this为&theApp { CWinThread::Run()//函数内部this为&theApp { for (;;) { while(没有消息时) { OnIdle(..);//空闲处理(虚函数) } do { if(::GetMessage抓到WM_QUIT消息) return ExitInstance(..);//善后处理(虚函数) }while(...) } } } } } ****************************** 父类,处理点击OK按钮发出的WM_COMMAND消息 ****************************** CDialog::OnOK() { EndDialog(IDOK) { ::EndDialog(m_hWnd, nResult);//只能将无模式对话框隐藏 } }
代码:
#include <afxwin.h> #include "resource.h" class CMyDlg : public CDialog{ DECLARE_MESSAGE_MAP() public: void OnZjwOK(); void OnZjwCancel( ); }; BEGIN_MESSAGE_MAP(CMyDlg, CDialog) ON_COMMAND( IDOK, OnZjwOK ) ON_COMMAND( IDCANCEL, OnZjwCancel ) END_MESSAGE_MAP() void CMyDlg::OnZjwCancel( ){ // CDialog::OnCancel( ); this->DestroyWindow( ); } void CMyDlg::OnZjwOK(){ // CDialog::OnOK();//只能将无模式对话框隐藏,并没有销毁。 ::DestroyWindow( this->m_hWnd ); } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; BOOL CMyWinApp::InitInstance( ){ CMyDlg* pdlg = new CMyDlg; pdlg->Create( IDD_DIALOG1 ); m_pMainWnd = pdlg; pdlg->ShowWindow( SW_SHOW ); return TRUE; } CMyWinApp theApp;
模式对话框:
执行过程:
伪代码:
AFX_MODULE_STATE aaa;//当前程序模块状态信息 AFX_MODULE_THREAD_STATE bbb; //当前程序线程状态信息 CWinApp::CWinApp()//构造全局对象CMyWinApp theApp { AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); //获取全局变量&aaa AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; //获取全局变量&bbb pThreadState->m_pCurrentWinThread = this;//将&theApp保存到bbb的一个成员中 AfxGetThread() { AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb CWinThread* pThread = pState->m_pCurrentWinThread; return pThread;//返回的为&theApp } pModuleState->m_pCurrentWinApp = this;//将&theApp保存到aaa的一个成员中 AfxGetApp() { return AfxGetModuleState()->m_pCurrentWinApp;//返回&theApp } } 进入入口函数 WinMain(...) { AfxWinMain(..) { CWinThread* pThread = AfxGetThread(); CWinApp* pApp = AfxGetApp();//获取&theApp pApp->InitApplication();//利用theApp调用应用程序类的成员 虚函数(初始化) pThread->InitInstance() { CMyDlg dlg===CDialog(IDD)//函数内部this为&dlg { m_lpszTemplateName=MAKEINTRESOURCE(IDD)//将对话框资源ID保存dlg的一个成员中 } m_pMainWnd = &dlg; dlg.DoModal( )//函数内部this为&dlg { HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG); hDialogTemplate = LoadResource(hInst, hResource); lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate); //以上三行代码,查找加载并锁定对话框资源 HWND hWndParent = PreModal();//获取父窗口的句柄 ::EnableWindow(hWndParent, FALSE);//将父窗口设置为不可用状态 CreateDlgIndirect(...);//间接方式创建无模式对话框 RunModalLoop(...)//函数内部this为&dlg { for (;;) //消息循环 { while(没有消息){ 空闲处理 } do{ 消息循环的相关函数; if (!ContinueModal())//函数内部this为&dlg(m_nFlags(24/8) & 0x0010) goto ExitModal; }while(....); } ExitModal: return m_nModalResult; } } ::EnableWindow(hWndParent, TRUE);//将父窗口设置为可用 DestroyWindow();//销毁无模式对话框 return m_nModalResult;//????dlg的一个成员变量 } } } 01000 10000 -------- 00000 ****************************** 父类,处理点击OK按钮发出的WM_COMMAND消息 ****************************** CDialog::OnOK()//函数内部this为&dlg { EndDialog(IDOK) //参数为1 { EndModalLoop(IDOK)//函数内部this为&dlg { m_nModalResult = IDOK; // 1 m_nFlags = 8; } ::EndDialog(m_hWnd, nResult);//只能将无模式对话框隐藏 } } CDialog::OnCancel()//函数内部this为&dlg { EndDialog(IDCANCEL) //参数为2 { EndModalLoop(IDCANCEL)//函数内部this为&dlg { m_nModalResult = IDCANCEL; // 1 m_nFlags = 8; } ::EndDialog(m_hWnd, nResult);//只能将无模式对话框隐藏 } }
代码:
#include <afxwin.h> #include "resource.h" class CMyDlg : public CDialog{ public: DECLARE_MESSAGE_MAP( ) enum{IDD=IDD_DIALOG1}; public: afx_msg void OnOK(); CMyDlg() : CDialog(IDD){ } }; BEGIN_MESSAGE_MAP( CMyDlg, CDialog ) ON_COMMAND( IDOK, OnOK ) END_MESSAGE_MAP( ) void CMyDlg::OnOK( ){ CDialog::OnOK(); } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; BOOL CMyWinApp::InitInstance( ){ CMyDlg dlg;//栈空间 m_pMainWnd = &dlg; int nRet = dlg.DoModal( ); return FALSE;//不再执行MFC库中安排的Run函数 } CMyWinApp theApp;
九.MFC控件
对象和控件绑定:
绑定的作用:
与数据类型对象绑定:
与控件类型对象绑定:
控件消息处理:
代码:
#include <afxwin.h> #include "resource.h" class CMyDlg : public CDialog{ public: DECLARE_MESSAGE_MAP( ) enum{IDD=IDD_DIALOG1}; public: afx_msg void OnOK(); afx_msg void OnBtn1(); afx_msg void OnBtn2(); afx_msg void OnDblClk( ); CMyDlg() : CDialog(IDD){ } public: CString m_strEdit;//数据类型对象 CEdit m_ctrlEdit;//控件类型对象 virtual void DoDataExchange( CDataExchange* pDX ); }; BEGIN_MESSAGE_MAP( CMyDlg, CDialog ) ON_BN_CLICKED( IDC_BUTTON1, OnBtn1 ) ON_BN_CLICKED( IDC_BUTTON2, OnBtn2 ) /* { WM_COMMAND, (WORD)BN_CLICKED, (WORD)IDC_BUTTON2, (WORD)IDC_BUTTON2, AfxSigCmd_v, (static_cast< AFX_PMSG > (OnBtn1)) },*/ ON_BN_CLICKED( IDOK, OnOK) ON_BN_DOUBLECLICKED( IDC_BUTTON2, OnDblClk) /* { WM_COMMAND, (WORD)BN_DOUBLECLICKED, (WORD)IDC_BUTTON2, (WORD)IDC_BUTTON2, AfxSigCmd_v, (static_cast< AFX_PMSG > (OnDblClk)) },*/ END_MESSAGE_MAP( ) void CMyDlg::OnDblClk( ){ AfxMessageBox( "双击了按钮" ); } void CMyDlg::OnBtn1(){//控件--》数据对象 UpdateData( TRUE ); AfxMessageBox( m_strEdit ); } void CMyDlg::OnBtn2(){//数据对象--》控件 m_strEdit = "hello world"; UpdateData( FALSE ); } void CMyDlg::DoDataExchange( CDataExchange* pDX ){ DDX_Text( pDX, IDC_EDIT1, m_strEdit );//调用一系列DDX_xxx函数(类向导自动添加) DDX_Control( pDX, IDC_EDIT1, m_ctrlEdit ); } void CMyDlg::OnOK( ){ m_ctrlEdit.MoveWindow(0, 0, 200, 200); // CDialog::OnOK(); } class CMyWinApp : public CWinApp{ public: virtual BOOL InitInstance( ); }; BOOL CMyWinApp::InitInstance( ){ CMyDlg dlg;//栈空间 m_pMainWnd = &dlg; int nRet = dlg.DoModal( ); return FALSE;//不再执行MFC库中安排的Run函数 } CMyWinApp theApp;
基本控件:
控件介绍 :
下压式按钮:
编辑框:
复选框按钮:
单选框按钮:
分组框按钮:
文本静态框:
图像静态框:
代码:
// MFCCtrl2Dlg.cpp : implementation file // #include "stdafx.h" #include "MFCCtrl2.h" #include "MFCCtrl2Dlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFCCtrl2Dlg dialog CMFCCtrl2Dlg::CMFCCtrl2Dlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMFCCtrl2Dlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMFCCtrl2Dlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_CHECK1, m_check); DDX_Control(pDX, IDC_BUTTON1, m_btn); DDX_Control(pDX, IDC_RADIO1, m_r1); DDX_Control(pDX, IDC_RADIO2, m_r2); DDX_Control(pDX, IDC_GROUP, m_group); DDX_Control(pDX, IDC_ST, m_st); DDX_Control(pDX, IDC_PS, m_ps); } BEGIN_MESSAGE_MAP(CMFCCtrl2Dlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, &CMFCCtrl2Dlg::OnClickedButton1) ON_BN_CLICKED(IDC_CHECK1, &CMFCCtrl2Dlg::OnClickedCheck1) ON_BN_CLICKED(IDC_RADIO1, &CMFCCtrl2Dlg::OnClickedRadio1) ON_BN_CLICKED(IDC_RADIO2, &CMFCCtrl2Dlg::OnClickedRadio2) END_MESSAGE_MAP() // CMFCCtrl2Dlg message handlers BOOL CMFCCtrl2Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here m_check.SetCheck( TRUE ); m_r1.SetCheck( TRUE ); return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMFCCtrl2Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMFCCtrl2Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CMFCCtrl2Dlg::OnClickedButton1() { /* if( m_check.GetCheck() ) m_check.SetCheck( FALSE ); else m_check.SetCheck( TRUE );*/ m_check.SetCheck( !m_check.GetCheck() ); m_st.SetWindowText( "hello" ); m_ps.SetBitmap( ::LoadBitmap( AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP2))); } void CMFCCtrl2Dlg::OnClickedCheck1() { int nState = m_check.GetCheck( ); CString sState; sState.Format( "%d", nState ); m_btn.SetWindowText( sState ); } void CMFCCtrl2Dlg::OnClickedRadio1()//男 { m_r1.SetCheck( TRUE ); m_r2.SetCheck( FALSE ); } void CMFCCtrl2Dlg::OnClickedRadio2()//女 { m_r2.SetCheck( TRUE ); m_r1.SetCheck( FALSE ); }
组件效果:
注意:有的组件的默认id为IDC_STATIC,需要修改id,才能在类向导里面找到。
组合框:
分类:简单式组合框/下拉式组合框/下拉列表式组合框
如何选择:
列表框:
代码:
// MFCCtrl3Dlg.cpp : implementation file // #include "stdafx.h" #include "MFCCtrl3.h" #include "MFCCtrl3Dlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFCCtrl3Dlg dialog CMFCCtrl3Dlg::CMFCCtrl3Dlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMFCCtrl3Dlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMFCCtrl3Dlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_DROPDOWN, m_dropdown); DDX_Control(pDX, IDC_DROPLIST, m_droplist); DDX_Control(pDX, IDC_SIMPLE, m_simple); } BEGIN_MESSAGE_MAP(CMFCCtrl3Dlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_CLEAR, &CMFCCtrl3Dlg::OnBnClickedClear) ON_BN_CLICKED(IDC_DEL, &CMFCCtrl3Dlg::OnBnClickedDel) ON_BN_CLICKED(IDC_TEXT, &CMFCCtrl3Dlg::OnBnClickedText) ON_BN_CLICKED(IDC_DATA, &CMFCCtrl3Dlg::OnBnClickedData) ON_CBN_SELCHANGE(IDC_SIMPLE, &CMFCCtrl3Dlg::OnSelchangeSimple) ON_CBN_EDITCHANGE(IDC_SIMPLE, &CMFCCtrl3Dlg::OnEditchangeSimple) END_MESSAGE_MAP() // CMFCCtrl3Dlg message handlers BOOL CMFCCtrl3Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon for( int i=0; i<100; i++ ){ char szItem[256]; sprintf(szItem, "Item%d", i); m_simple.AddString( szItem );//追加选项 m_simple.SetItemData( i, 1000+i ); m_dropdown.AddString( szItem ); m_droplist.AddString( szItem ); } m_simple.SetCurSel( 99 ); m_dropdown.SetCurSel( 99 ); m_droplist.SetCurSel( 99 ); return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMFCCtrl3Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMFCCtrl3Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CMFCCtrl3Dlg::OnBnClickedClear() { // TODO: Add your control notification handler code here m_simple.ResetContent( ); m_dropdown.ResetContent( ); m_droplist.ResetContent( ); } void CMFCCtrl3Dlg::OnBnClickedDel() { m_simple.DeleteString( m_simple.GetCurSel() ); m_dropdown.DeleteString( m_dropdown.GetCurSel() ); m_droplist.DeleteString( m_droplist.GetCurSel() ); } void CMFCCtrl3Dlg::OnBnClickedText() { //获取选项的文本内容 CString str; m_simple.GetLBText( m_simple.GetCurSel(), str ); AfxMessageBox( str ); } void CMFCCtrl3Dlg::OnBnClickedData() { DWORD nData = m_simple.GetItemData( m_simple.GetCurSel() ); CString strData; strData.Format( "附加数据:%d", nData ); AfxMessageBox( strData ); } void CMFCCtrl3Dlg::OnSelchangeSimple() { int nSel = m_simple.GetCurSel(); m_dropdown.SetCurSel( nSel ); m_droplist.SetCurSel( nSel ); } void CMFCCtrl3Dlg::OnEditchangeSimple() { AfxMessageBox( "内容被修改" ); }
滑块控件:
代码:
// MFCCtrlDlg.cpp : implementation file // #include "stdafx.h" #include "MFCCtrl.h" #include "MFCCtrlDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFCCtrlDlg dialog CMFCCtrlDlg::CMFCCtrlDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMFCCtrlDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMFCCtrlDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_SLIDER1, m_slider); DDX_Control(pDX, IDC_PROGRESS1, m_pro); } BEGIN_MESSAGE_MAP(CMFCCtrlDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER1, &CMFCCtrlDlg::OnCustomdrawSlider1) END_MESSAGE_MAP() // CMFCCtrlDlg message handlers BOOL CMFCCtrlDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here m_slider.SetRange( 0, 100 ); m_slider.SetPos( 50 ); m_pro.SetRange( 0, 100 ); m_pro.SetPos( 50 ); return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMFCCtrlDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMFCCtrlDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CMFCCtrlDlg::OnCustomdrawSlider1(NMHDR *pNMHDR, LRESULT *pResult) { LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR); int nPos = m_slider.GetPos( ); CString strPos; strPos.Format( "滑块位置:%d", nPos ); this->SetWindowText( strPos ); m_pro.SetPos( nPos ); *pResult = 0; }
进度条控件:
文件搜索类:
代码:
#include "stdafx.h" #include "MFCFind.h" using namespace std; void Find( CString path ){ CString strPath = path; strPath += "/*.*"; CFileFind find;//文件搜索类对象 BOOL goFind = find.FindFile( strPath ); //开启查找 while( goFind ){ goFind = find.FindNextFile( );//找到当前文件,将文件信息保存find对象的成员变量中 CString filename = find.GetFileName( ); CString filepath = find.GetFilePath(); if( find.IsDirectory() && !find.IsDots() ){ cout << "[" << filename << "]" << endl; Find( filepath ); }else{ cout << filename << endl; } } find.Close( ); } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { Find( "c:" ); return 0; }
列表控件:
代码:
// MFCListDlg.cpp : implementation file // #include "stdafx.h" #include "MFCList.h" #include "MFCListDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CAboutDlg dialog used for App About class CAboutDlg : public CDialogEx { public: CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CMFCListDlg dialog CMFCListDlg::CMFCListDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMFCListDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMFCListDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO1, m_combox); DDX_Control(pDX, IDC_LIST1, m_list); } BEGIN_MESSAGE_MAP(CMFCListDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_CBN_SELCHANGE(IDC_COMBO1, &CMFCListDlg::OnSelchangeCombo1) ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CMFCListDlg::OnDblclkList1) END_MESSAGE_MAP() // CMFCListDlg message handlers BOOL CMFCListDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here m_combox.AddString( "图标" ); m_combox.AddString( "小图标" ); m_combox.AddString( "列表" ); m_combox.AddString( "报表" ); m_combox.SetCurSel( 0 ); m_list.InsertColumn( 0, "名称", LVCFMT_LEFT, 150 ); m_list.InsertColumn( 1, "修改日期", LVCFMT_LEFT, 150 ); m_list.InsertColumn( 2, "类型", LVCFMT_LEFT, 150 ); m_list.InsertColumn( 3, "大小", LVCFMT_LEFT, 150 ); m_list.SetExtendedStyle( LVS_EX_GRIDLINES );//经纬线 CImageList* pImgLst = new CImageList; pImgLst->Create( IDB_BITMAP1, 24, 1, RGB(255,255,255) ); m_list.SetImageList( pImgLst, LVSIL_NORMAL );//将图像链表应用在列表控件的图标风格中 m_list.SetImageList( pImgLst, LVSIL_SMALL );//将图像链表应用在列表控件的其他风格中 ShowFile("c:"); /*//测试数据 m_list.InsertItem( 0, "目录", 0 ); m_list.SetItemText( 0, 1, "2100.5.7" ); m_list.SetItemText( 0, 2, "Dir" ); m_list.SetItemText( 0, 3, "3M" ); m_list.InsertItem( 1, "文件", 1 ); m_list.SetItemText( 1, 1, "2100.12.17" ); m_list.SetItemText( 1, 2, "File" ); m_list.SetItemText( 1, 3, "13K" );*/ return TRUE; // return TRUE unless you set the focus to a control } void CMFCListDlg::ShowFile( CString path ){ m_list.DeleteAllItems( ); CString strPath = path; strPath += "/*.*"; CFileFind find;//文件搜索类对象 BOOL goFind = find.FindFile( strPath ); //开启查找 int i = 0; while( goFind ){ goFind = find.FindNextFile( );//找到当前文件,将文件信息保存find对象的成员变量中 CString filename = find.GetFileName( ); CString *filepath = new CString; *filepath = find.GetFilePath(); if( find.IsDirectory() ){ m_list.InsertItem( i, filename, 0 ); m_list.SetItemData( i, (DWORD)filepath); }else{ m_list.InsertItem( i, filename, 1 ); } i++; } find.Close( ); } void CMFCListDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMFCListDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMFCListDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CMFCListDlg::OnSelchangeCombo1() { switch( m_combox.GetCurSel() ){ case 0://图标 m_list.ModifyStyle( LVS_SMALLICON|LVS_LIST|LVS_REPORT, LVS_ICON ); break; case 1://小图标 m_list.ModifyStyle( LVS_ICON|LVS_LIST|LVS_REPORT, LVS_SMALLICON ); break; case 2://列表 m_list.ModifyStyle( LVS_ICON|LVS_SMALLICON|LVS_REPORT, LVS_LIST ); break; case 3://报表 m_list.ModifyStyle( LVS_ICON|LVS_LIST|LVS_SMALLICON, LVS_REPORT ); break; } } void CMFCListDlg::OnDblclkList1(NMHDR *pNMHDR, LRESULT *pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); *pResult = 0; DWORD nData = m_list.GetItemData( pNMItemActivate->iItem );//双击选项 CString* filepath = (CString*)nData; if( filepath != NULL ) ShowFile( *filepath ); }
树控件:
代码:
// MFCTreeDlg.cpp : implementation file // #include "stdafx.h" #include "MFCTree.h" #include "MFCTreeDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFCTreeDlg dialog CMFCTreeDlg::CMFCTreeDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMFCTreeDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMFCTreeDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_TREE1, m_tree); } BEGIN_MESSAGE_MAP(CMFCTreeDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_DEL, &CMFCTreeDlg::OnBnClickedDel) ON_BN_CLICKED(IDC_TEXT, &CMFCTreeDlg::OnBnClickedText) END_MESSAGE_MAP() // CMFCTreeDlg message handlers BOOL CMFCTreeDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here CImageList* pImgLst = new CImageList; pImgLst->Create( IDB_BITMAP1, 12, 1, RGB(255,255,255)); m_tree.SetImageList( pImgLst, LVSIL_NORMAL ); HTREEITEM nRoot = m_tree.InsertItem( "达内集团", 0, 1, NULL ); m_tree.InsertItem( "中关村中心", 2, 3, nRoot ); m_tree.InsertItem( "亚运村中心", 2, 3, nRoot ); m_tree.InsertItem( "天坛中心", 2, 3, nRoot ); m_tree.SetItemHeight( 50 ); return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMFCTreeDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMFCTreeDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CMFCTreeDlg::OnBnClickedDel() { m_tree.DeleteItem(m_tree.GetSelectedItem( )); } void CMFCTreeDlg::OnBnClickedText() { AfxMessageBox( m_tree.GetItemText( m_tree.GetSelectedItem() ) ); }