在Windows程序設計編程中,創建一個窗口要經歷下面四個過程 (如有不懂,請看博客 win32初窺)
1設計一個窗口類;2注冊窗口類;3創建窗口;4顯示及更新窗口。 同樣的,WinMain也是入口函數,具體的過程,請看孫鑫視頻20講之第三講其中CMainFrame表示一個窗口(主窗體,包括標題欄,菜單...),XXApp表示運用程序,XXDOC表示文檔類(加載數據,實現數據的存儲與操作分離),XXView也表示一個窗口(相當于Windows的客戶區)
下面看看MFC中類的主要繼承關系:
由于繼承樹太大,這里只羅列了CWnd的繼承關系
API中CreateWindowEx和CreateWindow幾乎是一樣的,Ex表示擴展,多了一個參數
下面用API模擬CWnd
just模擬
[html] view plain copy//下面是模仿封裝API函數 class CWnd { public: BOOL CreateEX( DWord dwExStyle, // extended window style LPCTSTR lpClassName, // registered class name LPCTSTR lpWindowName, // window name DWORD dwStyle, // window style int x, // horizontal position of window int y, // vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window HMENU hMenu, // menu handle or child identifier HINSTANCE hInstance, // handle to application instance LPVOID lpParam // window-creation data ); BOOL ShowWindow(int nCmdShow); BOOL UpdateWindow(); public: HWND m_hWnd; }; BOOL CWnd::CreateEx( DWORD dwExStyle, // extended window style LPCTSTR lpClassName, // registered class name LPCTSTR lpWindowName, // window name DWORD dwStyle, // window style int x, // horizontal position of window int y, // vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window HMENU hMenu, // menu handle or child identifier HINSTANCE hInstance, // handle to application instance LPVOID lpParam // window-creation data ); { m_hWnd=::CreateWindowEx(dwExstyle,lClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent, hMenu,hInstance,lParam); if(m_hWnd!=NULL) return TRUE; else return FALSE; } BOOL CWnd::ShowWindow(int nCmdShow) { return ::ShowWindow(m_hWnd,nCmdShow);//調用的是SDK全局函數,加個::說明是全局的 } BOOL CWnd::UpdateWindow() { return ::UpdateWindow(m_hWnd); } int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPRevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state ) { WNDCLASS wndclass; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); wndclass.hIcon=LoadIcon(NULL,IDI_ERROR); wndclass.hInstance=hInstance; ... CWnd cwnd; cwnd.CreateEx(dwExstyle,...,...); cwnd.ShowWindow(nCmdShow); cwnd.UpdateWindow(); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } ... }
下面是重頭戲(引用了某位仁兄的,太詳細了)
重點:MFC運行機制 提示:對于不想理解內部運行過程的,可以不看這一章,可以看了后面的界面設計再回頭來看這一章,可能感覺更深刻?! ∵@一次課和上一次的課的重點就是MFC的窗口類創建過程,而要反復說明的就是:MFC的程序和C語言的程序,從執行原理上說,是完全一致的?! ∽プ∵@一點,那么對于理解MFC程序的運行機制也就相對于簡單了?! 中的main函數就相當于MFC中的WinMain函數?! 「信d趣的可以利用VC的斷點設置自己跟蹤下面講述的各個函數,就明白它的執行順序了?! ∫?、C語言程序執行步驟 在C語言中,大約的步驟如下: 1, 全局變量內存分配 2, 進入main函數 二、MFC程序的運行步驟(主要是初始化) 打開一個MFC APPWizard(exe)工程,跟蹤其執行步驟,可以發現,是以下順序: 1) CXXApp中的全局變量定義 CXXApp theApp; 2) 調用CXXApp構造函數 CXXApp ::CXXApp(){} 3) 進入Winmain函數(_tWinMain為宏,值為WinMain) _tWinMain(){} 4) 完成初始化工作:包括窗口類注冊、窗口產生、顯示和更新 pThread->InitInstance() 對于MFC程序,MainFrame,View,ToolBar,Controlbar等都是窗口,所以下面的窗口注冊與創建、顯示等要反復調用多次,一次對應一個窗口 ?。?) 注冊窗口類 AfxEndDeferRegisterClass (2) 創建窗口 CMainFrame::PreCreateWindow()//反復調用一次是給我們修改窗口屬性的機會 CFrameWnd::Create() ?。?) 消息循環 PumpMessage() 補充1: 在MFC中,由于涉及到(窗口)類定義,所以定義全局變量的時候,需要進行更多的步驟?! ∪肿兞可婕暗筋惗x(類似于C中的類型定義)的話,那么需要遵循以下步驟(以MFC的窗口類為例) 1) 設計一個窗口類 2) 注冊窗口類 3) 創建窗口 4) 顯示及更新窗口 5) 消息循環 補充2:其他需要注意的幾點 1, 每一個MFC程序,有且只有一個從WinApp類派生的類(應用程序類),也只有一個從應用程序類所事例化的對象,表示應用程序本身。在WIN32程序當中,表示應用程序是通過WINMAIN入口函數來表示的(通過一個應用程序的一個事例號這一個標識來表示的)。在基于MFC應用程序中,是通過產生一個應用程序對象,用它來唯一的表示了應用程序。 2, _tWinMain函數中通過調用AfxWinMain()函數來完成它要完成的功能。(Afx*前綴代表這是應用程序框架函數,是一些全局函數,應用程序框架是一套輔助生成應用程序的框架模型,把一些類做一些有機的集成,我們可根據這些類函數來設計自己的應用程序)?! ?, 設計窗口類:在MFC中事先設計好了幾種缺省的窗口類,根據不同的應用程序的選擇,調用AfxEndDeferRegisterClass()函數注冊所選擇的窗口類?! ?, PreCreateWindow()是個虛函數,如果子類有則調用子類的?! ?, CreateWindowEx()函數參數與CREATESTRUCT結構體成員完全一致,CreateWindowEx()函數與CREATESTRUCT結構體參數的對應關系,使我們在創建窗口之前通過可PreCreateWindow(cs)修改cs結構體成員來修改所要的窗口外觀。 6,注意兩個函數?! ?:TranslateMessage(&m_msgCur)函數進行消息(如鍵盤消息)轉換 ::DispatchMessage(&m_msgCur)函數分派消息到窗口的回調函數處理(實際上分派的消息經過消息映射,交由消息響應函數進行處理。) 7,可以認為View類窗口是CMainFram類窗口的子窗口。DOCument類是文檔類。DOC-VIEW結構將數據本身與它的顯示分離開?! ∥臋n類用于數據的存儲,加載;視類用于數據的顯示,修改 8,CTEApp::InitInstance()函數中通過文檔模板將文檔類,視類,框架類的有機組織一起。語句如下: CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CTEDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CTEView)); AddDocTemplate(pDocTemplate);//增加到模板 補充3:本課涉及到MFC函數的源文件位置 根目錄 找到您安裝VC98下MFC的位置,比如我的機子上為:D:/Program Files/Microsoft Visual Studio/VC98/MFC。下面提供的就是相對路徑了?! ?nbsp; CWinApp構造函數: MFC=>SRC=>APPCORE.CPP AfxWinMain:MFC=>SRC=>WINMAIN.CPP AfxEndDeferRegisterClass: MFC=>SRC=>APPCORE.CPP CFrameWnd::PreCreateWindow()函數所在文件:MFC=>SRC=>WINFRM.CPP CFrameWnd::Create()函數路徑:MFC=>SRC=>WINFRM.CPP CWnd::CreateEx()函數路徑:MFC=>SRC=>WINCORE.CPP CWinThread::Run()方法路徑:MFC=>SRC=>THRDCORE.CPP 創建按鈕
1在CMainFrame創建
雙擊CMainFrame,添加數據成員,CButton m_btn
在OnCreate方法添加如下代碼:
[html] view plain copym_btn.Create(TEXT("first Button"),BS_PUSHBUTTON|WS_CHILD,CRect(0,0,100,100),this,123); m_btn.ShowWindow(SW_NORMAL);
2在CXXView創建
雙擊CXXView,添加數據成員,CButton m_btn
在CXXView右鍵Add windows Message Handler 添加WM_CREATE消息處理,然后生成OnCreate函數
在OnCreate函數添加如下代碼
[html] view plain copym_btn.Create(TEXT("Button2"),BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE,CRect(0,0,100,100),this,123);兩個代碼效果是等價的:
新聞熱點
疑難解答