深入浅出MFC:动态创建控件
——-先以CButton為例講解MFC中動態創建控件——— 
 在對話框類中增加了以下3個成員變量: 
 CButton m_btn1; 
 CButton m_btn2; 
 CButton m_btn3;
在對話框的OnInitDialog函數中寫入了如下代碼動態創建控件
BOOL OnInitDialog {m_btn1.CreateEx(0, TEXT("BUTTON"), TEXT("Btn_1"), WS_CHILD | WS_VISIBLE, 10, 10, 100, 20,this->GetSafeHwnd(), (HMENU)IDC_BTN_DYN_BEG, 0);m_btn2.CreateEx(0, TEXT("BUTTON"), NULL, WS_CHILD | WS_VISIBLE, 10, 40, 100, 20,this->GetSafeHwnd(), (HMENU)IDC_BTN_DYN_BEG+1, 0);m_btn2.SetWindowText(TEXT("Btn_2"));m_btn3.Create(TEXT("Btn_3"), WS_CHILD | WS_VISIBLE, CRect(10, 70, 110, 90), this, IDC_BTN_DYN_BEG+4); }我們現在來研究一下代碼的本質: 
 m_btn1.CreateEx與m_btn2.CreateEx實際上調用的CWnd::CreateEx 
 m_btn3.Create調用了CButton::Create 
 先來瞧瞧CButton::Create,其中調用了CWnd::Create
CWnd::Create調用了CWnd::CreateEx
BOOL CWnd::Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName, DWORD dwStyle,const RECT& rect,CWnd* pParentWnd, UINT nID,CCreateContext* pContext) {return CreateEx(0, lpszClassName, lpszWindowName,dwStyle | WS_CHILD,rect.left, rect.top,rect.right - rect.left, rect.bottom - rect.top,pParentWnd->GetSafeHwnd(), (HMENU)(UINT_PTR)nID, (LPVOID)pContext); }研究CWnd::CreateEx才能看出本質
[wincore.cpp]
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,LPCTSTR lpszWindowName, DWORD dwStyle,int x, int y, int nWidth, int nHeight,HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam) {CREATESTRUCT cs;cs.dwExStyle = dwExStyle;cs.lpszClass = lpszClassName;cs.lpszName = lpszWindowName;cs.style = dwStyle;cs.x = x;cs.y = y;cs.cx = nWidth;cs.cy = nHeight;cs.hwndParent = hWndParent;cs.hMenu = nIDorHMenu;cs.hInstance = AfxGetInstanceHandle();cs.lpCreateParams = lpParam;if (!PreCreateWindow(cs)){PostNcDestroy();return FALSE;}AfxHookWindowCreate(this); //利用Hook進行了子類化HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass,cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);return TRUE; }[wincore.cpp]
void AFXAPI AfxHookWindowCreate(CWnd* pWnd) {pThreadState->m_pWndInit == pWnd;if (pThreadState->m_hHookOldCbtFilter == NULL){pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());}pThreadState->m_pWndInit = pWnd; }[wincore.cpp]
LRESULT CALLBACK _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam) {pWndInit->Attach(hWnd);pWndInit->PreSubclassWindow();WNDPROC *pOldWndProc = pWndInit->GetSuperWndProcAddr();WNDPROC afxWndProc = AfxGetAfxWndProc();//改寫了窗口過程函數為MFC通用的窗口過程函數也即子類化oldWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,(DWORD_PTR)afxWndProc); if (oldWndProc != afxWndProc)*pOldWndProc = oldWndProc;pThreadState->m_pWndInit = NULL; }所以動態創建控件全部都進行了子類化 
 以下列出了MFC中具體控件對應的窗口類名稱 
 (由于BUTTON按鈕對應了PUSHBUTTON&CHECKBOX&RADIOBOX等,按鈕樣式區分了創建按鈕的類型) 
 顯然: 
 Button———- CButton—— “BUTTON” — BS_PUSHBUTTON 
 Check Box——- CButton—— “BUTTON” — BS_AUTOCHECKBOX 
 Radio Button—- CButton—— “BUTTON” — BS_AUTORADIOBUTTON 
 Edit Control—- CEdit——– “EDIT” 
 Combo Box——- CComboBox—- “COMBOBOX” 
 List Box——– CListBox—– “SysListView32”
如果要動態創建Check Box,代碼如下
CButton m_btnChk; m_btnChk.CreateEx(0, TEXT("BUTTON"), NULL, WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 10, 160, 100, 20,this->GetSafeHwnd(), (HMENU)1250, 0);在CButton實例對象調用CreateEx時指定窗口類名為”EDIT”都可以,只不過創建的控件就是Edit Box了
m_btn1.CreateEx(0, TEXT("EDIT"), TEXT("Btn_1"), WS_CHILD | WS_VISIBLE, 10, 10, 100, 20,this->GetSafeHwnd(), (HMENU)IDC_BTN_DYN_BEG, 0);總結
以上是生活随笔為你收集整理的深入浅出MFC:动态创建控件的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 前端学习(2562):v-loading
 - 下一篇: 第14课:JSP动作 JSP param