Dave
Dave

Reputation: 81

MFC Have enter key act as "apply" button

In a certain dialog I would like when the user presses the enter key for it to act as an "apply" button. So far I have at least been able to make the dialog not close upon pressing enter by overriding CWnd::PreTranslateMessage, so currently it just does nothing and I'm not sure how to send apply command from there.

Upvotes: 3

Views: 4639

Answers (5)

IInspectable
IInspectable

Reputation: 51511

As Mark pointed out above the dialog manager already has all the logic built in to handle the Enter key by invoking the command associated with the default button. You can statically assign the BS_DEFPUSHBUTTON style or handle the DM_GETDEFID message.

The former is trivially easy and the latter is fairly simple to implement. Make sure you set the Default Button property to False for all buttons on your dialog. Now add a message handler for the DM_GETDEFID message. There is no dedicated macro for this message so you have to use the generic handler:

BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
    ...
    ON_MESSAGE(DM_GETDEFID, OnGetDefId)
END_MESSAGE_MAP()

The message handler is equally simple and uses the default message handler signature:

LRESULT CMyDialog::OnGetDefId(WPARAM wParam, LPARAM lParam)
{
    return MAKELRESULT(ID_APPLY, DC_HASDEFID);
}

The message handler must return a value whose high-order word contains DC_HASDEFID and the low-order word contains the control ID.

If you navigate over the controls of the dialog you will see that the Apply button has the typical default button visual cue while focus is not on another command button. Pressing Enter while a non-button control has the input focus invokes the default button's command handler. No additional code required.

Upvotes: 2

Mark Ransom
Mark Ransom

Reputation: 308520

Every dialog should have one and only one button with the BS_DEFPUSHBUTTON style, which indicates to the dialog that this is the button to activate with the Enter key. Usually this is the OK button, but you can make it the Apply button if you want to.

Upvotes: 4

rrirower
rrirower

Reputation: 4590

If your intent is to handle the Enter key without dismissing the dialog, you may be going about it incorrectly. Please take a look at this MSDN article. While using PreTranslateMessage should work, it is not the best way to handle these types of events.

Upvotes: 1

HVar
HVar

Reputation: 140

Another way to overwrite the message.

BOOL CMyDialog::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN)
    {       
        switch (pMsg->wParam)
        {   
        case VK_RETURN:
            {
               UINT nID = ::GetDlgCtrlID(pMsg->hwnd);       

                if (nID == ID_APPLY)
                { 
                   //DO YOUR STUFF HERE
                }        
            }
            break;
        default:
            break;
        }
    }
    return CDialog::PreTranslateMessage(pMsg); 
}

Also, you don't need to use PreTranslateMessage if you are using ::OnKeyDown

Upvotes: 0

The Forest And The Trees
The Forest And The Trees

Reputation: 1866

You'll need to handle the OnKeyDown message, and handle the VK_RETURN character inside that function.

void MyCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
    if(nChar == VK_RETURN)  
    {       
        // Do Stuff 
        return; 
    }   

    CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

Upvotes: 0

Related Questions