stoicfury
stoicfury

Reputation: 128

Adding another VC++ Dialog causes the second one to have focus dotted rectangle around controls?

I made a Visual Studio 2012 (Professional) project that behaves unexpectedly. When I have just one dialog, no focus rectangles appear (dotted border) on controls when I use them, except after I first press TAB or ALT. When I tried to load another dialog prior to the primary one (as a splash screen), the focus dotted borders do appear on the main (second) dialog, they are already shown on the first item when the window loads. Why is this so and how do I prevent this from happening?

enter image description here

My only guess is that pressing ENTER or ESC causes the same kind of behavior as pressing TAB or ALT, and I always see the effects because the user has to press ENTER or ESC to close the splash screen. One would think there was a way to remove focus from a control, but that doesn't seem easy to do. I can easily set the focus to a control, but not just remove it in general.

For those interested in sample code:


I could show the my entire project's code but it'd be easier to test it yourself honestly. Create a new VC++ project > MFC Application, set as "Dialog based", Finish. In the Resource View, right click Dialog and "Insert Dialog". Make it something recognizably different than the main window and add least one control that can take focus. Finally, near the top of your primary .cpp file, you will find the text "// The one and only"... Under that is a line that declares the primary application object. Create a new dialog class beneath that line (for the "splash screen", you can see mine below*), and then within your primary application's InitInstance(), insert code to load the splash screen just above the part that looks something like this:

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

The code I used to show the splash screen is:

CSplashDlg dlgSplash;
dlgSplash.DoModal();

*My code for the splash dialog:

Update: I changed my code to allow clicking the dialog first instead of pressing enter (in fact, I will at some point override pretranslatemsg() and catch ESC and ENTER. Here is my lastest code:

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);
}

Upvotes: 0

Views: 648

Answers (2)

stoicfury
stoicfury

Reputation: 128

It seems that pressing ESC or ENTER is programmatically similar to pressing TAB or ALT, such that hitting any of those keys triggers the focus borders on controls. My solution was to close the dialog manually, rather than using the default "OK" and "CANCEL" options which for some reason triggered the focus borders in the future dialog that hadn't even been created yet.

The latest code I pasted above is the solution, and as final note I should point out it's also important to prevent the user from pressing ENTER or ESC at the dialog anyways (they might do so even though they are allowed to click it now) , so I catch those keypresses using PreTranslateMessage. You could probably prevent the original problem from occurring at all while still allowing the use of ESCAPE and ENTER while using this method, but it is not as simple as including CSplashDlg::EndDialog(1); in the PreTranslateMessage call (I tried that and it failed).

In my CSplashDlg class definition:

virtual BOOL PreTranslateMessage(MSG* pMsg);

And my function looks like this:

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);
}

Upvotes: 1

cha
cha

Reputation: 10411

In your main dialog (not splash) in the OnInitDialog() put return FALSE; as a last statement

Upvotes: 0

Related Questions