深入浅出MFC:动态创建控件
——-先以CButton為例講解MFC中動(dòng)態(tài)創(chuàng)建控件———
在對(duì)話框類中增加了以下3個(gè)成員變量:
CButton m_btn1;
CButton m_btn2;
CButton m_btn3;
在對(duì)話框的OnInitDialog函數(shù)中寫入了如下代碼動(dòng)態(tài)創(chuàng)建控件
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); }我們現(xiàn)在來研究一下代碼的本質(zhì):
m_btn1.CreateEx與m_btn2.CreateEx實(shí)際上調(diào)用的CWnd::CreateEx
m_btn3.Create調(diào)用了CButton::Create
先來瞧瞧CButton::Create,其中調(diào)用了CWnd::Create
CWnd::Create調(diào)用了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才能看出本質(zhì)
[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進(jìn)行了子類化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();//改寫了窗口過程函數(shù)為MFC通用的窗口過程函數(shù)也即子類化oldWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,(DWORD_PTR)afxWndProc); if (oldWndProc != afxWndProc)*pOldWndProc = oldWndProc;pThreadState->m_pWndInit = NULL; }所以動(dòng)態(tài)創(chuàng)建控件全部都進(jìn)行了子類化
以下列出了MFC中具體控件對(duì)應(yīng)的窗口類名稱
(由于BUTTON按鈕對(duì)應(yīng)了PUSHBUTTON&CHECKBOX&RADIOBOX等,按鈕樣式區(qū)分了創(chuàng)建按鈕的類型)
顯然:
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”
如果要?jiǎng)討B(tài)創(chuàng)建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實(shí)例對(duì)象調(diào)用CreateEx時(shí)指定窗口類名為”EDIT”都可以,只不過創(chuàng)建的控件就是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);總結(jié)
以上是生活随笔為你收集整理的深入浅出MFC:动态创建控件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(2562):v-loading
- 下一篇: 组合逻辑电路的分析与设计