如果想自定義 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就行了。