MFC 學習筆記

2022-11-06 21:01:17

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>
#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 );
}

樹控制元件:

image-20221106153824192

程式碼:


// 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() ) );
}