0

我制作了一个行为异常的 Visual Studio 2012 (Professional) 项目。当我只有一个对话框时,当我使用它们时,控件上不会出现焦点矩形(虚线边框),除非在我第一次按 TAB 或 ALT 之后。当我尝试在主对话框(作为启动屏幕)之前加载另一个对话框时,焦点虚线边框确实出现在主(第二个)对话框上,当窗口加载时它们已经显示在第一个项目上。为什么会这样,我该如何防止这种情况发生?

在此处输入图像描述

我唯一的猜测是按 ENTER 或 ESC 会导致与按 TAB 或 ALT 相同的行为,我总是看到效果,因为用户必须按 ENTER 或 ESC 才能关闭启动屏幕。有人会认为有一种方法可以从控件中移除焦点,但这似乎并不容易。我可以轻松地将焦点设置为控件,但通常不只是将其删除。

对于那些对示例代码感兴趣的人:


我可以展示我整个项目的代码,但诚实地自己测试会更容易。创建一个新的 VC++ 项目 > MFC 应用程序,设置为“基于对话框”,完成。在资源视图中,右键单击对话框和“插入对话框”。使其与主窗口明显不同,并添加至少一个可以获取焦点的控件。最后,在您的主 .cpp 文件的顶部附近,您会发现文本“// The one and only”...在其下方是声明主应用程序对象的行。在该行下方创建一个新的对话框类(对于“启动屏幕”,您可以在下面看到我的*),然后在您的主应用程序中InitInstance(),插入代码以在看起来像这样的部分上方加载启动屏幕:

CDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();

我用来显示启动画面的代码是:

CSplashDlg dlgSplash;
dlgSplash.DoModal();

*我的启动对话框代码:

更新:我更改了我的代码以允许首先单击对话框而不是按回车键(事实上,我将在某些时候覆盖 pretranslatemsg() 并捕获 ESC 和 ENTER。这是我最新的代码:

class CSplashDlg : public CDialogEx
{
public:
    CSplashDlg();
    enum { IDD = IDD_SPLASH };

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
};

CSplashDlg::CSplashDlg() : CDialogEx(CSplashDlg::IDD) {}

void CSplashDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); }

BEGIN_MESSAGE_MAP(CSplashDlg, CDialogEx)
    ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

void CSplashDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
    EndDialog(1);
    CDialogEx::OnLButtonUp(nFlags, point);
}
4

2 回答 2

1

似乎按 ESC 或 ENTER 在编程上与按 TAB 或 ALT 类似,因此按下这些键中的任何一个都会触发控件上的焦点边框。我的解决方案是手动关闭对话框,而不是使用默认的“OK”和“CANCEL”选项,这些选项由于某种原因触发了未来对话框中甚至尚未创建的焦点边框。

我在上面粘贴的最新代码是解决方案,作为最后一点,我应该指出,防止用户在对话框中按 ENTER 或 ESC 也很重要(即使现在允许他们点击它,他们也可能会这样做),所以我使用PreTranslateMessage. 您可以完全阻止原始问题的发生,同时仍然允许在使用此方法时使用 ESCAPE 和 ENTER,但它并不像包含CSplashDlg::EndDialog(1);在 PreTranslateMessage 调用中那么简单(我尝试过,但失败了)。

在我的 CSplashDlg 类定义中:

virtual BOOL PreTranslateMessage(MSG* pMsg);

我的功能如下所示:

BOOL CSplashDlg::PreTranslateMessage(MSG* pMsg) {
    if ( pMsg->message == WM_KEYDOWN ) {
        if ( pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN ) {
            pMsg->wParam = NULL;
            //return MAKELONG(0,DC_HASDEFID);
        }
    }
    return CDialog::PreTranslateMessage(pMsg);
}
于 2013-02-21T22:51:30.967 回答
0

在 OnInitDialog() 中的主对话框(不是飞溅)中,return FALSE;作为最后一条语句

于 2013-02-21T04:18:29.527 回答