天天看點

CDialog輸入焦點

如果想自定義 CDialog的輸入焦點,一種辦法是可以通過VC自帶的資源編輯器,設定Tab Order來指定哪個控件是在Tab order的順序是第一。這種方法的好處是簡單友善,但是無法動态指定輸入焦點。

如果要根據一些運作時的情況來判斷輸入焦點,我們很容易想到調用空間的SetFocus函數,但是一般情況下這樣是不管用的,輸入焦點仍然是在Tab order排第一的那個控件上,為什麼?因為MFC在初始化對話框時,會調用OnInitDialog函數,大多數情況下我們自定義一個對話框,都會覆寫這個方法,如:

CDialog::OnInitDialog();

// todo: 插入你自己的初始化對話框的代碼

return TRUE;

注意最後一句:return TRUE

原因就在這一句上。我們看一下MFC的架構代碼:

LRESULT CDialog::HandleInitDialog(WPARAM, LPARAM)

{

PreInitDialog();

#ifndef _AFX_NO_OCC_SUPPORT

// create OLE controls

COccManager* pOccManager = afxOccManager;

if ((pOccManager != NULL) && (m_pOccDialogInfo != NULL))

{

BOOL bDlgInit;

if (m_lpDialogInit != NULL)

bDlgInit = pOccManager->CreateDlgControls(this, m_lpDialogInit,

m_pOccDialogInfo);

else

bDlgInit = pOccManager->CreateDlgControls(this, m_lpszTemplateName,

m_pOccDialogInfo);

if (!bDlgInit)

{

TRACE(traceAppMsg, 0, "Warning: CreateDlgControls failed during dialog init./n");

EndDialog(-1);

return FALSE;

}

}

#endif

// Default will call the dialog proc, and thus OnInitDialog

LRESULT bResult = Default();

#ifndef _AFX_NO_OCC_SUPPORT

if (bResult && (m_nFlags & WF_OLECTLCONTAINER))

{

CWnd* pWndNext = GetNextDlgTabItem(NULL);

if (pWndNext != NULL)

{

pWndNext->SetFocus(); // UI Activate OLE control

bResult = FALSE;

}

}

#endif

return bResult;

}

看最底下的代碼

LRESULT bResult = Default();

#ifndef _AFX_NO_OCC_SUPPORT

if (bResult && (m_nFlags & WF_OLECTLCONTAINER))

{

CWnd* pWndNext = GetNextDlgTabItem(NULL);

if (pWndNext != NULL)

{

pWndNext->SetFocus(); // UI Activate OLE control

bResult = FALSE;

}

}

#endif

在調用完初始化函數後,會判斷OnInitDialog的傳回值,如果傳回的是TRUE,會繼續調用設定輸入焦點的代碼,這個輸入焦點就是根據Tab order中指定的第一個輸入焦點的控件。

是以,要想在OnInitDialog中指定的輸入焦點生效,那麼我們就把OnInitDialog的傳回值設成FALSE就行了。