How to use arrow keys in derived CMFCPropertyGridCtrl in a CDiaogEx?

ChuckieAJ 411 Reputation points
2026-07-04T16:03:05.16+00:00

I am using a CMFCPropertyGridCtrl in my CDialogEx and whilst I cab tab to the property grid I can't use arrow keys to navigate the properties. This means the user is forced to click into each control.

What would cause this behaviour and how can I fix it?

Windows development | Windows API - Win32

Answer accepted by question author
Taki Ly (WICLOUD CORPORATION) 5,300 Reputation points Microsoft External Staff Moderator
2026-07-06T06:27:49.9333333+00:00

Hello @ChuckieAJ ,

When a user clicks or tabs into a property's value field, the grid creates an in-place active inline editor (such as a text box or combo box). Since this internal control captures keyboard inputs for text traversal, the arrow keys will move the text cursor left, right, up, or down within the text itself. Consequently, these keys are consumed and cannot be used to navigate between different grid rows.

From a standard Windows UX perspective, it is generally recommended to stick to the default behavior. Users can simply press Enter (to commit changes) or Esc (to cancel their input) to exit the edit mode. Once exited, the grid regains focus, and the Up/Down arrow keys will navigate through the property rows as expected.

If your project requirements specifically dictate that the arrow keys should move to the next/previous property seamlessly, even while the user is actively typing, you could consider a workaround.

You can accomplish this by deriving a custom class from CMFCPropertyGridCtrl and overriding its PreTranslateMessage function. This approach intercepts the arrow key presses, manually ends the edit session, and forwards the navigation message back to the grid.

Below is a minimal code snippet to demonstrate this approach:

BOOL CMyPropertyGridCtrl::PreTranslateMessage(MSG* pMsg)
{
    // Intercept Up / Down arrow keys
    if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN))
    {
        CMFCPropertyGridProperty* pActiveProp = GetCurSel();
        // Check if there is an active property and it is currently being edited
        if (pActiveProp != nullptr && pActiveProp->IsInPlaceEditing())
        {
            // 1. Force the grid to end the edit mode.
            // Pass TRUE to save the current text input, or FALSE to discard it.
            this->EndEditItem(TRUE);
            // 2. Forward the arrow key message to the property grid itself 
            // so it can handle the row up/down navigation natively.
            ::SendMessage(this->GetSafeHwnd(), WM_KEYDOWN, pMsg->wParam, pMsg->lParam);
            // 3. Mark the message as handled so it doesn't reach the inner edit control.
            return TRUE; 
        }
    }
    // Fall back to default message processing
    return CMFCPropertyGridCtrl::PreTranslateMessage(pMsg);
}

For further reading, you can refer to the official Microsoft documentations on the methods and classes used in this workaround:

Hopefully, this provides you with enough information to decide which approach is best for your application's user experience. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guide for your confirmation.

Thank you.

Was this answer helpful?

1 person found this answer helpful.
0 comments No comments

0 additional answers

Sort by: Newest

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.