1. 程式人生 > >C++MFC程式設計筆記day01 MFC介紹、建立MFC程式和重寫訊息處理

C++MFC程式設計筆記day01 MFC介紹、建立MFC程式和重寫訊息處理

一、MFC概念和作用

1、全稱Microsoft Foundation Class Library,我們稱為微軟基礎類庫,封閉了絕大部分的win32 Api函式,C++語法中的資料結構,程式的執行流程
MFC就是一個庫(動態庫,靜態庫)
MFC還是一個程式框架
2、為什麼使用MFC
基於框架程式設計,提高工作效率,減少開發週期,節約開發成本。
二、幾個重要的標頭檔案
afx.h    -絕大部分類的宣告標頭檔案
afxwin.h -包含了afx.h和windows.h
afxext.h -提供了擴充套件視窗類的支援(工具欄,狀態列等)
三、使用MFC
1、使用MFC庫做自己的控制檯程式
入口函式 _tmain()不同於以往的main()
CWinApp theApp;-全域性程式物件。
注意:
::函式名()-為win32的API函式。
以Afx開頭的函式,為MFC庫裡的全域性函式。
2、使用MFC庫做自己的庫程式(MFC AppWizard dll)
規則動態庫:可以被任何程式呼叫
擴充套件動態庫:只能被支援MFC的程式呼叫
3、MFC視窗程式
單文件檢視構架程式。
CFrameWnd-框架視窗類;
CWinApp-應用程式類,負責管理整個程式的執行流程;
CDocument-文件類,負責管理資料(資料的提取、轉換、儲存等操作);
CView-檢視視窗類,負責顯示資料
多文件檢視構架程式。
CMDIChildWnd-子框架視窗類,負責管理子框架視窗。
CMDIFrameWnd-主框架視窗類
CWinApp-應用程式類,負責管理整個程式的執行流程;
CDocument-文件類,負責管理資料(資料的提取、轉換、儲存等操作);
CView-檢視視窗類,負責顯示資料
對話方塊程式
CWinApp-應用程式類,負責管理整個程式的執行流程;
CDialog-對話方塊類
四、MFC類的介紹
CObject -mfc庫絕大部分類的基類,封裝了MFC庫中最基本的一些機制,執行時類資訊機制/動態建立機制/序列化機制.
CCmdTarget-訊息對映機制基類
CWinThread/CWinApp-應用程式類
CDocTemplate及其子類 -文件模版類
CDocument及其子類-文件類,封裝了對各種資料的操作。
Exceptions - 異常類,封裝了MFC中的各種異常情況。
CFile-文操作類
CWnd  -所有視窗類基類
FrameWindows  框架視窗類,封裝了對各種框架視窗的操作
ControlBars-各種工具欄類,封閉了對各種工具欄的操作
Dialog Boxes 對話方塊類。
Views 檢視視窗類
Controls 控制元件類
CDC/CGdiObject 封裝了繪圖操作
CArray/AList/CMap  對C++中的資料的封裝,以C開頭。


機制1:MFC入口函式機制

現在學習時,MFC都是建立Win32 Application程式,然後通過下列步驟改為MFC程式,只有一步步瞭解怎麼去手動建立MFC,以後通過MFC嚮導自動生成的大量MFC程式碼我們才能看得懂。
1、刪除主程式cpp中的入口函式
2、將stdafx.h中的windows.h改為afxwin.h
3、工程-設定 中選擇使用MFC庫
4、自定義框架類和程式類,繼承自MFC類,並重寫CWinApp的InitInstance方法:

class CMyFrameWnd:public CFrameWnd
{
};
class CMyWinApp:public CWinApp
{
public:
CMyWinApp();
virtual BOOL InitInstance();
};
CMyWinApp::CMyWinApp()
{
}
BOOL CMyWinApp::InitInstance()
{
CMyFrameWnd *pFrame=new CMyFrameWnd;
pFrame->Create(NULL,"MFC base");
m_pMainWnd=pFrame;
pFrame->ShowWindow(SW_SHOW);
pFrame->UpdateWindow();
return true;
}
5、建立一個程式類物件(觸發點):
CMyWinApp theApp;


AFX_MODULE_STATE* pModuleState = AfxGetModuleState();//獲取當前程式模組狀態資訊
AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;//獲取當前執行緒狀態資訊
pThreadState->m_pCurrentWinThread = this;//theapp全域性物件資訊賦值
pModuleState->m_pCurrentWinApp = this;
ASSERT(bool表示式);//如果表示式不成立,則彈出錯誤,不往下執行
全域性函式:AfxGetApp(),AfxGetThread() 獲取theApp地址
AfxMessageBox();//彈出訊息
vc6中,檢視-除錯視窗-call stack 可以看到被誰呼叫
可重寫(前加virtual):
BOOL CMyWinApp::InitApplication();
BOOL CMyWinApp::InitInstance()//初始化
int  CMyWinApp::Run()//執行
BOOL CMyWinApp::OnIdle(LONG lcount);//空閒時處理
int CMyWinApp::ExitInstance();

示例程式碼:

// MFCbase.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
class CMyFrameWnd:public CFrameWnd
{

};
class CMyWinApp:public CWinApp
{
public:

	CMyWinApp();
	virtual BOOL InitInstance();
	virtual int Run();
};
CMyWinApp::CMyWinApp()
{

}
BOOL CMyWinApp::InitInstance()
{
	CMyFrameWnd *pFrame=new CMyFrameWnd;
	pFrame->Create(NULL,"MFC base");
	m_pMainWnd=pFrame;
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return true;
}
int CMyWinApp::Run()
{
	AfxMessageBox("run");
	return CWinApp::Run();
}
CMyWinApp theApp;//建立一個程式物件


機制2:MFC視窗建立機制:

AfxGetInstanceHandle();//全域性控制代碼
1、載入選單
2、呼叫CreateEx 設計、註冊視窗類
PreCreateWindow():
WNDCLASS   wndcls;wndcls.lpfWinProc=DefWindowProc;
AfxRegisterWithIcon(),AfxRegisterClass()
::RegisterClass註冊一個區域性視窗類,類名“AfxFrameOrView42sd”,預設處理函式。
AfxHookWindowCreate(pFrame) 埋下勾子
CHandleMap* pMap = afxMapHWND(TRUE);
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//對映物件儲存到全域性變數
pState->m_pmapHWND = new CHandleMap(...);
pMap->SetPermanent(m_hWnd = hWndNew, this);
    //pFrame->m_hWnd 為視窗控制代碼。
CWnd* pWnd=CWnd::FromHandlePermanent(hWnd);
//pState->m_pmapHWND->LookupPermanent(HANDLE h)成員,可通過視窗控制代碼獲取pFrame
::CreateWindowEx函式,建立視窗
3、鉤子處理函式
將框架物件地址和視窗控制代碼建立一一對應關係。
利用::SetWindowLong,將視窗處理函式更改為AfxWndProc.


----------MSDN Library Visual Studio 6.0
//埋下勾子
HHOOK SetWindowsHookEx(
  int idHook,        // 勾子型別
  HOOKPROC lpfn,     // 處理函式(不同型別不同)
  HINSTANCE hMod,    // 程序控制代碼,NULL時不限制範圍
  DWORD dwThreadId   // 執行緒ID
);
//勾子型別為WH_CBT時的處理函式
LRESULT CALLBACK CBTProc(
  int nCode,      // hook code
  WPARAM wParam,  // 建立好的視窗控制代碼
  LPARAM lParam   // depends on hook code
);
//勾子處理函式修改預設處理函式
WNDPROC afxWndProc = AfxGetAfxWndProc();
oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,(DWORD)afxWndProc);
//修改視窗處理函式
LONG SetWindowLong(
  HWND hWnd,       // 視窗控制代碼
  int nIndex,      // 傳入:GWL_WNDPROC
  LONG dwNewLong   // 視窗處理函式地址
);
//全域性變數資訊
_AFX_THREAD_STATE* pThreadState=_afxThreadState.GetDate();
::GetCurrentThreadId();//獲取當前執行緒ID
pThreadState->m_pWndInit = pWnd;//賦值到全域性變數


::CreateWindowEx() //此函式處理完後直接進入勾子處理函式


重寫訊息處理函式
LRESULT CMyFrameWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
AfxMessageBox("WM_CREATE");
break;
}
return CFrameWnd::WindowProc(message,wParam,lParam);

}

示例:

// MFCcreate2.cpp : Defines the entry point for the application.
#include "stdafx.h"

class CMyFrameWnd:public CFrameWnd
{
public:
	virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
};
LRESULT CMyFrameWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	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(this->m_hWnd,&ps);
		}
		break;
	case WM_MOUSEMOVE:
		{
			//g_xpos=LOWORD(lParam);
			//g_ypos=HIWORD(lParam);
			::InvalidateRect(this->m_hWnd,NULL,true);
		}
		break;
	}
	return CFrameWnd::WindowProc(message,wParam,lParam);
}
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;
	//return CWinApp::InitInstance();
}
CMyWinApp theApp;