天天看点

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就行了。